Skip to content

Commit 05de9cb

Browse files
committed
gfx/sixel,network: 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). These drivers store their menu state in file-scope static globals rather than struct members (unlike e.g. fpga/caca which carry the state on the driver handle). The globals survive across driver teardown/re-init, so the new capacity variable is explicitly reset to 0 in the *_free path alongside clearing the pointer to NULL; without that, re-init after teardown could skip the realloc on a same-or-smaller first frame and memcpy into the freed pointer. 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 7a488b8 commit 05de9cb

2 files changed

Lines changed: 40 additions & 39 deletions

File tree

gfx/drivers/network_gfx.c

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ typedef struct network
6262
} network_video_t;
6363

6464
static unsigned char *network_menu_frame = NULL;
65+
static size_t network_menu_frame_cap = 0;
6566
static unsigned network_menu_width = 0;
6667
static unsigned network_menu_height = 0;
6768
static unsigned network_menu_pitch = 0;
@@ -371,6 +372,7 @@ static void network_gfx_free(void *data)
371372
free(network_video_temp_buf);
372373

373374
network_menu_frame = NULL;
375+
network_menu_frame_cap = 0;
374376
network_video_temp_buf = NULL;
375377

376378
font_driver_free_osd();
@@ -391,32 +393,29 @@ static void network_set_texture_frame(void *data,
391393
const void *frame, bool rgb32, unsigned width, unsigned height,
392394
float alpha)
393395
{
394-
unsigned pitch = width * 2;
396+
unsigned pitch = width * (rgb32 ? 4 : 2);
397+
size_t required;
395398

396-
if (rgb32)
397-
pitch = width * 4;
398-
399-
if (network_menu_frame)
400-
{
401-
free(network_menu_frame);
402-
network_menu_frame = NULL;
403-
}
399+
if (!frame || !width || !height || !pitch)
400+
return;
404401

405-
if ( !network_menu_frame
406-
|| (network_menu_width != width)
407-
|| (network_menu_height != height)
408-
|| (network_menu_pitch != pitch))
409-
if (pitch && height)
410-
network_menu_frame = (unsigned char*)malloc(pitch * height);
402+
required = (size_t)pitch * (size_t)height;
411403

412-
if (network_menu_frame && frame && pitch && height)
404+
if (required > network_menu_frame_cap)
413405
{
414-
memcpy(network_menu_frame, frame, pitch * height);
415-
network_menu_width = width;
416-
network_menu_height = height;
417-
network_menu_pitch = pitch;
418-
network_menu_bits = rgb32 ? 32 : 16;
406+
unsigned char *tmp = (unsigned char*)realloc(
407+
network_menu_frame, required);
408+
if (!tmp)
409+
return; /* keep previous frame intact */
410+
network_menu_frame = tmp;
411+
network_menu_frame_cap = required;
419412
}
413+
414+
memcpy(network_menu_frame, frame, required);
415+
network_menu_width = width;
416+
network_menu_height = height;
417+
network_menu_pitch = pitch;
418+
network_menu_bits = rgb32 ? 32 : 16;
420419
}
421420

422421
static void network_get_video_output_size(void *data,

gfx/drivers/sixel_gfx.c

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ font_renderer_t sixel_font = {
137137
*/
138138

139139
static unsigned char *sixel_menu_frame = NULL;
140+
static size_t sixel_menu_frame_cap = 0;
140141
static unsigned sixel_menu_width = 0;
141142
static unsigned sixel_menu_height = 0;
142143
static unsigned sixel_menu_pitch = 0;
@@ -532,6 +533,7 @@ static void sixel_gfx_free(void *data)
532533
free(sixel_menu_frame);
533534
sixel_menu_frame = NULL;
534535
}
536+
sixel_menu_frame_cap = 0;
535537

536538
if (sixel_temp_buf)
537539
{
@@ -566,29 +568,29 @@ static void sixel_set_texture_frame(void *data,
566568
const void *frame, bool rgb32, unsigned width, unsigned height,
567569
float alpha)
568570
{
569-
unsigned pitch = width * 2;
571+
unsigned pitch = width * (rgb32 ? 4 : 2);
572+
size_t required;
570573

571-
if (rgb32)
572-
pitch = width * 4;
573-
574-
if (sixel_menu_frame)
575-
{
576-
free(sixel_menu_frame);
577-
sixel_menu_frame = NULL;
578-
}
574+
if (!frame || !width || !height || !pitch)
575+
return;
579576

580-
if (!sixel_menu_frame || sixel_menu_width != width || sixel_menu_height != height || sixel_menu_pitch != pitch)
581-
if (pitch && height)
582-
sixel_menu_frame = (unsigned char*)malloc(pitch * height);
577+
required = (size_t)pitch * (size_t)height;
583578

584-
if (sixel_menu_frame && frame && pitch && height)
579+
if (required > sixel_menu_frame_cap)
585580
{
586-
memcpy(sixel_menu_frame, frame, pitch * height);
587-
sixel_menu_width = width;
588-
sixel_menu_height = height;
589-
sixel_menu_pitch = pitch;
590-
sixel_menu_bits = rgb32 ? 32 : 16;
581+
unsigned char *tmp = (unsigned char*)realloc(
582+
sixel_menu_frame, required);
583+
if (!tmp)
584+
return; /* keep previous frame intact */
585+
sixel_menu_frame = tmp;
586+
sixel_menu_frame_cap = required;
591587
}
588+
589+
memcpy(sixel_menu_frame, frame, required);
590+
sixel_menu_width = width;
591+
sixel_menu_height = height;
592+
sixel_menu_pitch = pitch;
593+
sixel_menu_bits = rgb32 ? 32 : 16;
592594
}
593595

594596
static void sixel_get_video_output_size(void *data,

0 commit comments

Comments
 (0)