diff --git a/src/console.c b/src/console.c
index 1ac1810866c6ad5ef6c3b9a29d6ddc3e706ac04d..10b569daa4182f9a680dc36f9e7f04f890a403e5 100644
--- a/src/console.c
+++ b/src/console.c
@@ -1267,7 +1267,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))
 	{
 #if (defined (_WINDOWS)) || (defined (__OS2__) && !defined (HAVE_SDL))
 		patch_t *con_backpic = W_CachePatchName("CONSBACK", PU_PATCH);
@@ -1584,13 +1584,11 @@ void CON_Drawer(void)
 	if (!con_started || !graphics_started)
 		return;
 
-	if (needpatchrecache)
-		R_ReloadHUDGraphics();
-
 	if (con_recalc)
 	{
 		CON_RecalcSize();
-		CON_ClearHUD();
+		if (con_curlines <= 0)
+			CON_ClearHUD();
 	}
 
 	if (con_curlines > 0)
diff --git a/src/d_main.c b/src/d_main.c
index c84d6e7a2a030d51d3f52c3650df6af09d55e935..4b68f73ba494fbad0060aeaca734de04cdc428ee 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -117,6 +117,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;
@@ -227,7 +229,7 @@ gamestate_t wipegamestate = GS_LEVEL;
 
 static void D_Display(void)
 {
-	INT32 setrenderstillneeded = setrenderneeded;
+	INT32 setrenderstillneeded = 0;
 	boolean forcerefresh = false;
 	static boolean wipe = false;
 	INT32 wipedefindex = 0;
@@ -242,9 +244,16 @@ static void D_Display(void)
 	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()
@@ -256,6 +265,8 @@ static void D_Display(void)
 		forcerefresh = true; // force background redraw
 	}
 
+	D_CheckRendererState();
+
 	// draw buffered stuff to screen
 	// Used only by linux GGI version
 	I_UpdateNoBlit();
@@ -495,16 +506,24 @@ static void D_Display(void)
 		I_FinishUpdate(); // page flip or blit buffer
 	}
 
-	// in the occasion no functions
-	// that require patches to be cached
-	// have been called.
-	if (needpatchrecache)
-		R_ReloadHUDGraphics();
-
 	needpatchflush = false;
 	needpatchrecache = false;
 }
 
+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
 // =========================================================================
@@ -1201,6 +1220,21 @@ void D_SRB2Main(void)
 
 	// set user default mode or mode set at cmdline
 	SCR_CheckDefaultMode();
+	// renderer needs to change?
+	// ok cool please just change it
+	// exactly right now please.
+	if ((setrenderneeded != 0) && (setrenderneeded != rendermode))
+	{
+		needpatchflush = true;
+		needpatchrecache = true;
+		VID_CheckRenderer();
+		// set cv_renderer back
+		if (setrenderneeded == render_soft)
+			CV_StealthSetValue(&cv_renderer, 1);
+		else if (setrenderneeded == render_opengl)
+			CV_StealthSetValue(&cv_renderer, 2);
+	}
+	D_CheckRendererState();
 
 	wipegamestate = gamestate;
 
diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c
index 0716a130f253f2adba25e84b9f5eae2a9a9aac18..7e9efd38b8ab34d7cfbaa01f188f0340b22d3050 100644
--- a/src/hardware/hw_cache.c
+++ b/src/hardware/hw_cache.c
@@ -712,9 +712,6 @@ void HWR_GetFlat(lumpnum_t flatlumpnum)
 {
 	GLMipmap_t *grmip;
 
-	if (needpatchflush)
-		Z_FlushCachedPatches();
-
 	grmip = &HWR_GetCachedGLPatch(flatlumpnum)->mipmap;
 
 	if (!grmip->downloaded && !grmip->grInfo.data)
@@ -751,9 +748,6 @@ static void HWR_LoadMappedPatch(GLMipmap_t *grmip, GLPatch_t *gpatch)
 // -----------------+
 void HWR_GetPatch(GLPatch_t *gpatch)
 {
-	if (needpatchflush)
-		Z_FlushCachedPatches();
-
 	// is it in hardware cache
 	if (!gpatch->mipmap.downloaded && !gpatch->mipmap.grInfo.data)
 	{
@@ -781,9 +775,6 @@ void HWR_GetMappedPatch(GLPatch_t *gpatch, const UINT8 *colormap)
 {
 	GLMipmap_t *grmip, *newmip;
 
-	if (needpatchflush)
-		Z_FlushCachedPatches();
-
 	if (colormap == colormaps || colormap == NULL)
 	{
 		// Load the default (green) color in doom cache (temporary?) AND hardware cache
@@ -909,9 +900,6 @@ GLPatch_t *HWR_GetPic(lumpnum_t lumpnum)
 {
 	GLPatch_t *grpatch;
 
-	if (needpatchflush)
-		Z_FlushCachedPatches();
-
 	grpatch = HWR_GetCachedGLPatch(lumpnum);
 
 	if (!grpatch->mipmap.downloaded && !grpatch->mipmap.grInfo.data)
@@ -1109,9 +1097,6 @@ void HWR_GetFadeMask(lumpnum_t fademasklumpnum)
 {
 	GLMipmap_t *grmip;
 
-	if (needpatchflush)
-		Z_FlushCachedPatches();
-
 	grmip = &HWR_GetCachedGLPatch(fademasklumpnum)->mipmap;
 
 	if (!grmip->downloaded && !grmip->grInfo.data)
diff --git a/src/hu_stuff.c b/src/hu_stuff.c
index 2451f5c4d8bd2a8137d0f818d58d23701cca5239..a9a2b7504c07287ab40efae2c01d4e23ae88fc5f 100644
--- a/src/hu_stuff.c
+++ b/src/hu_stuff.c
@@ -1993,9 +1993,6 @@ static void HU_DrawDemoInfo(void)
 //
 void HU_Drawer(void)
 {
-	if (needpatchrecache)
-		R_ReloadHUDGraphics();
-
 #ifndef NONET
 	// draw chat string plus cursor
 	if (chat_on)
diff --git a/src/m_menu.c b/src/m_menu.c
index 9a55ced4b367eb46890973d55f545f03383545d2..ba3fb4c2d78a1de23df3af08d2f22207c1094fcf 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -2481,9 +2481,6 @@ void M_Drawer(void)
 	if (currentMenu == &MessageDef)
 		menuactive = true;
 
-	if (needpatchrecache)
-		R_ReloadHUDGraphics();
-
 	if (menuactive)
 	{
 		// now that's more readable with a faded background (yeah like Quake...)
diff --git a/src/p_setup.c b/src/p_setup.c
index 82b9eb691cffcf318d1836c42a6bf74a65028332..afd5ac06aaeb59aa6607956b187349e49ddb949b 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -3098,10 +3098,7 @@ boolean P_SetupLevel(boolean skipprecip)
 	// preload graphics
 #ifdef HWRENDER // not win32 only 19990829 by Kin
 	if (rendermode == render_opengl)
-	{
 		HWR_PrepLevelCache(numtextures);
-		//HWR_FreeColormaps();
-	}
 #endif
 
 	P_MapEnd();
diff --git a/src/r_main.c b/src/r_main.c
index d7196427c037614ae2f3d44d25a49be41beca22b..2cca68ff0c9f2f0808e6a197571d31d562c7056c 100644
--- a/src/r_main.c
+++ b/src/r_main.c
@@ -1353,7 +1353,7 @@ void R_InitHardwareMode(void)
 
 void R_ReloadHUDGraphics(void)
 {
-	Z_FlushCachedPatches();
+	CONS_Debug(DBG_RENDER, "R_ReloadHUDGraphics()...\n");
 	ST_LoadGraphics();
 	HU_LoadGraphics();
 	ST_ReloadSkinFaceGraphics();
diff --git a/src/st_stuff.c b/src/st_stuff.c
index 11bb9875d2cba8f86ef2a01f951514843dbe0338..287aea134ba4e81bb5f50848696516d11990a9bb 100644
--- a/src/st_stuff.c
+++ b/src/st_stuff.c
@@ -1909,9 +1909,6 @@ static void ST_overlayDrawer(void)
 
 void ST_Drawer(void)
 {
-	if (needpatchrecache)
-		R_ReloadHUDGraphics();
-
 #ifdef SEENAMES
 	if (cv_seenames.value && cv_allowseenames.value && displayplayer == consoleplayer && seenplayer && seenplayer->mo)
 	{
diff --git a/src/w_wad.c b/src/w_wad.c
index 96381635ae64ecd52393a34b015c67685e7641d2..2a98ba0a79b784f987da71a26d1c50f92d1821c5 100644
--- a/src/w_wad.c
+++ b/src/w_wad.c
@@ -830,10 +830,10 @@ void W_UnloadWadFile(UINT16 num)
 	lumpcache = delwad->lumpcache;
 	numwadfiles--;
 #ifdef HWRENDER
-	if (rendermode != render_soft && rendermode != render_none)
+	if (rendermode == render_opengl)
 	{
-		HWR_FreeTextureCache();
 		HWR_FreeColormaps();
+		HWR_FreeTextureCache();
 	}
 	M_AATreeFree(delwad->hwrcache);
 #endif
@@ -1512,9 +1512,6 @@ static inline void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag)
 {
 	GLPatch_t *grPatch;
 
-	if (needpatchflush)
-		Z_FlushCachedPatches();
-
 	if (rendermode == render_soft || rendermode == render_none)
 		return W_CacheLumpNumPwad(wad, lump, tag);
 
diff --git a/src/y_inter.c b/src/y_inter.c
index ab27a00fe210777f40b785593b1652fe75dc7190..080e380d1dd2b3ada296f4225fe51850eaa4b507 100644
--- a/src/y_inter.c
+++ b/src/y_inter.c
@@ -192,7 +192,6 @@ void Y_IntermissionDrawer(void)
 	if (needpatchrecache)
 	{
 		Y_CleanupData();
-		R_ReloadHUDGraphics();
 		safetorender = false;
 	}
 
diff --git a/src/z_zone.c b/src/z_zone.c
index add18b5682318aa3e1aac529e4e766da517574eb..a0e34ec352802d7128713bd305ecf5ee44449eed 100644
--- a/src/z_zone.c
+++ b/src/z_zone.c
@@ -415,20 +415,20 @@ void Z_FreeTags(INT32 lowtag, INT32 hightag)
 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)
 {
-	if (needpatchflush)
-	{
-		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);
-	}
-	needpatchflush = false;
+	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);
 }
 
 //