mirror of
https://github.com/yquake2/yquake2remaster.git
synced 2025-01-31 21:30:36 +00:00
Merge pull request #416 from 0lvin/for_review
Fix overrun in RE_BufferDifferenceStart
This commit is contained in:
commit
c1ccb95026
3 changed files with 160 additions and 24 deletions
|
@ -582,6 +582,9 @@ void R_FreeUnusedImages(void);
|
||||||
void R_InitSkyBox(void);
|
void R_InitSkyBox(void);
|
||||||
void R_IMFlatShadedQuad( vec3_t a, vec3_t b, vec3_t c, vec3_t d, int color, float alpha );
|
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);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
====================================================================
|
====================================================================
|
||||||
|
|
||||||
|
|
|
@ -119,6 +119,9 @@ RE_Draw_CharScaled(int x, int y, int num, float scale)
|
||||||
drawline = (vid.height - y) / iscale;
|
drawline = (vid.height - y) / iscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VID_DamageBuffer(x, y);
|
||||||
|
VID_DamageBuffer(x + (iscale << 3), y + (iscale * drawline));
|
||||||
|
|
||||||
while (drawline--)
|
while (drawline--)
|
||||||
{
|
{
|
||||||
for (ypos=0; ypos < iscale; ypos ++)
|
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__);
|
ri.Sys_Error(ERR_FATAL, "%s: bad coordinates", __func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VID_DamageBuffer(x, y);
|
||||||
|
VID_DamageBuffer(x + w, y + h);
|
||||||
|
|
||||||
height = h;
|
height = h;
|
||||||
if (y < 0)
|
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;
|
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 (!pic->transparent)
|
||||||
{
|
{
|
||||||
if (iscale == 1)
|
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)
|
if (w <= 0 || h <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
VID_DamageBuffer(x, y);
|
||||||
|
VID_DamageBuffer(x + w, y + h);
|
||||||
|
|
||||||
pic = RE_Draw_FindPic (name);
|
pic = RE_Draw_FindPic (name);
|
||||||
if (!pic)
|
if (!pic)
|
||||||
{
|
{
|
||||||
|
@ -448,6 +460,9 @@ RE_Draw_Fill (int x, int y, int w, int h, int c)
|
||||||
if (w < 0 || h < 0)
|
if (w < 0 || h < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
VID_DamageBuffer(x, y);
|
||||||
|
VID_DamageBuffer(x + w, y + h);
|
||||||
|
|
||||||
dest = vid_buffer + y * vid.width + x;
|
dest = vid_buffer + y * vid.width + x;
|
||||||
for (v=0 ; v<h ; v++, dest += vid.width)
|
for (v=0 ; v<h ; v++, dest += vid.width)
|
||||||
memset(dest, c, w);
|
memset(dest, c, w);
|
||||||
|
@ -465,6 +480,9 @@ RE_Draw_FadeScreen (void)
|
||||||
{
|
{
|
||||||
int x,y;
|
int x,y;
|
||||||
|
|
||||||
|
VID_DamageBuffer(0, 0);
|
||||||
|
VID_DamageBuffer(vid.width, vid.height);
|
||||||
|
|
||||||
for (y=0 ; y<vid.height ; y++)
|
for (y=0 ; y<vid.height ; y++)
|
||||||
{
|
{
|
||||||
int t;
|
int t;
|
||||||
|
|
|
@ -40,6 +40,7 @@ static int swap_current = 0;
|
||||||
espan_t *vid_polygon_spans = NULL;
|
espan_t *vid_polygon_spans = NULL;
|
||||||
pixel_t *vid_colormap = NULL;
|
pixel_t *vid_colormap = NULL;
|
||||||
pixel_t *vid_alphamap = NULL;
|
pixel_t *vid_alphamap = NULL;
|
||||||
|
static int vid_minu, vid_minv, vid_maxu, vid_maxv;
|
||||||
|
|
||||||
refimport_t ri;
|
refimport_t ri;
|
||||||
|
|
||||||
|
@ -198,11 +199,61 @@ zvalue_t *d_pzbuffer;
|
||||||
static void Draw_GetPalette (void);
|
static void Draw_GetPalette (void);
|
||||||
static void RE_BeginFrame( float camera_separation );
|
static void RE_BeginFrame( float camera_separation );
|
||||||
static void Draw_BuildGammaTable(void);
|
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_CleanFrame(void);
|
||||||
static void RE_EndFrame(void);
|
static void RE_EndFrame(void);
|
||||||
static void R_DrawBeam(const entity_t *e);
|
static void R_DrawBeam(const entity_t *e);
|
||||||
|
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
Damage_VIDBuffer
|
||||||
|
|
||||||
|
Mark VID buffer as damaged and need to be rewritten
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
VID_DamageBuffer(int u, int v)
|
||||||
|
{
|
||||||
|
// update U
|
||||||
|
if (vid_minu > 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
|
R_InitTurb
|
||||||
|
@ -1120,6 +1171,9 @@ RE_RenderFrame (refdef_t *fd)
|
||||||
ri.Sys_Error(ERR_FATAL, "%s: NULL worldmodel", __func__);
|
ri.Sys_Error(ERR_FATAL, "%s: NULL worldmodel", __func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Need to rerender whole frame
|
||||||
|
VID_WholeDamageBuffer();
|
||||||
|
|
||||||
VectorCopy (fd->vieworg, r_refdef.vieworg);
|
VectorCopy (fd->vieworg, r_refdef.vieworg);
|
||||||
VectorCopy (fd->viewangles, r_refdef.viewangles);
|
VectorCopy (fd->viewangles, r_refdef.viewangles);
|
||||||
|
|
||||||
|
@ -1793,10 +1847,10 @@ RE_CopyFrame (Uint32 * pixels, int pitch, int vmin, int vmax)
|
||||||
Uint32 *pixels_pos;
|
Uint32 *pixels_pos;
|
||||||
pixel_t *buffer_pos;
|
pixel_t *buffer_pos;
|
||||||
|
|
||||||
max_pixels = pixels + vmax * vid.width;
|
max_pixels = pixels + vmax;
|
||||||
buffer_pos = vid_buffer + vmin * vid.width;
|
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];
|
*pixels_pos = sdl_palette[*buffer_pos];
|
||||||
buffer_pos++;
|
buffer_pos++;
|
||||||
|
@ -1804,10 +1858,14 @@ RE_CopyFrame (Uint32 * pixels, int pitch, int vmin, int vmax)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int y,x, buffer_pos;
|
int y,x, buffer_pos, ymin, ymax;
|
||||||
|
|
||||||
buffer_pos = 0;
|
ymin = vmin / vid.width;
|
||||||
for (y=vmin; y < vmax; y++)
|
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 ++)
|
for (x=0; x < vid.width; x ++)
|
||||||
{
|
{
|
||||||
|
@ -1824,15 +1882,32 @@ RE_BufferDifferenceStart(int vmin, int vmax)
|
||||||
{
|
{
|
||||||
int *front_buffer, *back_buffer, *back_max;
|
int *front_buffer, *back_buffer, *back_max;
|
||||||
|
|
||||||
back_buffer = (int*)swap_frames[0] + vmin * vid.width;
|
back_buffer = (int*)(swap_frames[0] + vmin);
|
||||||
front_buffer = (int*)swap_frames[1] + vmin * vid.width;
|
front_buffer = (int*)(swap_frames[1] + vmin);
|
||||||
back_max = (int*)swap_frames[0] + vmax * vid.width;
|
back_max = (int*)(swap_frames[0] + vmax);
|
||||||
|
|
||||||
while (back_buffer < back_max && *back_buffer == *front_buffer) {
|
while (back_buffer < back_max && *back_buffer == *front_buffer) {
|
||||||
back_buffer ++;
|
back_buffer ++;
|
||||||
front_buffer ++;
|
front_buffer ++;
|
||||||
}
|
}
|
||||||
return ((pixel_t*)back_buffer - swap_frames[0]) / vid.width;
|
return (pixel_t*)back_buffer - swap_frames[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
RE_BufferDifferenceEnd(int vmin, int vmax)
|
||||||
|
{
|
||||||
|
int *front_buffer, *back_buffer, *back_min;
|
||||||
|
|
||||||
|
back_buffer = (int*)(swap_frames[0] + vmax);
|
||||||
|
front_buffer = (int*)(swap_frames[1] + vmax);
|
||||||
|
back_min = (int*)(swap_frames[0] + vmin);
|
||||||
|
|
||||||
|
do {
|
||||||
|
back_buffer --;
|
||||||
|
front_buffer --;
|
||||||
|
} 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
|
static void
|
||||||
|
@ -1853,34 +1928,34 @@ RE_CleanFrame(void)
|
||||||
|
|
||||||
SDL_RenderCopy(renderer, texture, NULL, NULL);
|
SDL_RenderCopy(renderer, texture, NULL, NULL);
|
||||||
SDL_RenderPresent(renderer);
|
SDL_RenderPresent(renderer);
|
||||||
|
|
||||||
|
// All changes flushed
|
||||||
|
VID_NoDamageBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
RE_FlushFrame(int vmin)
|
RE_FlushFrame(int vmin, int vmax)
|
||||||
{
|
{
|
||||||
int pitch;
|
int pitch;
|
||||||
Uint32 *pixels;
|
Uint32 *pixels;
|
||||||
SDL_Rect copy_rect;
|
|
||||||
|
|
||||||
copy_rect.x = 0;
|
|
||||||
copy_rect.y = vmin;
|
|
||||||
copy_rect.w = vid.width;
|
|
||||||
copy_rect.h = vid.height - vmin;
|
|
||||||
|
|
||||||
if (SDL_LockTexture(texture, NULL, (void**)&pixels, &pitch))
|
if (SDL_LockTexture(texture, NULL, (void**)&pixels, &pitch))
|
||||||
{
|
{
|
||||||
Com_Printf("Can't lock texture: %s\n", SDL_GetError());
|
Com_Printf("Can't lock texture: %s\n", SDL_GetError());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
RE_CopyFrame (pixels, pitch / sizeof(Uint32), vmin, vid.height);
|
RE_CopyFrame (pixels, pitch / sizeof(Uint32), vmin, vmax);
|
||||||
SDL_UnlockTexture(texture);
|
SDL_UnlockTexture(texture);
|
||||||
|
|
||||||
SDL_RenderCopy(renderer, texture, ©_rect, ©_rect);
|
SDL_RenderCopy(renderer, texture, NULL, NULL);
|
||||||
SDL_RenderPresent(renderer);
|
SDL_RenderPresent(renderer);
|
||||||
|
|
||||||
// replace use next buffer
|
// replace use next buffer
|
||||||
swap_current ++;
|
swap_current ++;
|
||||||
vid_buffer = swap_frames[swap_current&1];
|
vid_buffer = swap_frames[swap_current&1];
|
||||||
|
|
||||||
|
// All changes flushed
|
||||||
|
VID_NoDamageBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1892,14 +1967,52 @@ RE_FlushFrame(int vmin)
|
||||||
static void
|
static void
|
||||||
RE_EndFrame (void)
|
RE_EndFrame (void)
|
||||||
{
|
{
|
||||||
int vmin;
|
int vmin, vmax;
|
||||||
|
|
||||||
vmin = RE_BufferDifferenceStart(0, vid.height);
|
// fix possible issue with min/max
|
||||||
if (vmin >= vid.height)
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
vmin = vid_minu + vid_minv * vid.width;
|
||||||
|
vmax = vid_maxu + vid_maxv * vid.width;
|
||||||
|
|
||||||
|
// 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;
|
return;
|
||||||
}
|
}
|
||||||
RE_FlushFrame(vmin);
|
|
||||||
|
// search difference end
|
||||||
|
vmax = RE_BufferDifferenceEnd(vmin, vmax);
|
||||||
|
if (vmax > (vid.height * vid.width))
|
||||||
|
{
|
||||||
|
vmax = vid.height * vid.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
RE_FlushFrame(vmin, vmax);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1949,6 +2062,8 @@ SWimp_CreateRender(void)
|
||||||
swap_frames[0] = swap_buffers;
|
swap_frames[0] = swap_buffers;
|
||||||
swap_frames[1] = swap_buffers + vid.height * vid.width * sizeof(pixel_t);
|
swap_frames[1] = swap_buffers + vid.height * vid.width * sizeof(pixel_t);
|
||||||
vid_buffer = swap_frames[swap_current&1];
|
vid_buffer = swap_frames[swap_current&1];
|
||||||
|
// Need to rewrite whole frame
|
||||||
|
VID_WholeDamageBuffer();
|
||||||
|
|
||||||
sintable = malloc((vid.width+CYCLE) * sizeof(int));
|
sintable = malloc((vid.width+CYCLE) * sizeof(int));
|
||||||
intsintable = malloc((vid.width+CYCLE) * sizeof(int));
|
intsintable = malloc((vid.width+CYCLE) * sizeof(int));
|
||||||
|
|
Loading…
Reference in a new issue