diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0ac5ac75..6d97f5ed 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -49,7 +49,7 @@ set(WOOF_SOURCES i_video.c i_video.h info.c info.h m_argv.c m_argv.h - m_array.c m_array.h + m_array.h m_bbox.c m_bbox.h m_cheat.c m_cheat.h m_fixed.h @@ -227,7 +227,7 @@ set(SETUP_SOURCES i_system.c i_system.h i_timer.c i_timer.h m_argv.c m_argv.h - m_array.c m_array.h + m_array.h m_io.c m_io.h m_misc2.c m_misc2.h net_io.c net_io.h diff --git a/src/am_map.c b/src/am_map.c index d60437e8..46d63fa0 100644 --- a/src/am_map.c +++ b/src/am_map.c @@ -575,14 +575,6 @@ static void AM_clearLastMark(void) void AM_enableSmoothLines(void) { - static boolean precalc_once = true; - - if (precalc_once && map_smooth_lines) - { - V_InitFlexTranTable(); - precalc_once = false; - } - AM_drawFline = map_smooth_lines ? AM_drawFline_Smooth : AM_drawFline_Vanilla; } diff --git a/src/d_main.c b/src/d_main.c index 66b6585b..e30e75dd 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -388,7 +388,7 @@ void D_Display (void) } while (!done); - I_ResetTargetRefresh(); // reset after wipe + drs_skip_frame = true; // skip DRS after wipe } // diff --git a/src/g_game.c b/src/g_game.c index c7fe65ae..0e8d8337 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -59,6 +59,7 @@ #include "m_snapshot.h" #include "m_swap.h" // [FG] LONG #include "i_input.h" +#include "i_video.h" #include "m_array.h" #define SAVEGAMESIZE 0x20000 @@ -2155,6 +2156,8 @@ static void G_DoSaveGame(void) if (name) free(name); M_SetQuickSaveSlot(savegameslot); + + drs_skip_frame = true; } static void G_DoLoadGame(void) diff --git a/src/i_video.c b/src/i_video.c index ebcfd384..98fa71ac 100644 --- a/src/i_video.c +++ b/src/i_video.c @@ -108,6 +108,8 @@ boolean screenvisible = true; boolean window_focused = true; +boolean drs_skip_frame; + void *I_GetSDLWindow(void) { return screen; @@ -249,6 +251,8 @@ static void HandleWindowEvent(SDL_WindowEvent *event) default: break; } + + drs_skip_frame = true; } // [FG] fullscreen toggle from Chocolate Doom 3.0 @@ -471,7 +475,7 @@ static void UpdateRender(void) } } -static uint64_t frametime_withoutpresent; +static uint64_t frametime_start, frametime_withoutpresent; static int targetrefresh; static void ResetResolution(int height); @@ -482,13 +486,18 @@ void I_DynamicResolution(void) static int frame_counter; static double averagepercent; - if (resolution_mode != RES_DRS || frametime_withoutpresent == 0 || - // Skip if frame time is too long (e.g. window event). - frametime_withoutpresent > 100000) + if (resolution_mode != RES_DRS || frametime_withoutpresent == 0 || menuactive) { return; } + if (drs_skip_frame) + { + frametime_start = frametime_withoutpresent = 0; + drs_skip_frame = false; + return; + } + // 1.25 milliseconds for SDL render present double target = (1.0 / targetrefresh) - 0.00125; double actual = frametime_withoutpresent / 1000000.0; @@ -498,9 +507,8 @@ void I_DynamicResolution(void) #define DRS_MIN_HEIGHT 400 #define DRS_DELTA 0.1 #define DRS_GREATER (1 + DRS_DELTA) - #define DRS_LESS (1 - DRS_DELTA) - // 50px step to make scaling artefacts less noticeable. - #define DRS_STEP (SCREENHEIGHT / 4) + #define DRS_LESS (1 - DRS_DELTA / 10.0) + #define DRS_STEP (SCREENHEIGHT / 2) int newheight = 0; int oldheight = video.height; @@ -513,7 +521,7 @@ void I_DynamicResolution(void) if (actualpercent > DRS_GREATER) { - double reduction = (actualpercent - DRS_GREATER ) * 0.2; + double reduction = (actualpercent - DRS_GREATER ) * 0.4; newheight = (int)MAX(DRS_MIN_HEIGHT, oldheight - oldheight * reduction); } else if (averagepercent < DRS_LESS && frame_counter > targetrefresh) @@ -553,8 +561,6 @@ static void CreateUpscaledTexture(boolean force); void I_FinishUpdate(void) { - static uint64_t frametime_start; - if (noblit) { return; @@ -1090,6 +1096,8 @@ static void ResetResolution(int height) I_InitDiskFlash(); I_Printf(VB_DEBUG, "ResetResolution: %dx%d", video.width, video.height); + + drs_skip_frame = true; } static void CreateUpscaledTexture(boolean force) @@ -1206,8 +1214,6 @@ static void ResetLogicalSize(void) void I_ResetTargetRefresh(void) { - frametime_withoutpresent = 0; // skip DRS one frame - if (uncapped) { targetrefresh = (fpslimit >= TICRATE) ? fpslimit : native_refresh_rate; diff --git a/src/i_video.h b/src/i_video.h index 000edc5f..ccdb3320 100644 --- a/src/i_video.h +++ b/src/i_video.h @@ -69,6 +69,8 @@ void I_ToggleVsync(void); // [JN] Calls native SDL vsync toggle void I_DynamicResolution(void); +extern boolean drs_skip_frame; + extern char *sdl_renderdriver; extern boolean use_vsync; // killough 2/8/98: controls whether vsync is called diff --git a/src/m_array.c b/src/m_array.c deleted file mode 100644 index daf36e91..00000000 --- a/src/m_array.c +++ /dev/null @@ -1,52 +0,0 @@ -// -// Copyright(C) 2024 Roman Fomin -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -#include - -#include "m_array.h" -#include "i_system.h" - -m_array_buffer_t *array_ptr(void *v) -{ - return (m_array_buffer_t *)((char *)v - offsetof(m_array_buffer_t, buffer)); -} - -int array_size(void *v) -{ - return v ? array_ptr(v)->size : 0; -} - -int array_capacity(void *v) -{ - return v ? array_ptr(v)->capacity : 0; -} - -void *M_ArrayGrow(void *v, size_t esize, int n) -{ - m_array_buffer_t *p; - - if (v) - { - p = array_ptr(v); - p = I_Realloc(p, sizeof(m_array_buffer_t) + (p->capacity + n) * esize); - p->capacity += n; - } - else - { - p = malloc(sizeof(m_array_buffer_t) + n * esize); - p->capacity = n; - p->size = 0; - } - - return p->buffer; -} diff --git a/src/m_array.h b/src/m_array.h index a0250317..0380e125 100644 --- a/src/m_array.h +++ b/src/m_array.h @@ -19,6 +19,9 @@ // and any previously-taken pointers should be considered invalidated. #include +#include + +#include "doomtype.h" #ifndef M_ARRAY_INIT_CAPACITY #define M_ARRAY_INIT_CAPACITY 8 @@ -31,11 +34,20 @@ typedef struct char buffer[]; } m_array_buffer_t; -m_array_buffer_t *array_ptr(void *v); -int array_size(void *v); -int array_capacity(void *v); +inline static m_array_buffer_t *array_ptr(void *v) +{ + return (m_array_buffer_t *)((char *)v - offsetof(m_array_buffer_t, buffer)); +} -void *M_ArrayGrow(void *v, size_t esize, int n); +inline static int array_size(void *v) +{ + return v ? array_ptr(v)->size : 0; +} + +inline static int array_capacity(void *v) +{ + return v ? array_ptr(v)->capacity : 0; +} #define array_grow(v, n) \ ((v) = M_ArrayGrow((v), sizeof(*(v)), n)) @@ -63,3 +75,23 @@ void *M_ArrayGrow(void *v, size_t esize, int n); (v) = NULL; \ } \ } while (0) + +inline static void *M_ArrayGrow(void *v, size_t esize, int n) +{ + m_array_buffer_t *p; + + if (v) + { + p = array_ptr(v); + p = realloc(p, sizeof(m_array_buffer_t) + (p->capacity + n) * esize); + p->capacity += n; + } + else + { + p = malloc(sizeof(m_array_buffer_t) + n * esize); + p->capacity = n; + p->size = 0; + } + + return p->buffer; +} diff --git a/src/r_main.c b/src/r_main.c index 2ae3a1a1..def77651 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -29,7 +29,7 @@ #include "r_voxel.h" #include "i_video.h" #include "v_video.h" -#include "am_map.h" +#include "v_flextran.h" #include "st_stuff.h" // killough: viewangleoffset is a legacy from the pre-v1.2 days, when Doom @@ -557,6 +557,7 @@ void R_Init (void) R_InitLightTables(); R_InitSkyMap(); R_InitTranslationTables(); + V_InitFlexTranTable(); // [FG] spectre drawing mode R_SetFuzzColumnMode(); diff --git a/src/v_video.c b/src/v_video.c index b6c4b5d4..f94596c5 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -418,48 +418,50 @@ static void V_DrawPatchColumnTL(const patch_column_t *patchcol) static void V_DrawMaskedColumn(patch_column_t *patchcol, const int ytop, column_t *column) { - for ( ; column->topdelta != 0xff; column = (column_t *)((byte *)column + column->length + 4)) - { - // calculate unclipped screen coordinates for post - int columntop = ytop + column->topdelta; + while (column->topdelta != 0xff) + { + // calculate unclipped screen coordinates for post + int columntop = ytop + column->topdelta; - if (columntop >= 0) - { - // SoM: Make sure the lut is never referenced out of range - if (columntop >= SCREENHEIGHT) - return; + if (columntop >= 0) + { + // SoM: Make sure the lut is never referenced out of range + if (columntop >= SCREENHEIGHT) + return; - patchcol->y1 = y1lookup[columntop]; - patchcol->frac = 0; - } - else - { - patchcol->frac = (-columntop) << FRACBITS; - patchcol->y1 = 0; - } + patchcol->y1 = y1lookup[columntop]; + patchcol->frac = 0; + } + else + { + patchcol->frac = (-columntop) << FRACBITS; + patchcol->y1 = 0; + } - if (columntop + column->length - 1 < 0) - continue; - if (columntop + column->length - 1 < SCREENHEIGHT) - patchcol->y2 = y2lookup[columntop + column->length - 1]; - else - patchcol->y2 = y2lookup[SCREENHEIGHT - 1]; + if (columntop + column->length - 1 < 0) + continue; + if (columntop + column->length - 1 < SCREENHEIGHT) + patchcol->y2 = y2lookup[columntop + column->length - 1]; + else + patchcol->y2 = y2lookup[SCREENHEIGHT - 1]; - // SoM: The failsafes should be completely redundant now... - // haleyjd 05/13/08: fix clipping; y2lookup not clamped properly - if ((column->length > 0 && patchcol->y2 < patchcol->y1) || - patchcol->y2 >= video.height) - { - patchcol->y2 = video.height - 1; - } + // SoM: The failsafes should be completely redundant now... + // haleyjd 05/13/08: fix clipping; y2lookup not clamped properly + if ((column->length > 0 && patchcol->y2 < patchcol->y1) || + patchcol->y2 >= video.height) + { + patchcol->y2 = video.height - 1; + } - // killough 3/2/98, 3/27/98: Failsafe against overflow/crash: - if (patchcol->y1 <= patchcol->y2 && patchcol->y2 < video.height) - { - patchcol->source = (byte *)column + 3; - drawcolfunc(patchcol); - } - } + // killough 3/2/98, 3/27/98: Failsafe against overflow/crash: + if (patchcol->y1 <= patchcol->y2 && patchcol->y2 < video.height) + { + patchcol->source = (byte *)column + 3; + drawcolfunc(patchcol); + } + + column = (column_t *)((byte *)column + column->length + 4); + } } void V_DrawPatchInt(int x, int y, patch_t *patch, boolean flipped, @@ -467,7 +469,6 @@ void V_DrawPatchInt(int x, int y, patch_t *patch, boolean flipped, { int x1, x2, w; fixed_t iscale, xiscale, startfrac = 0; - int maxw; patch_column_t patchcol = {0}; w = SHORT(patch->width); @@ -488,10 +489,9 @@ void V_DrawPatchInt(int x, int y, patch_t *patch, boolean flipped, iscale = video.xstep; patchcol.step = video.ystep; - maxw = video.unscaledw; // off the left or right side? - if (x2 < 0 || x1 >= maxw) + if (x2 < 0 || x1 >= video.unscaledw) return; if (translation) @@ -510,10 +510,10 @@ void V_DrawPatchInt(int x, int y, patch_t *patch, boolean flipped, // very carefully here. if (x1 >= 0) x1 = x1lookup[x1]; - else if (-x1 - 1 < maxw) + else if (-x1 - 1 < video.unscaledw) x1 = -x2lookup[-x1 - 1]; else // too far off-screen - x1 = -(((-x1 - 1) * video.xscale) >> FRACBITS); + x1 = (x1 * video.xscale) >> FRACBITS; if (x2 < video.unscaledw) x2 = x2lookup[x2]; @@ -662,8 +662,8 @@ static void V_ScaleClippedRect(vrect_t *rect) #ifdef RANGECHECK // sanity check - out-of-bounds values should not come out of the scaling // arrays so long as they are accessed within bounds. - if(rect->sx < 0 || rect->sx + rect->sw > video.width || - rect->sy < 0 || rect->sy + rect->sh > video.height) + if (rect->sx < 0 || rect->sx + rect->sw > video.width || + rect->sy < 0 || rect->sy + rect->sh > video.height) { I_Error("V_ScaleRect: internal error - invalid scaling lookups"); } @@ -680,6 +680,11 @@ void V_FillRect(int x, int y, int width, int height, byte color) dstrect.h = height; V_ClipRect(&dstrect); + + // clipped away completely? + if (dstrect.cw <= 0 || dstrect.ch <= 0) + return; + V_ScaleClippedRect(&dstrect); byte* dest = V_ADDRESS(dest_screen, dstrect.sx, dstrect.sy);