diff --git a/src/android/i_video.c b/src/android/i_video.c index 1909cd71a..a38078a5d 100644 --- a/src/android/i_video.c +++ b/src/android/i_video.c @@ -9,6 +9,7 @@ #include "utils/Log.h" rendermode_t rendermode = render_soft; +rendermode_t chosenrendermode = render_none; boolean highcolor = false; @@ -52,8 +53,15 @@ INT32 VID_SetMode(INT32 modenum) return 0; } -void VID_CheckRenderer(void) {} -void VID_CheckGLLoaded(rendermode_t oldrender) {} +boolean VID_CheckRenderer(void) +{ + return false; +} + +void VID_CheckGLLoaded(rendermode_t oldrender) +{ + (void)oldrender; +} const char *VID_GetModeName(INT32 modenum) { diff --git a/src/console.c b/src/console.c index e9c0138d7..630feb2aa 100644 --- a/src/console.c +++ b/src/console.c @@ -45,7 +45,8 @@ #define MAXHUDLINES 20 static boolean con_started = false; // console has been initialised - boolean con_startup = false; // true at game startup, screen need refreshing + boolean con_startup = false; // true at game startup + boolean con_refresh = false; // screen needs refreshing static boolean con_forcepic = true; // at startup toggle console translucency when first off boolean con_recalc; // set true when screen size has changed @@ -406,7 +407,8 @@ void CON_Init(void) if (!dedicated) { con_started = true; - con_startup = true; // need explicit screen refresh until we are in Doom loop + con_startup = true; + con_refresh = true; // needs explicit screen refresh until we are in the main game loop consoletoggle = false; CV_RegisterVar(&cons_msgtimeout); CV_RegisterVar(&cons_hudlines); @@ -419,7 +421,8 @@ void CON_Init(void) else { con_started = true; - con_startup = false; // need explicit screen refresh until we are in Doom loop + con_startup = false; + con_refresh = false; // disable explicit screen refresh consoletoggle = true; } } @@ -1293,16 +1296,19 @@ void CONS_Printf(const char *fmt, ...) con_scrollup = 0; // if not in display loop, force screen update - if (con_startup && (!setrenderneeded)) + if (con_refresh) { -#ifdef _WINDOWS - patch_t *con_backpic = W_CachePatchName("CONSBACK", PU_PATCH); +#if defined(_WINDOWS) + if (con_startup) + { + patch_t *con_backpic = W_CachePatchName("CONSBACK", PU_PATCH); - // Jimita: CON_DrawBackpic just called V_DrawScaledPatch - V_DrawScaledPatch(0, 0, 0, con_backpic); + // Jimita: CON_DrawBackpic just called V_DrawScaledPatch + V_DrawScaledPatch(0, 0, 0, con_backpic); - W_UnlockCachedPatch(con_backpic); - I_LoadingScreen(txt); // Win32/OS2 only + W_UnlockCachedPatch(con_backpic); + I_LoadingScreen(txt); // Win32/OS2 only + } #else // here we display the console text CON_Drawer(); @@ -1369,7 +1375,7 @@ void CONS_Debug(INT32 debugflags, const char *fmt, ...) // void CONS_Error(const char *msg) { -#ifdef RPC_NO_WINDOWS_H +#if defined(RPC_NO_WINDOWS_H) && defined(_WINDOWS) if (!graphics_started) { MessageBoxA(vid.WndParent, msg, "SRB2 Warning", MB_OK); diff --git a/src/console.h b/src/console.h index 2be92d62b..6f38ca8d0 100644 --- a/src/console.h +++ b/src/console.h @@ -20,8 +20,12 @@ boolean CON_Responder(event_t *ev); // set true when screen size has changed, to adapt console extern boolean con_recalc; +// console being displayed at game startup extern boolean con_startup; +// needs explicit screen refresh until we are in the main game loop +extern boolean con_refresh; + // top clip value for view render: do not draw part of view hidden by console extern INT32 con_clipviewtop; diff --git a/src/d_main.c b/src/d_main.c index ee3ce699c..6144abd85 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -220,7 +220,6 @@ INT16 wipetypepost = -1; static void D_Display(void) { - INT32 setrenderstillneeded = 0; boolean forcerefresh = false; static boolean wipe = false; INT32 wipedefindex = 0; @@ -245,36 +244,21 @@ static void D_Display(void) // modes (resolution) are called. // 4. The frame is ready to be drawn! - // stop movie if needs to change renderer - if (setrenderneeded && (moviemode == MM_APNG)) - M_StopMovie(); - - // check for change of renderer or screen size (video mode) + // 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) - { + // Recalc the screen + if (vid.recalc) SCR_Recalc(); // NOTE! setsizeneeded is set by SCR_Recalc() -#ifdef HWRENDER - // Shoot! The screen texture was flushed! - if ((rendermode == render_opengl) && (gamestate == GS_INTERMISSION)) - usebuffer = false; -#endif - } + // View morph if (rendermode == render_soft && !splitscreen) R_CheckViewMorph(); - // change the view size if needed - if (setsizeneeded || setrenderstillneeded) + // Change the view size if needed + // Set by changing video mode or renderer + if (setsizeneeded) { R_ExecuteSetViewSize(); forcerefresh = true; // force background redraw @@ -697,6 +681,7 @@ void D_SRB2Loop(void) oldentertics = I_GetTime(); // end of loading screen: CONS_Printf() will no more call FinishUpdate() + con_refresh = false; con_startup = false; // make sure to do a d_display to init mode _before_ load a level @@ -1402,14 +1387,20 @@ void D_SRB2Main(void) // set user default mode or mode set at cmdline SCR_CheckDefaultMode(); - // Lactozilla: Does the render mode need to change? - if ((setrenderneeded != 0) && (setrenderneeded != rendermode)) + // Lactozilla: Check if the render mode needs to change. + if (setrenderneeded) { CONS_Printf(M_GetText("Switching the renderer...\n")); + // Switch the renderer in the interface + if (VID_CheckRenderer()) + con_refresh = true; // Allow explicit screen refresh again + // Set cv_renderer to the new render mode - VID_CheckRenderer(); - SCR_ChangeRendererCVars(rendermode); + CV_StealthSetValue(&cv_renderer, rendermode); +#ifdef HWRENDER + CV_StealthSetValue(&cv_newrenderer, rendermode); +#endif } wipegamestate = gamestate; diff --git a/src/dummy/i_video.c b/src/dummy/i_video.c index 56ead3672..38a67ef37 100644 --- a/src/dummy/i_video.c +++ b/src/dummy/i_video.c @@ -3,6 +3,7 @@ #include "../i_video.h" rendermode_t rendermode = render_none; +rendermode_t chosenrendermode = render_none; boolean highcolor = false; @@ -40,8 +41,15 @@ INT32 VID_SetMode(INT32 modenum) return 0; } -void VID_CheckRenderer(void) {} -void VID_CheckGLLoaded(rendermode_t oldrender) {} +boolean VID_CheckRenderer(void) +{ + return false; +} + +void VID_CheckGLLoaded(rendermode_t oldrender) +{ + (void)oldrender; +} const char *VID_GetModeName(INT32 modenum) { diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index a26721169..901c0184a 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -585,23 +585,27 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm static size_t gl_numtextures = 0; // Texture count static GLMapTexture_t *gl_textures; // For all textures static GLMapTexture_t *gl_flats; // For all (texture) flats, as normal flats don't need to be cached - -void HWR_InitTextureCache(void) -{ - gl_textures = NULL; - gl_flats = NULL; -} +boolean gl_maptexturesloaded = false; void HWR_FreeTexture(patch_t *patch) { + if (!patch) + return; + if (patch->hardware) { GLPatch_t *grPatch = patch->hardware; HWR_FreeTextureColormaps(patch); - if (grPatch->mipmap && (rendermode == render_opengl)) - HWD.pfnDeleteTexture(grPatch->mipmap); + if (grPatch->mipmap) + { + if (vid.glstate == VID_GL_LIBRARY_LOADED) + HWD.pfnDeleteTexture(grPatch->mipmap); + if (grPatch->mipmap->data) + Z_Free(grPatch->mipmap->data); + Z_Free(grPatch->mipmap); + } Z_Free(patch->hardware); } @@ -609,7 +613,7 @@ void HWR_FreeTexture(patch_t *patch) patch->hardware = NULL; } -// Called by HWR_FreeTextureCache. +// Called by HWR_FreePatchCache. void HWR_FreeTextureColormaps(patch_t *patch) { GLPatch_t *pat; @@ -653,10 +657,22 @@ void HWR_FreeTextureColormaps(patch_t *patch) } } -void HWR_FreeMipmapCache(void) +static void HWR_FreePatchCache(boolean freeall) { INT32 i; + for (i = 0; i < numwadfiles; i++) + { + INT32 j = 0; + for (; j < wadfiles[i]->numlumps; j++) + (freeall ? HWR_FreeTexture : HWR_FreeTextureColormaps)(wadfiles[i]->patchcache[j]); + } +} + +void HWR_ClearAllTextures(void) +{ + HWR_FreeMapTextures(); + // free references to the textures HWD.pfnClearMipMapCache(); @@ -666,19 +682,38 @@ void HWR_FreeMipmapCache(void) Z_FreeTag(PU_HWRCACHE_UNLOCKED); // Alam: free the Z_Blocks before freeing it's users - // free all patch colormaps after each level: must be done after ClearMipMapCache! - for (i = 0; i < numwadfiles; i++) - { - INT32 j = 0; - for (; j < wadfiles[i]->numlumps; j++) - HWR_FreeTextureColormaps(wadfiles[i]->patchcache[j]); - } + HWR_FreePatchCache(true); } -void HWR_FreeTextureCache(void) +// free all patch colormaps after each level: must be done after ClearMipMapCache! +void HWR_FreeColormapCache(void) { - // free references to the textures - HWR_FreeMipmapCache(); + HWR_FreePatchCache(false); +} + +void HWR_InitMapTextures(void) +{ + gl_textures = NULL; + gl_flats = NULL; + gl_maptexturesloaded = false; +} + +static void FreeMapTexture(GLMapTexture_t *tex) +{ + HWD.pfnDeleteTexture(&tex->mipmap); + if (tex->mipmap.data) + Z_Free(tex->mipmap.data); +} + +void HWR_FreeMapTextures(void) +{ + size_t i; + + for (i = 0; i < gl_numtextures; i++) + { + FreeMapTexture(&gl_textures[i]); + FreeMapTexture(&gl_flats[i]); + } // now the heap don't have any 'user' pointing to our // texturecache info, we can free it @@ -689,12 +724,13 @@ void HWR_FreeTextureCache(void) gl_textures = NULL; gl_flats = NULL; gl_numtextures = 0; + gl_maptexturesloaded = false; } -void HWR_LoadTextures(size_t pnumtextures) +void HWR_LoadMapTextures(size_t pnumtextures) { // we must free it since numtextures changed - HWR_FreeTextureCache(); + HWR_FreeMapTextures(); // Why not Z_Malloc? gl_numtextures = pnumtextures; @@ -704,7 +740,9 @@ void HWR_LoadTextures(size_t pnumtextures) // Doesn't tell you which it _is_, but hopefully // should never ever happen (right?!) if ((gl_textures == NULL) || (gl_flats == NULL)) - I_Error("HWR_LoadTextures: ran out of memory for OpenGL textures. Sad!"); + I_Error("HWR_LoadMapTextures: ran out of memory for OpenGL textures. Sad!"); + + gl_maptexturesloaded = true; } void HWR_SetPalette(RGBA_t *palette) @@ -814,10 +852,13 @@ static void HWR_CacheTextureAsFlat(GLMipmap_t *grMipmap, INT32 texturenum) void HWR_LiterallyGetFlat(lumpnum_t flatlumpnum) { GLMipmap_t *grmip; + patch_t *patch; + if (flatlumpnum == LUMPERROR) return; - grmip = ((GLPatch_t *)HWR_GetCachedGLPatch(flatlumpnum)->hardware)->mipmap; + patch = HWR_GetCachedGLPatch(flatlumpnum); + grmip = ((GLPatch_t *)Patch_AllocateHardwarePatch(patch))->mipmap; if (!grmip->downloaded && !grmip->data) HWR_CacheFlat(grmip, flatlumpnum); @@ -933,7 +974,7 @@ void HWR_GetMappedPatch(patch_t *patch, const UINT8 *colormap) //BP: WARNING: don't free it manually without clearing the cache of harware renderer // (it have a liste of mipmap) - // this malloc is cleared in HWR_FreeTextureCache + // this malloc is cleared in HWR_FreeColormapCache // (...) unfortunately z_malloc fragment alot the memory :(so malloc is better newMipmap = calloc(1, sizeof (*newMipmap)); if (newMipmap == NULL) @@ -1190,7 +1231,8 @@ static void HWR_CacheFadeMask(GLMipmap_t *grMipmap, lumpnum_t fademasklumpnum) void HWR_GetFadeMask(lumpnum_t fademasklumpnum) { - GLMipmap_t *grmip = ((GLPatch_t *)HWR_GetCachedGLPatch(fademasklumpnum)->hardware)->mipmap; + patch_t *patch = HWR_GetCachedGLPatch(fademasklumpnum); + GLMipmap_t *grmip = ((GLPatch_t *)Patch_AllocateHardwarePatch(patch))->mipmap; if (!grmip->downloaded && !grmip->data) HWR_CacheFadeMask(grmip, fademasklumpnum); diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index 94c553535..b16a0f231 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -90,9 +90,11 @@ void HWR_FreeExtraSubsectors(void); // -------- // hw_cache.c // -------- -void HWR_InitTextureCache(void); -void HWR_FreeTextureCache(void); -void HWR_FreeMipmapCache(void); +void HWR_InitMapTextures(void); +void HWR_LoadMapTextures(size_t pnumtextures); +void HWR_FreeMapTextures(void); + +extern boolean gl_maptexturesloaded; patch_t *HWR_GetCachedGLPatchPwad(UINT16 wad, UINT16 lump); patch_t *HWR_GetCachedGLPatch(lumpnum_t lumpnum); @@ -108,6 +110,8 @@ void HWR_LiterallyGetFlat(lumpnum_t flatlumpnum); void HWR_FreeTexture(patch_t *patch); void HWR_FreeTextureColormaps(patch_t *patch); +void HWR_ClearAllTextures(void); +void HWR_FreeColormapCache(void); void HWR_UnlockCachedPatch(GLPatch_t *gpatch); void HWR_SetPalette(RGBA_t *palette); diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 7ba7f911c..e9d52c791 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5930,7 +5930,7 @@ void HWR_Startup(void) HWR_InitPolyPool(); HWR_AddSessionCommands(); - HWR_InitTextureCache(); + HWR_InitMapTextures(); HWR_InitModels(); #ifdef ALAM_LIGHTING HWR_InitLight(); @@ -5954,9 +5954,20 @@ void HWR_Startup(void) // -------------------------------------------------------------------------- void HWR_Switch(void) { + // Add session commands + HWR_AddSessionCommands(); + // Set special states from CVARs HWD.pfnSetSpecialState(HWD_SET_TEXTUREFILTERMODE, cv_glfiltermode.value); HWD.pfnSetSpecialState(HWD_SET_TEXTUREANISOTROPICMODE, cv_glanisotropicmode.value); + + // Load textures + if (!gl_maptexturesloaded) + HWR_LoadMapTextures(numtextures); + + // Create plane polygons + if (gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction)) + HWR_LoadLevel(); } // -------------------------------------------------------------------------- @@ -5967,7 +5978,7 @@ void HWR_Shutdown(void) CONS_Printf("HWR_Shutdown()\n"); HWR_FreeExtraSubsectors(); HWR_FreePolyPool(); - HWR_FreeTextureCache(); + HWR_FreeMapTextures(); HWD.pfnFlushScreenTextures(); } diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 3bcef05de..780572a85 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -41,7 +41,6 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t scale, void HWR_MakePatch(const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap); void HWR_CreatePlanePolygons(INT32 bspnum); void HWR_CreateStaticLightmaps(INT32 bspnum); -void HWR_LoadTextures(size_t pnumtextures); void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color); void HWR_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT16 actualcolor, UINT8 strength); void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT32 actualcolor); // Lat: separate flags from color since color needs to be an uint to work right. diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index caef0a02d..057ef62c1 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1094,7 +1094,7 @@ static void HWR_GetBlendedTexture(patch_t *patch, patch_t *blendpatch, INT32 ski //BP: WARNING: don't free it manually without clearing the cache of harware renderer // (it have a liste of mipmap) - // this malloc is cleared in HWR_FreeTextureCache + // this malloc is cleared in HWR_FreeColormapCache // (...) unfortunately z_malloc fragment alot the memory :(so malloc is better newMipmap = calloc(1, sizeof (*newMipmap)); if (newMipmap == NULL) diff --git a/src/i_video.h b/src/i_video.h index 98ed7f38a..ab48881d4 100644 --- a/src/i_video.h +++ b/src/i_video.h @@ -36,10 +36,9 @@ typedef enum */ extern rendermode_t rendermode; -/** \brief OpenGL state - 0 = never loaded, 1 = loaded successfully, -1 = failed loading +/** \brief render mode set by command line arguments */ -extern INT32 vid_opengl_state; +extern rendermode_t chosenrendermode; /** \brief use highcolor modes if true */ @@ -90,8 +89,9 @@ INT32 VID_GetModeForSize(INT32 w, INT32 h); INT32 VID_SetMode(INT32 modenum); /** \brief Checks the render state + \return true if the renderer changed */ -void VID_CheckRenderer(void); +boolean VID_CheckRenderer(void); /** \brief Load OpenGL mode */ diff --git a/src/m_menu.c b/src/m_menu.c index 3d6b1c0fa..0e60dce0c 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -2149,15 +2149,22 @@ menu_t OP_PlaystyleDef = { static void M_VideoOptions(INT32 choice) { (void)choice; + + OP_VideoOptionsMenu[op_video_renderer].status = (IT_TRANSTEXT | IT_PAIR); + OP_VideoOptionsMenu[op_video_renderer].patch = "Renderer"; + OP_VideoOptionsMenu[op_video_renderer].text = "Software"; + #ifdef HWRENDER - if (vid_opengl_state == -1) + if (vid.glstate != VID_GL_LIBRARY_ERROR) { - OP_VideoOptionsMenu[op_video_renderer].status = (IT_TRANSTEXT | IT_PAIR); - OP_VideoOptionsMenu[op_video_renderer].patch = "Renderer"; - OP_VideoOptionsMenu[op_video_renderer].text = "Software"; + OP_VideoOptionsMenu[op_video_renderer].status = (IT_STRING | IT_CVAR); + OP_VideoOptionsMenu[op_video_renderer].patch = NULL; + OP_VideoOptionsMenu[op_video_renderer].text = "Renderer"; } + CV_StealthSetValue(&cv_newrenderer, cv_renderer.value); #endif + M_SetupNextMenu(&OP_VideoOptionsDef); } diff --git a/src/p_setup.c b/src/p_setup.c index ceb96df40..0105a06da 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4146,13 +4146,11 @@ boolean P_LoadLevel(boolean fromnetsave) #ifdef HWRENDER // not win32 only 19990829 by Kin // Lactozilla: 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 + HWR_FreeExtraSubsectors(); + + // Create plane polygons. if (rendermode == render_opengl) - HWR_SetupLevel(); + HWR_LoadLevel(); #endif // oh god I hope this helps @@ -4238,7 +4236,7 @@ boolean P_LoadLevel(boolean fromnetsave) } #ifdef HWRENDER -void HWR_SetupLevel(void) +void HWR_LoadLevel(void) { // Lactozilla (December 8, 2019) // Level setup used to free EVERY mipmap from memory. @@ -4249,7 +4247,7 @@ void HWR_SetupLevel(void) // when the texture list is loaded. // Sal: Unfortunately, NOT freeing them causes the dreaded Color Bug. - HWR_FreeMipmapCache(); + HWR_FreeColormapCache(); #ifdef ALAM_LIGHTING // BP: reset light between levels (we draw preview frame lights on current frame) diff --git a/src/p_setup.h b/src/p_setup.h index e7150c0ae..497870628 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -99,7 +99,7 @@ void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum); void P_RespawnThings(void); boolean P_LoadLevel(boolean fromnetsave); #ifdef HWRENDER -void HWR_SetupLevel(void); +void HWR_LoadLevel(void); #endif boolean P_AddWadFile(const char *wadfilename); boolean P_RunSOC(const char *socfilename); diff --git a/src/r_data.c b/src/r_data.c index 4b2ff7484..dc2c41150 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -33,7 +33,7 @@ #endif #ifdef HWRENDER -#include "hardware/hw_main.h" // HWR_LoadTextures +#include "hardware/hw_main.h" // HWR_LoadMapTextures #endif #if defined(_MSC_VER) @@ -1084,7 +1084,7 @@ void R_LoadTextures(void) #ifdef HWRENDER if (rendermode == render_opengl) - HWR_LoadTextures(numtextures); + HWR_LoadMapTextures(numtextures); #endif } diff --git a/src/r_main.c b/src/r_main.c index b70e6f25f..883ac0abf 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1560,18 +1560,6 @@ void R_RenderPlayerView(player_t *player) free(masks); } -// Lactozilla: Renderer switching -#ifdef HWRENDER -void R_InitHardwareMode(void) -{ - HWR_AddSessionCommands(); - HWR_Switch(); - HWR_LoadTextures(numtextures); - if (gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction)) - HWR_SetupLevel(); -} -#endif - // ========================================================================= // ENGINE COMMANDS & VARS // ========================================================================= diff --git a/src/r_main.h b/src/r_main.h index cc098462d..6c0aec3f5 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -112,9 +112,6 @@ extern consvar_t cv_tailspickup; // Called by startup code. void R_Init(void); -#ifdef HWRENDER -void R_InitHardwareMode(void); -#endif void R_CheckViewMorph(void); void R_ApplyViewMorph(void); diff --git a/src/screen.c b/src/screen.c index f5d19cada..d460e1f6d 100644 --- a/src/screen.c +++ b/src/screen.c @@ -28,6 +28,7 @@ #include "d_main.h" #include "d_clisrv.h" #include "f_finale.h" +#include "y_inter.h" // usebuffer #include "i_sound.h" // closed captions #include "s_sound.h" // ditto #include "g_game.h" // ditto @@ -63,7 +64,6 @@ 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_ActuallyChangeRenderer(void); CV_PossibleValue_t cv_renderer_t[] = { {1, "Software"}, #ifdef HWRENDER @@ -71,7 +71,7 @@ CV_PossibleValue_t cv_renderer_t[] = { #endif {0, NULL} }; -consvar_t cv_renderer = {"renderer", "Software", CV_SAVE|CV_NOLUA|CV_CALL, cv_renderer_t, SCR_ChangeRenderer, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_renderer = {"renderer", "Software", CV_SAVE|CV_NOLUA|CV_CALL, cv_renderer_t, SCR_SetTargetRenderer, 0, NULL, NULL, 0, 0, NULL}; static void SCR_ChangeFullscreen(void); @@ -202,11 +202,15 @@ void SCR_SetMode(void) // Lactozilla: Renderer switching if (setrenderneeded) { + // stop recording movies (APNG only) + if (setrenderneeded && (moviemode == MM_APNG)) + M_StopMovie(); + VID_CheckRenderer(); - if (!setmodeneeded) - VID_SetMode(vid.modenum); + vid.recalc = 1; } + // Set the video mode in the video interface. if (setmodeneeded) VID_SetMode(--setmodeneeded); @@ -276,34 +280,9 @@ void SCR_Startup(void) vid.modenum = 0; - vid.dupx = vid.width / BASEVIDWIDTH; - vid.dupy = vid.height / BASEVIDHEIGHT; - vid.dupx = vid.dupy = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); - vid.fdupx = FixedDiv(vid.width*FRACUNIT, BASEVIDWIDTH*FRACUNIT); - vid.fdupy = FixedDiv(vid.height*FRACUNIT, BASEVIDHEIGHT*FRACUNIT); - -#ifdef HWRENDER - if (rendermode != render_opengl && rendermode != render_none) // This was just placing it incorrectly at non aspect correct resolutions in opengl -#endif - vid.fdupx = vid.fdupy = (vid.fdupx < vid.fdupy ? vid.fdupx : vid.fdupy); - - vid.meddupx = (UINT8)(vid.dupx >> 1) + 1; - vid.meddupy = (UINT8)(vid.dupy >> 1) + 1; -#ifdef HWRENDER - vid.fmeddupx = vid.meddupx*FRACUNIT; - vid.fmeddupy = vid.meddupy*FRACUNIT; -#endif - - vid.smalldupx = (UINT8)(vid.dupx / 3) + 1; - vid.smalldupy = (UINT8)(vid.dupy / 3) + 1; -#ifdef HWRENDER - vid.fsmalldupx = vid.smalldupx*FRACUNIT; - vid.fsmalldupy = vid.smalldupy*FRACUNIT; -#endif - - vid.baseratio = FRACUNIT; - V_Init(); + V_Recalc(); + CV_RegisterVar(&cv_ticrate); CV_RegisterVar(&cv_constextsize); @@ -320,38 +299,7 @@ void SCR_Recalc(void) // bytes per pixel quick access scr_bpp = vid.bpp; - // scale 1,2,3 times in x and y the patches for the menus and overlays... - // calculated once and for all, used by routines in v_video.c - vid.dupx = vid.width / BASEVIDWIDTH; - vid.dupy = vid.height / BASEVIDHEIGHT; - vid.dupx = vid.dupy = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); - vid.fdupx = FixedDiv(vid.width*FRACUNIT, BASEVIDWIDTH*FRACUNIT); - vid.fdupy = FixedDiv(vid.height*FRACUNIT, BASEVIDHEIGHT*FRACUNIT); - -#ifdef HWRENDER - //if (rendermode != render_opengl && rendermode != render_none) // This was just placing it incorrectly at non aspect correct resolutions in opengl - // 13/11/18: - // The above is no longer necessary, since we want OpenGL to be just like software now - // -- Monster Iestyn -#endif - vid.fdupx = vid.fdupy = (vid.fdupx < vid.fdupy ? vid.fdupx : vid.fdupy); - - //vid.baseratio = FixedDiv(vid.height << FRACBITS, BASEVIDHEIGHT << FRACBITS); - vid.baseratio = FRACUNIT; - - vid.meddupx = (UINT8)(vid.dupx >> 1) + 1; - vid.meddupy = (UINT8)(vid.dupy >> 1) + 1; -#ifdef HWRENDER - vid.fmeddupx = vid.meddupx*FRACUNIT; - vid.fmeddupy = vid.meddupy*FRACUNIT; -#endif - - vid.smalldupx = (UINT8)(vid.dupx / 3) + 1; - vid.smalldupy = (UINT8)(vid.dupy / 3) + 1; -#ifdef HWRENDER - vid.fsmalldupx = vid.smalldupx*FRACUNIT; - vid.fsmalldupy = vid.smalldupy*FRACUNIT; -#endif + V_Recalc(); // toggle off (then back on) the automap because some screensize-dependent values will // be calculated next time the automap is activated. @@ -371,6 +319,12 @@ void SCR_Recalc(void) // vid.recalc lasts only for the next refresh... con_recalc = true; am_recalc = true; + +#ifdef HWRENDER + // Shoot! The screen texture was flushed! + if ((rendermode == render_opengl) && (gamestate == GS_INTERMISSION)) + usebuffer = false; +#endif } // Check for screen cmd-line parms: to force a resolution. @@ -408,7 +362,19 @@ void SCR_CheckDefaultMode(void) setmodeneeded = VID_GetModeForSize(cv_scr_width.value, cv_scr_height.value) + 1; } - SCR_ActuallyChangeRenderer(); + if (cv_renderer.value != (signed)rendermode) + { + if (chosenrendermode == render_none) // nothing set at command line + SCR_ChangeRenderer(); + else + { + // Set cv_renderer to the current render mode + CV_StealthSetValue(&cv_renderer, rendermode); +#ifdef HWRENDER + CV_StealthSetValue(&cv_newrenderer, rendermode); +#endif + } + } } // sets the modenum as the new default video mode to be saved in the config file @@ -438,67 +404,33 @@ void SCR_ChangeFullscreen(void) #endif } -static int target_renderer = 0; - -void SCR_ActuallyChangeRenderer(void) +void SCR_SetTargetRenderer(void) { - setrenderneeded = target_renderer; + if (!con_refresh) + SCR_ChangeRenderer(); +} + +void SCR_ChangeRenderer(void) +{ + if ((signed)rendermode == cv_renderer.value) + return; #ifdef HWRENDER - // Well, it didn't even load anyway. - if ((vid_opengl_state == -1) && (setrenderneeded == render_opengl)) + // Check if OpenGL loaded successfully (or wasn't disabled) before switching to it. + if ((vid.glstate == VID_GL_LIBRARY_ERROR) + && (cv_renderer.value == render_opengl)) { if (M_CheckParm("-nogl")) CONS_Alert(CONS_ERROR, "OpenGL rendering was disabled!\n"); else CONS_Alert(CONS_ERROR, "OpenGL never loaded\n"); - setrenderneeded = 0; return; } #endif - // setting the same renderer twice WILL crash your game, so let's not, please - if (rendermode == setrenderneeded) - setrenderneeded = 0; -} - -// Lactozilla: Renderer switching -void SCR_ChangeRenderer(void) -{ - setrenderneeded = 0; - - if (con_startup) - { - target_renderer = cv_renderer.value; -#ifdef HWRENDER - if (M_CheckParm("-opengl") && (vid_opengl_state == 1)) - target_renderer = rendermode = render_opengl; - else -#endif - if (M_CheckParm("-software")) - target_renderer = rendermode = render_soft; - // set cv_renderer back - SCR_ChangeRendererCVars(rendermode); - return; - } - - if (cv_renderer.value == 1) - target_renderer = render_soft; - else if (cv_renderer.value == 2) - target_renderer = render_opengl; - SCR_ActuallyChangeRenderer(); -} - -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); -#ifdef HWRENDER - CV_StealthSetValue(&cv_newrenderer, cv_renderer.value); -#endif + // Set the new render mode + setrenderneeded = cv_renderer.value; + con_refresh = false; } boolean SCR_IsAspectCorrect(INT32 width, INT32 height) diff --git a/src/screen.h b/src/screen.h index 91ec175f4..3f6c91d05 100644 --- a/src/screen.h +++ b/src/screen.h @@ -72,10 +72,16 @@ typedef struct viddef_s #ifdef HWRENDER INT32/*fixed_t*/ fsmalldupx, fsmalldupy; INT32/*fixed_t*/ fmeddupx, fmeddupy; + INT32 glstate; #endif } viddef_t; -#define VIDWIDTH vid.width -#define VIDHEIGHT vid.height + +enum +{ + VID_GL_LIBRARY_NOTLOADED = 0, + VID_GL_LIBRARY_LOADED = 1, + VID_GL_LIBRARY_ERROR = -1, +}; // internal additional info for vesa modes only typedef struct @@ -171,10 +177,10 @@ extern boolean R_SSE2; extern viddef_t vid; extern INT32 setmodeneeded; // mode number to set if needed, or 0 +extern UINT8 setrenderneeded; void SCR_ChangeRenderer(void); -void SCR_ChangeRendererCVars(INT32 mode); -extern UINT8 setrenderneeded; +void SCR_SetTargetRenderer(void); extern INT32 scr_bpp; extern UINT8 *scr_borderpatch; // patch used to fill the view borders @@ -188,17 +194,23 @@ extern consvar_t cv_newrenderer; // wait for page flipping to end or not extern consvar_t cv_vidwait; +// Initialize the screen +void SCR_Startup(void); + // Change video mode, only at the start of a refresh. void SCR_SetMode(void); + +// Set drawer functions for Software void SCR_SetDrawFuncs(void); + // Recalc screen size dependent stuff void SCR_Recalc(void); + // Check parms once at startup void SCR_CheckDefaultMode(void); -// Set the mode number which is saved in the config -void SCR_SetDefaultMode (void); -void SCR_Startup (void); +// Set the mode number which is saved in the config +void SCR_SetDefaultMode(void); FUNCMATH boolean SCR_IsAspectCorrect(INT32 width, INT32 height); diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 1bb48e468..3e31e4450 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -95,7 +95,7 @@ static INT32 numVidModes = -1; static char vidModeName[33][32]; // allow 33 different modes rendermode_t rendermode = render_soft; -static rendermode_t chosenrendermode = render_soft; // set by command line arguments +rendermode_t chosenrendermode = render_none; // set by command line arguments boolean highcolor = false; @@ -105,7 +105,6 @@ static consvar_t cv_stretch = {"stretch", "Off", CV_SAVE|CV_NOSHOWHELP, CV_OnOff static consvar_t cv_alwaysgrabmouse = {"alwaysgrabmouse", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; UINT8 graphics_started = 0; // Is used in console.c and screen.c -INT32 vid_opengl_state = 0; // To disable fullscreen at startup; is set in VID_PrepareModeList boolean allow_fullscreen = false; @@ -1443,7 +1442,8 @@ static SDL_bool Impl_CreateContext(void) { // Renderer-specific stuff #ifdef HWRENDER - if ((rendermode == render_opengl) && (vid_opengl_state != -1)) + if ((rendermode == render_opengl) + && (vid.glstate != VID_GL_LIBRARY_ERROR)) { if (!sdlglcontext) sdlglcontext = SDL_GL_CreateContext(window); @@ -1479,30 +1479,29 @@ static SDL_bool Impl_CreateContext(void) void VID_CheckGLLoaded(rendermode_t oldrender) { #ifdef HWRENDER - if (vid_opengl_state == -1) // Well, it didn't work the first time anyway. + if (vid.glstate == VID_GL_LIBRARY_ERROR) // Well, it didn't work the first time anyway. { CONS_Alert(CONS_ERROR, "OpenGL never loaded\n"); rendermode = oldrender; if (chosenrendermode == render_opengl) // fallback to software rendermode = render_soft; - if (setrenderneeded) - { - CV_StealthSetValue(&cv_renderer, oldrender); - CV_StealthSetValue(&cv_newrenderer, oldrender); - setrenderneeded = 0; - } + + CV_StealthSetValue(&cv_renderer, oldrender); + CV_StealthSetValue(&cv_newrenderer, oldrender); } #endif } -void VID_CheckRenderer(void) +boolean VID_CheckRenderer(void) { boolean rendererchanged = false; boolean contextcreated = false; +#ifdef HWRENDER rendermode_t oldrenderer = rendermode; +#endif if (dedicated) - return; + return false; if (setrenderneeded) { @@ -1516,11 +1515,12 @@ void VID_CheckRenderer(void) // Initialise OpenGL before calling SDLSetMode!!! // This is because SDLSetMode calls OglSdlSurface. - if (vid_opengl_state == 0) + if (vid.glstate == VID_GL_LIBRARY_NOTLOADED) { VID_StartupOpenGL(); + // Loaded successfully! - if (vid_opengl_state == 1) + if (vid.glstate == VID_GL_LIBRARY_LOADED) { // Destroy the current window, if it exists. if (window) @@ -1543,7 +1543,7 @@ void VID_CheckRenderer(void) contextcreated = true; } } - else if (vid_opengl_state == -1) + else if (vid.glstate == VID_GL_LIBRARY_ERROR) rendererchanged = false; } #endif @@ -1565,27 +1565,22 @@ void VID_CheckRenderer(void) bufSurface = NULL; } - if (rendererchanged) - { #ifdef HWRENDER - if (vid_opengl_state == 1) // Only if OpenGL ever loaded! - HWR_FreeTextureCache(); + if (rendererchanged && vid.glstate == VID_GL_LIBRARY_LOADED) // Only if OpenGL ever loaded! + HWR_ClearAllTextures(); #endif - SCR_SetDrawFuncs(); - } + + SCR_SetDrawFuncs(); } #ifdef HWRENDER - else if (rendermode == render_opengl) + else if (rendermode == render_opengl && rendererchanged) { - if (rendererchanged) - { - R_InitHardwareMode(); - V_SetPalette(0); - } + HWR_Switch(); + V_SetPalette(0); } -#else - (void)oldrenderer; #endif + + return rendererchanged; } INT32 VID_SetMode(INT32 modeNum) @@ -1626,7 +1621,7 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen) flags |= SDL_WINDOW_BORDERLESS; #ifdef HWRENDER - if (vid_opengl_state == 1) + if (vid.glstate == VID_GL_LIBRARY_LOADED) flags |= SDL_WINDOW_OPENGL; #endif @@ -1747,12 +1742,44 @@ void I_StartupGraphics(void) framebuffer = SDL_TRUE; } -#ifdef HWRENDER - if (M_CheckParm("-opengl")) - chosenrendermode = rendermode = render_opengl; + // Renderer choices + // Takes priority over the config. + if (M_CheckParm("-renderer")) + { + INT32 i = 0; + CV_PossibleValue_t *renderer_list = cv_renderer_t; + const char *modeparm = M_GetNextParm(); + while (renderer_list[i].strvalue) + { + if (!stricmp(modeparm, renderer_list[i].strvalue)) + { + chosenrendermode = renderer_list[i].value; + break; + } + i++; + } + } + + // Choose Software renderer else if (M_CheckParm("-software")) + chosenrendermode = render_soft; + +#ifdef HWRENDER + // Choose OpenGL renderer + else if (M_CheckParm("-opengl")) + chosenrendermode = render_opengl; + + // Don't startup OpenGL + if (M_CheckParm("-nogl")) + { + vid.glstate = VID_GL_LIBRARY_ERROR; + if (chosenrendermode == render_opengl) + chosenrendermode = render_none; + } #endif - chosenrendermode = rendermode = render_soft; + + if (chosenrendermode != render_none) + rendermode = chosenrendermode; usesdl2soft = M_CheckParm("-softblit"); borderlesswindow = M_CheckParm("-borderless"); @@ -1761,9 +1788,7 @@ void I_StartupGraphics(void) VID_Command_ModeList_f(); #ifdef HWRENDER - if (M_CheckParm("-nogl")) - vid_opengl_state = -1; // Don't startup OpenGL - else if (chosenrendermode == render_opengl) + if (rendermode == render_opengl) VID_StartupOpenGL(); #endif @@ -1865,9 +1890,9 @@ void VID_StartupOpenGL(void) HWD.pfnLoadCustomShader = hwSym("LoadCustomShader",NULL); HWD.pfnInitCustomShaders= hwSym("InitCustomShaders",NULL); - vid_opengl_state = HWD.pfnInit() ? 1 : -1; // let load the OpenGL library + vid.glstate = HWD.pfnInit() ? VID_GL_LIBRARY_LOADED : VID_GL_LIBRARY_ERROR; // let load the OpenGL library - if (vid_opengl_state == -1) + if (vid.glstate == VID_GL_LIBRARY_ERROR) { rendermode = render_soft; setrenderneeded = 0; diff --git a/src/v_video.c b/src/v_video.c index 7f07852fa..89ffea6cf 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -3719,3 +3719,36 @@ void V_Init(void) CONS_Debug(DBG_RENDER, " screens[%d] = %x\n", i, screens[i]); #endif } + +void V_Recalc(void) +{ + // scale 1,2,3 times in x and y the patches for the menus and overlays... + // calculated once and for all, used by routines in v_video.c and v_draw.c + vid.dupx = vid.width / BASEVIDWIDTH; + vid.dupy = vid.height / BASEVIDHEIGHT; + vid.dupx = vid.dupy = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); + vid.fdupx = FixedDiv(vid.width*FRACUNIT, BASEVIDWIDTH*FRACUNIT); + vid.fdupy = FixedDiv(vid.height*FRACUNIT, BASEVIDHEIGHT*FRACUNIT); + +#ifdef HWRENDER + //if (rendermode != render_opengl && rendermode != render_none) // This was just placing it incorrectly at non aspect correct resolutions in opengl + // 13/11/18: + // The above is no longer necessary, since we want OpenGL to be just like software now + // -- Monster Iestyn +#endif + vid.fdupx = vid.fdupy = (vid.fdupx < vid.fdupy ? vid.fdupx : vid.fdupy); + + vid.meddupx = (UINT8)(vid.dupx >> 1) + 1; + vid.meddupy = (UINT8)(vid.dupy >> 1) + 1; +#ifdef HWRENDER + vid.fmeddupx = vid.meddupx*FRACUNIT; + vid.fmeddupy = vid.meddupy*FRACUNIT; +#endif + + vid.smalldupx = (UINT8)(vid.dupx / 3) + 1; + vid.smalldupy = (UINT8)(vid.dupy / 3) + 1; +#ifdef HWRENDER + vid.fsmalldupx = vid.smalldupx*FRACUNIT; + vid.fsmalldupy = vid.smalldupy*FRACUNIT; +#endif +} diff --git a/src/v_video.h b/src/v_video.h index 9f7a9a9e9..96bc7db89 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -37,6 +37,9 @@ cv_allcaps; // Allocates buffer screens, call before R_Init. void V_Init(void); +// Recalculates the viddef (dupx, dupy, etc.) according to the current screen resolution. +void V_Recalc(void); + // Color look-up table #define COLORBITS 6 #define SHIFTCOLORBITS (8-COLORBITS) diff --git a/src/w_wad.c b/src/w_wad.c index f40f4eb4a..0d329302a 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -845,7 +845,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup) #ifdef HWRENDER // Read shaders from file - if (rendermode == render_opengl && (vid_opengl_state == 1)) + if (rendermode == render_opengl && (vid.glstate == VID_GL_LIBRARY_LOADED)) { HWR_ReadShaders(numwadfiles - 1, (type == RET_PK3)); HWR_LoadShaders(); diff --git a/src/win32/win_vid.c b/src/win32/win_vid.c index 716f38089..6a74a08d2 100644 --- a/src/win32/win_vid.c +++ b/src/win32/win_vid.c @@ -48,6 +48,7 @@ // this is the CURRENT rendermode!! very important: used by w_wad, and much other code rendermode_t rendermode = render_soft; +rendermode_t chosenrendermode = render_none; // set by command line arguments static void OnTop_OnChange(void); // synchronize page flipping with screen refresh static CV_PossibleValue_t CV_NeverOnOff[] = {{-1, "Never"}, {0, "Off"}, {1, "On"}, {0, NULL}}; @@ -56,7 +57,6 @@ static consvar_t cv_stretch = {"stretch", "On", CV_SAVE|CV_NOSHOWHELP, CV_OnOff, static consvar_t cv_ontop = {"ontop", "Never", 0, CV_NeverOnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; boolean highcolor; -int vid_opengl_state = 0; static BOOL bDIBMode; // means we are using DIB instead of DirectDraw surfaces static LPBITMAPINFO bmiMain = NULL; @@ -952,7 +952,11 @@ INT32 VID_SetMode(INT32 modenum) return 1; } -void VID_CheckRenderer(void) {} +boolean VID_CheckRenderer(void) +{ + return false; +} + void VID_CheckGLLoaded(rendermode_t oldrender) { (void)oldrender;