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_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;
|
||||
}
|
||||
|
||||
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<h ; v++, dest += vid.width)
|
||||
memset(dest, c, w);
|
||||
|
@ -465,6 +480,9 @@ RE_Draw_FadeScreen (void)
|
|||
{
|
||||
int x,y;
|
||||
|
||||
VID_DamageBuffer(0, 0);
|
||||
VID_DamageBuffer(vid.width, vid.height);
|
||||
|
||||
for (y=0 ; y<vid.height ; y++)
|
||||
{
|
||||
int t;
|
||||
|
|
|
@ -40,6 +40,7 @@ static int swap_current = 0;
|
|||
espan_t *vid_polygon_spans = NULL;
|
||||
pixel_t *vid_colormap = NULL;
|
||||
pixel_t *vid_alphamap = NULL;
|
||||
static int vid_minu, vid_minv, vid_maxu, vid_maxv;
|
||||
|
||||
refimport_t ri;
|
||||
|
||||
|
@ -198,11 +199,61 @@ 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);
|
||||
|
||||
/*
|
||||
================
|
||||
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
|
||||
|
@ -1120,6 +1171,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);
|
||||
|
||||
|
@ -1793,10 +1847,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++;
|
||||
|
@ -1804,10 +1858,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 = 0;
|
||||
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 ++)
|
||||
{
|
||||
|
@ -1824,15 +1882,32 @@ 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
|
||||
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
|
||||
|
@ -1853,34 +1928,34 @@ RE_CleanFrame(void)
|
|||
|
||||
SDL_RenderCopy(renderer, texture, NULL, NULL);
|
||||
SDL_RenderPresent(renderer);
|
||||
|
||||
// All changes flushed
|
||||
VID_NoDamageBuffer();
|
||||
}
|
||||
|
||||
static void
|
||||
RE_FlushFrame(int vmin)
|
||||
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 = vid.height - 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);
|
||||
SDL_RenderCopy(renderer, texture, NULL, NULL);
|
||||
SDL_RenderPresent(renderer);
|
||||
|
||||
// replace use next buffer
|
||||
swap_current ++;
|
||||
vid_buffer = swap_frames[swap_current&1];
|
||||
|
||||
// All changes flushed
|
||||
VID_NoDamageBuffer();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1892,14 +1967,52 @@ RE_FlushFrame(int vmin)
|
|||
static void
|
||||
RE_EndFrame (void)
|
||||
{
|
||||
int vmin;
|
||||
int vmin, vmax;
|
||||
|
||||
vmin = RE_BufferDifferenceStart(0, vid.height);
|
||||
if (vmin >= 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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[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));
|
||||
|
|
Loading…
Reference in a new issue