Skip to content

Commit 7a488b8

Browse files
committed
gfx/caca,fpga: reuse menu frame buffer across set_texture_frame calls
Both drivers unconditionally free'd menu_frame and set it to NULL before a subsequent size-comparison check, making the "only reallocate if size changed" branch dead. Every menu frame triggered a full free+malloc+memcpy round-trip on a buffer that typically never changes size after the first call. Replace with a cached-capacity realloc pattern: allocate or grow only when the required size exceeds the current capacity; otherwise reuse the existing buffer. On realloc failure the previous frame is kept intact (the original free+malloc sequence would have lost it). fpga_gfx.c also had a separate latent bug: the pitch calculation used fpga->rgb32 (the video/core pixel format) instead of the rgb32 parameter (the menu pixel format), producing wrong bytes-per-pixel when core and menu formats differed. The menu_bits assignment had the same bug. Both fixed to use the incoming parameter. Thread-safety: set_texture_frame and the frame read-site both run on the video thread (threaded video) or main thread (non-threaded), sequentially within the same loop iteration. No synchronization required, none added. The realloc pattern additionally closes a transient NULL window that existed between the free and malloc in the original code.
1 parent c0551a8 commit 7a488b8

2 files changed

Lines changed: 38 additions & 35 deletions

File tree

gfx/drivers/caca_gfx.c

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ typedef struct caca
4949
caca_dither_t *dither;
5050
caca_display_t *display;
5151
unsigned char *menu_frame;
52+
size_t menu_frame_cap;
5253
unsigned menu_width;
5354
unsigned menu_height;
5455
unsigned menu_pitch;
@@ -371,27 +372,29 @@ static void caca_set_texture_frame(void *data,
371372
const void *frame, bool rgb32, unsigned width, unsigned height,
372373
float alpha)
373374
{
374-
caca_t *caca = (caca_t*)data;
375-
unsigned pitch = width * 2;
375+
caca_t *caca = (caca_t*)data;
376+
unsigned pitch = width * (rgb32 ? 4 : 2);
377+
size_t required;
376378

377-
if (rgb32)
378-
pitch = width * 4;
379+
if (!frame || !width || !height || !pitch)
380+
return;
379381

380-
if (caca->menu_frame)
381-
free(caca->menu_frame);
382-
caca->menu_frame = NULL;
382+
required = (size_t)pitch * (size_t)height;
383383

384-
if ( (!caca->menu_frame)
385-
|| (caca->menu_width != width)
386-
|| (caca->menu_height != height)
387-
|| (caca->menu_pitch != pitch))
384+
if (required > caca->menu_frame_cap)
388385
{
389-
if (pitch && height)
390-
caca->menu_frame = (unsigned char*)malloc(pitch * height);
386+
unsigned char *tmp = (unsigned char*)realloc(
387+
caca->menu_frame, required);
388+
if (!tmp)
389+
return; /* keep previous frame intact */
390+
caca->menu_frame = tmp;
391+
caca->menu_frame_cap = required;
391392
}
392393

393-
if (caca->menu_frame && frame && pitch && height)
394-
memcpy(caca->menu_frame, frame, pitch * height);
394+
memcpy(caca->menu_frame, frame, required);
395+
caca->menu_width = width;
396+
caca->menu_height = height;
397+
caca->menu_pitch = pitch;
395398
}
396399

397400
static const video_poke_interface_t caca_poke_interface = {

gfx/drivers/fpga_gfx.c

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ typedef struct fpga
5353
RegOp regOp; /* ptr alignment */
5454
volatile unsigned *framebuffer;
5555
unsigned char *menu_frame;
56+
size_t menu_frame_cap;
5657
unsigned menu_width;
5758
unsigned menu_height;
5859
unsigned menu_pitch;
@@ -307,31 +308,30 @@ static void fpga_set_texture_frame(void *data,
307308
const void *frame, bool rgb32, unsigned width, unsigned height,
308309
float alpha)
309310
{
310-
fpga_t *fpga = (fpga_t*)data;
311-
unsigned pitch = width * 2;
311+
fpga_t *fpga = (fpga_t*)data;
312+
unsigned pitch = width * (rgb32 ? 4 : 2);
313+
size_t required;
312314

313-
if (fpga->rgb32)
314-
pitch = width * 4;
315-
316-
if (fpga->menu_frame)
317-
free(fpga->menu_frame);
318-
fpga->menu_frame = NULL;
315+
if (!frame || !width || !height || !pitch)
316+
return;
319317

320-
if ( !fpga->menu_frame ||
321-
fpga->menu_width != width ||
322-
fpga->menu_height != height ||
323-
fpga->menu_pitch != pitch)
324-
if (pitch && height)
325-
fpga->menu_frame = (unsigned char*)malloc(pitch * height);
318+
required = (size_t)pitch * (size_t)height;
326319

327-
if (fpga->menu_frame && frame && pitch && height)
320+
if (required > fpga->menu_frame_cap)
328321
{
329-
memcpy(fpga->menu_frame, frame, pitch * height);
330-
fpga->menu_width = width;
331-
fpga->menu_height = height;
332-
fpga->menu_pitch = pitch;
333-
fpga->menu_bits = fpga->rgb32 ? 32 : 16;
322+
unsigned char *tmp = (unsigned char*)realloc(
323+
fpga->menu_frame, required);
324+
if (!tmp)
325+
return; /* keep previous frame intact */
326+
fpga->menu_frame = tmp;
327+
fpga->menu_frame_cap = required;
334328
}
329+
330+
memcpy(fpga->menu_frame, frame, required);
331+
fpga->menu_width = width;
332+
fpga->menu_height = height;
333+
fpga->menu_pitch = pitch;
334+
fpga->menu_bits = rgb32 ? 32 : 16;
335335
}
336336

337337
/* TODO/FIXME - implement */

0 commit comments

Comments
 (0)