From ceb7fd03b1c2b10130919dc7163ce5c69ad06f60 Mon Sep 17 00:00:00 2001 From: Denis Pauk Date: Sun, 30 Jun 2019 17:19:09 +0300 Subject: [PATCH 1/5] fix issue with back_max in RE_BufferDifferenceStart --- src/client/refresh/soft/sw_main.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/client/refresh/soft/sw_main.c b/src/client/refresh/soft/sw_main.c index 9db54ab8..cc46b56c 100644 --- a/src/client/refresh/soft/sw_main.c +++ b/src/client/refresh/soft/sw_main.c @@ -139,6 +139,7 @@ static cvar_t *sw_overbrightbits; cvar_t *sw_custom_particles; cvar_t *sw_texture_filtering; cvar_t *sw_retexturing; +static cvar_t *sw_partialflush; cvar_t *r_drawworld; static cvar_t *r_drawentities; @@ -198,7 +199,7 @@ zvalue_t *d_pzbuffer; static void Draw_GetPalette (void); static void RE_BeginFrame( float camera_separation ); static void Draw_BuildGammaTable(void); -static void RE_FlushFrame(int vmin); +static void RE_FlushFrame(int vmin, int vmax); static void RE_CleanFrame(void); static void RE_EndFrame(void); static void R_DrawBeam(const entity_t *e); @@ -240,6 +241,7 @@ R_RegisterVariables (void) sw_custom_particles = ri.Cvar_Get("sw_custom_particles", "0", CVAR_ARCHIVE); sw_texture_filtering = ri.Cvar_Get("sw_texture_filtering", "0", CVAR_ARCHIVE); sw_retexturing = ri.Cvar_Get("sw_retexturing", "0", CVAR_ARCHIVE); + sw_partialflush = ri.Cvar_Get("sw_partialflush", "0", CVAR_ARCHIVE); r_mode = ri.Cvar_Get( "r_mode", "0", CVAR_ARCHIVE ); r_lefthand = ri.Cvar_Get( "hand", "0", CVAR_USERINFO | CVAR_ARCHIVE ); @@ -1806,7 +1808,8 @@ RE_CopyFrame (Uint32 * pixels, int pitch, int vmin, int vmax) { int y,x, buffer_pos; - buffer_pos = 0; + buffer_pos = vmin * vid.width; + pixels += vmin * pitch; for (y=vmin; y < vmax; y++) { for (x=0; x < vid.width; x ++) @@ -1824,9 +1827,9 @@ RE_BufferDifferenceStart(int vmin, int vmax) { int *front_buffer, *back_buffer, *back_max; - back_buffer = (int*)swap_frames[0] + vmin * vid.width; - front_buffer = (int*)swap_frames[1] + vmin * vid.width; - back_max = (int*)swap_frames[0] + vmax * vid.width; + back_buffer = (int*)(swap_frames[0] + vmin * vid.width); + front_buffer = (int*)(swap_frames[1] + vmin * vid.width); + back_max = (int*)(swap_frames[0] + vmax * vid.width); while (back_buffer < back_max && *back_buffer == *front_buffer) { back_buffer ++; @@ -1856,7 +1859,7 @@ RE_CleanFrame(void) } static void -RE_FlushFrame(int vmin) +RE_FlushFrame(int vmin, int vmax) { int pitch; Uint32 *pixels; @@ -1865,14 +1868,14 @@ RE_FlushFrame(int vmin) copy_rect.x = 0; copy_rect.y = vmin; copy_rect.w = vid.width; - copy_rect.h = vid.height - vmin; + copy_rect.h = vmax - vmin; if (SDL_LockTexture(texture, NULL, (void**)&pixels, &pitch)) { Com_Printf("Can't lock texture: %s\n", SDL_GetError()); return; } - RE_CopyFrame (pixels, pitch / sizeof(Uint32), vmin, vid.height); + RE_CopyFrame (pixels, pitch / sizeof(Uint32), vmin, vmax); SDL_UnlockTexture(texture); SDL_RenderCopy(renderer, texture, ©_rect, ©_rect); @@ -1899,7 +1902,13 @@ RE_EndFrame (void) { return; } - RE_FlushFrame(vmin); + + // flush whole buffer + if (!sw_partialflush->value) + { + vmin = 0; + } + RE_FlushFrame(vmin, vid.height); } /* From a7199f95dbefb6e4f31ce1276380238fe4e03909 Mon Sep 17 00:00:00 2001 From: Denis Pauk Date: Sun, 30 Jun 2019 22:14:49 +0300 Subject: [PATCH 2/5] Always flush whole texture to render --- src/client/refresh/soft/sw_main.c | 48 ++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/src/client/refresh/soft/sw_main.c b/src/client/refresh/soft/sw_main.c index cc46b56c..1b9bc01b 100644 --- a/src/client/refresh/soft/sw_main.c +++ b/src/client/refresh/soft/sw_main.c @@ -1838,6 +1838,22 @@ RE_BufferDifferenceStart(int vmin, int vmax) return ((pixel_t*)back_buffer - swap_frames[0]) / vid.width; } +static int +RE_BufferDifferenceEnd(int vmin, int vmax) +{ + int *front_buffer, *back_buffer, *back_min; + + back_buffer = (int*)(swap_frames[0] + vmax * vid.width); + front_buffer = (int*)(swap_frames[1] + vmax * vid.width); + back_min = (int*)(swap_frames[0] + vmin * vid.width); + + while (back_buffer > back_min && *back_buffer == *front_buffer) { + back_buffer --; + front_buffer --; + } + return ((pixel_t*)back_buffer - swap_frames[0]) / vid.width; +} + static void RE_CleanFrame(void) { @@ -1863,12 +1879,13 @@ RE_FlushFrame(int vmin, int vmax) { int pitch; Uint32 *pixels; - SDL_Rect copy_rect; - copy_rect.x = 0; - copy_rect.y = vmin; - copy_rect.w = vid.width; - copy_rect.h = vmax - vmin; + // flush whole buffer + if (!sw_partialflush->value) + { + vmin = 0; + vmax = vid.height; + } if (SDL_LockTexture(texture, NULL, (void**)&pixels, &pitch)) { @@ -1878,7 +1895,7 @@ RE_FlushFrame(int vmin, int vmax) RE_CopyFrame (pixels, pitch / sizeof(Uint32), vmin, vmax); SDL_UnlockTexture(texture); - SDL_RenderCopy(renderer, texture, ©_rect, ©_rect); + SDL_RenderCopy(renderer, texture, NULL, NULL); SDL_RenderPresent(renderer); // replace use next buffer @@ -1895,20 +1912,23 @@ RE_FlushFrame(int vmin, int vmax) static void RE_EndFrame (void) { - int vmin; + int vmin, vmax; vmin = RE_BufferDifferenceStart(0, vid.height); - if (vmin >= vid.height) + // +1 for fully cover line with changes + vmax = RE_BufferDifferenceEnd(vmin, vid.height) + 1; + if (vmax > vid.height) + { + vmax = vid.height; + } + + // no differences found + if (vmin >= vmax) { return; } - // flush whole buffer - if (!sw_partialflush->value) - { - vmin = 0; - } - RE_FlushFrame(vmin, vid.height); + RE_FlushFrame(vmin, vmax); } /* From c6b31d1b466abc829d95618217cdb17c63b81ad9 Mon Sep 17 00:00:00 2001 From: Denis Pauk Date: Sat, 6 Jul 2019 10:33:15 +0300 Subject: [PATCH 3/5] change 2d buffer damage before frame flush --- src/client/refresh/soft/header/local.h | 3 + src/client/refresh/soft/sw_draw.c | 18 ++++++ src/client/refresh/soft/sw_main.c | 86 +++++++++++++++++++++++++- 3 files changed, 105 insertions(+), 2 deletions(-) diff --git a/src/client/refresh/soft/header/local.h b/src/client/refresh/soft/header/local.h index 90fd66f8..f125a31a 100644 --- a/src/client/refresh/soft/header/local.h +++ b/src/client/refresh/soft/header/local.h @@ -582,6 +582,9 @@ void R_FreeUnusedImages(void); void R_InitSkyBox(void); void R_IMFlatShadedQuad( vec3_t a, vec3_t b, vec3_t c, vec3_t d, int color, float alpha ); +// VID Buffer damage +void VID_DamageBuffer(int u, int v); + /* ==================================================================== diff --git a/src/client/refresh/soft/sw_draw.c b/src/client/refresh/soft/sw_draw.c index 5e36e84e..f4104cff 100644 --- a/src/client/refresh/soft/sw_draw.c +++ b/src/client/refresh/soft/sw_draw.c @@ -119,6 +119,9 @@ RE_Draw_CharScaled(int x, int y, int num, float scale) drawline = (vid.height - y) / iscale; } + VID_DamageBuffer(x, y); + VID_DamageBuffer(x + (iscale << 3), y + (iscale * drawline)); + while (drawline--) { for (ypos=0; ypos < iscale; ypos ++) @@ -178,6 +181,9 @@ RE_Draw_StretchPicImplementation (int x, int y, int w, int h, const image_t *pic ri.Sys_Error(ERR_FATAL, "%s: bad coordinates", __func__); } + VID_DamageBuffer(x, y); + VID_DamageBuffer(x + w, y + h); + height = h; if (y < 0) { @@ -293,6 +299,9 @@ RE_Draw_PicScaled(int x, int y, char *name, float scale) dest = vid_buffer + y * vid.width + x; + VID_DamageBuffer(x, y); + VID_DamageBuffer(x + iscale * pic->width, y + iscale * pic->height); + if (!pic->transparent) { if (iscale == 1) @@ -399,6 +408,9 @@ RE_Draw_TileClear (int x, int y, int w, int h, char *name) if (w <= 0 || h <= 0) return; + VID_DamageBuffer(x, y); + VID_DamageBuffer(x + w, y + h); + pic = RE_Draw_FindPic (name); if (!pic) { @@ -448,6 +460,9 @@ RE_Draw_Fill (int x, int y, int w, int h, int c) if (w < 0 || h < 0) return; + VID_DamageBuffer(x, y); + VID_DamageBuffer(x + w, y + h); + dest = vid_buffer + y * vid.width + x; for (v=0 ; v u) + { + vid_minu = u; + } + if (vid_maxu < u) + { + vid_maxu = u; + } + // update V + if (vid_minv > v) + { + vid_minv = v; + } + if (vid_maxv < v) + { + vid_maxv = v; + } +} + +// clean damage state +static void +VID_NoDamageBuffer(void) +{ + vid_minu = vid.width; + vid_maxu = 0; + vid_minv = vid.height; + vid_maxv = 0; +} + +// Need to rewrite whole buffer +static void +VID_WholeDamageBuffer(void) +{ + vid_minu = 0; + vid_maxu = vid.width; + vid_minv = 0; + vid_maxv = vid.height; +} + /* ================ R_InitTurb @@ -1122,6 +1173,9 @@ RE_RenderFrame (refdef_t *fd) ri.Sys_Error(ERR_FATAL, "%s: NULL worldmodel", __func__); } + // Need to rerender whole frame + VID_WholeDamageBuffer(); + VectorCopy (fd->vieworg, r_refdef.vieworg); VectorCopy (fd->viewangles, r_refdef.viewangles); @@ -1872,6 +1926,9 @@ RE_CleanFrame(void) SDL_RenderCopy(renderer, texture, NULL, NULL); SDL_RenderPresent(renderer); + + // All changes flushed + VID_NoDamageBuffer(); } static void @@ -1901,6 +1958,9 @@ RE_FlushFrame(int vmin, int vmax) // replace use next buffer swap_current ++; vid_buffer = swap_frames[swap_current&1]; + + // All changes flushed + VID_NoDamageBuffer(); } /* @@ -1914,9 +1974,29 @@ RE_EndFrame (void) { int vmin, vmax; - vmin = RE_BufferDifferenceStart(0, vid.height); + // fix possible issue with min/max + if (vid_minu < 0) + { + vid_minu = 0; + } + if (vid_minv < 0) + { + vid_minv = 0; + } + if (vid_maxu > vid.width) + { + vid_maxu = vid.width; + } + if (vid_maxv > vid.height) + { + vid_maxv = vid.height; + } + + // search real begin/end of difference + vmin = RE_BufferDifferenceStart(vid_minv, vid_maxv); + // +1 for fully cover line with changes - vmax = RE_BufferDifferenceEnd(vmin, vid.height) + 1; + vmax = RE_BufferDifferenceEnd(vmin, vid_maxv) + 1; if (vmax > vid.height) { vmax = vid.height; @@ -1978,6 +2058,8 @@ SWimp_CreateRender(void) swap_frames[0] = swap_buffers; swap_frames[1] = swap_buffers + vid.height * vid.width * sizeof(pixel_t); vid_buffer = swap_frames[swap_current&1]; + // Need to rewrite whole frame + VID_WholeDamageBuffer(); sintable = malloc((vid.width+CYCLE) * sizeof(int)); intsintable = malloc((vid.width+CYCLE) * sizeof(int)); From 5b98640dd2bc1c1aa65c861d86f173edd5520d3d Mon Sep 17 00:00:00 2001 From: Denis Pauk Date: Sat, 6 Jul 2019 11:43:01 +0300 Subject: [PATCH 4/5] use pixel position for skip unchanged --- src/client/refresh/soft/sw_main.c | 54 +++++++++++++++++-------------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/src/client/refresh/soft/sw_main.c b/src/client/refresh/soft/sw_main.c index ffdcfd49..4d076b32 100644 --- a/src/client/refresh/soft/sw_main.c +++ b/src/client/refresh/soft/sw_main.c @@ -1849,10 +1849,10 @@ RE_CopyFrame (Uint32 * pixels, int pitch, int vmin, int vmax) Uint32 *pixels_pos; pixel_t *buffer_pos; - max_pixels = pixels + vmax * vid.width; - buffer_pos = vid_buffer + vmin * vid.width; + max_pixels = pixels + vmax; + buffer_pos = vid_buffer + vmin; - for (pixels_pos = pixels + vmin * vid.width; pixels_pos < max_pixels; pixels_pos++) + for (pixels_pos = pixels + vmin; pixels_pos < max_pixels; pixels_pos++) { *pixels_pos = sdl_palette[*buffer_pos]; buffer_pos++; @@ -1860,11 +1860,14 @@ RE_CopyFrame (Uint32 * pixels, int pitch, int vmin, int vmax) } else { - int y,x, buffer_pos; + int y,x, buffer_pos, ymin, ymax; - buffer_pos = vmin * vid.width; - pixels += vmin * pitch; - for (y=vmin; y < vmax; y++) + ymin = vmin / vid.width; + ymax = vmax / vid.width; + + buffer_pos = ymin * vid.width; + pixels += ymin * pitch; + for (y=ymin; y < ymax; y++) { for (x=0; x < vid.width; x ++) { @@ -1881,15 +1884,15 @@ RE_BufferDifferenceStart(int vmin, int vmax) { int *front_buffer, *back_buffer, *back_max; - back_buffer = (int*)(swap_frames[0] + vmin * vid.width); - front_buffer = (int*)(swap_frames[1] + vmin * vid.width); - back_max = (int*)(swap_frames[0] + vmax * vid.width); + back_buffer = (int*)(swap_frames[0] + vmin); + front_buffer = (int*)(swap_frames[1] + vmin); + back_max = (int*)(swap_frames[0] + vmax); while (back_buffer < back_max && *back_buffer == *front_buffer) { back_buffer ++; front_buffer ++; } - return ((pixel_t*)back_buffer - swap_frames[0]) / vid.width; + return (pixel_t*)back_buffer - swap_frames[0]; } static int @@ -1897,15 +1900,16 @@ RE_BufferDifferenceEnd(int vmin, int vmax) { int *front_buffer, *back_buffer, *back_min; - back_buffer = (int*)(swap_frames[0] + vmax * vid.width); - front_buffer = (int*)(swap_frames[1] + vmax * vid.width); - back_min = (int*)(swap_frames[0] + vmin * vid.width); + back_buffer = (int*)(swap_frames[0] + vmax); + front_buffer = (int*)(swap_frames[1] + vmax); + back_min = (int*)(swap_frames[0] + vmin); - while (back_buffer > back_min && *back_buffer == *front_buffer) { + do { back_buffer --; front_buffer --; - } - return ((pixel_t*)back_buffer - swap_frames[0]) / vid.width; + } while (back_buffer > back_min && *back_buffer == *front_buffer); + // +1 for fully cover changes + return (pixel_t*)back_buffer - swap_frames[0] + sizeof(int); } static void @@ -1941,7 +1945,7 @@ RE_FlushFrame(int vmin, int vmax) if (!sw_partialflush->value) { vmin = 0; - vmax = vid.height; + vmax = vid.height * vid.width; } if (SDL_LockTexture(texture, NULL, (void**)&pixels, &pitch)) @@ -1992,14 +1996,16 @@ RE_EndFrame (void) vid_maxv = vid.height; } - // search real begin/end of difference - vmin = RE_BufferDifferenceStart(vid_minv, vid_maxv); + vmin = vid_minu + vid_minv * vid.width; + vmax = vid_maxu + vid_maxv * vid.width; - // +1 for fully cover line with changes - vmax = RE_BufferDifferenceEnd(vmin, vid_maxv) + 1; - if (vmax > vid.height) + // search real begin/end of difference + vmin = RE_BufferDifferenceStart(vmin, vmax); + + vmax = RE_BufferDifferenceEnd(vmin, vmax); + if (vmax > (vid.height * vid.width)) { - vmax = vid.height; + vmax = vid.height * vid.width; } // no differences found From af27d6848333bedb9013e6b281a7ae1557a777ab Mon Sep 17 00:00:00 2001 From: Denis Pauk Date: Sat, 6 Jul 2019 13:25:29 +0300 Subject: [PATCH 5/5] Remove unused sw_partialflush flag --- src/client/refresh/soft/sw_main.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/client/refresh/soft/sw_main.c b/src/client/refresh/soft/sw_main.c index 4d076b32..3196f9aa 100644 --- a/src/client/refresh/soft/sw_main.c +++ b/src/client/refresh/soft/sw_main.c @@ -140,7 +140,6 @@ static cvar_t *sw_overbrightbits; cvar_t *sw_custom_particles; cvar_t *sw_texture_filtering; cvar_t *sw_retexturing; -static cvar_t *sw_partialflush; cvar_t *r_drawworld; static cvar_t *r_drawentities; @@ -292,7 +291,6 @@ R_RegisterVariables (void) sw_custom_particles = ri.Cvar_Get("sw_custom_particles", "0", CVAR_ARCHIVE); sw_texture_filtering = ri.Cvar_Get("sw_texture_filtering", "0", CVAR_ARCHIVE); sw_retexturing = ri.Cvar_Get("sw_retexturing", "0", CVAR_ARCHIVE); - sw_partialflush = ri.Cvar_Get("sw_partialflush", "0", CVAR_ARCHIVE); r_mode = ri.Cvar_Get( "r_mode", "0", CVAR_ARCHIVE ); r_lefthand = ri.Cvar_Get( "hand", "0", CVAR_USERINFO | CVAR_ARCHIVE ); @@ -1941,13 +1939,6 @@ RE_FlushFrame(int vmin, int vmax) int pitch; Uint32 *pixels; - // flush whole buffer - if (!sw_partialflush->value) - { - vmin = 0; - vmax = vid.height * vid.width; - } - if (SDL_LockTexture(texture, NULL, (void**)&pixels, &pitch)) { Com_Printf("Can't lock texture: %s\n", SDL_GetError()); @@ -1999,21 +1990,28 @@ RE_EndFrame (void) vmin = vid_minu + vid_minv * vid.width; vmax = vid_maxu + vid_maxv * vid.width; - // search real begin/end of difference - vmin = RE_BufferDifferenceStart(vmin, vmax); - - vmax = RE_BufferDifferenceEnd(vmin, vmax); + // fix to correct limit if (vmax > (vid.height * vid.width)) { vmax = vid.height * vid.width; } + // search real begin/end of difference + vmin = RE_BufferDifferenceStart(vmin, vmax); + // no differences found if (vmin >= vmax) { return; } + // search difference end + vmax = RE_BufferDifferenceEnd(vmin, vmax); + if (vmax > (vid.height * vid.width)) + { + vmax = vid.height * vid.width; + } + RE_FlushFrame(vmin, vmax); }