Skip to content

Commit

Permalink
rg_display: Added rg_display_clear_except
Browse files Browse the repository at this point in the history
In some cases we can clear everything except the viewport (because it's about to be overwritten).

This reduces flicker when entering/leaving menus.
  • Loading branch information
ducalex committed Dec 17, 2024
1 parent 61621dc commit 157ae61
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 29 deletions.
64 changes: 38 additions & 26 deletions components/retro-go/rg_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -314,11 +314,10 @@ static void display_task(void *arg)
// Clear the screen if the viewport doesn't cover the entire screen because garbage could remain on the sides
if (display.viewport.width < display.screen.width || display.viewport.height < display.screen.height)
{
// FIXME: It would reduce flicker if we filled only the areas outside the viewport...
if (border)
rg_display_write(0, 0, border->width, border->height, 0, border->data, RG_DISPLAY_WRITE_NOSYNC);
rg_display_write_rect(0, 0, border->width, border->height, 0, border->data, RG_DISPLAY_WRITE_NOSYNC);
else
rg_display_clear(C_BLACK);
rg_display_clear_except(display.viewport.left, display.viewport.top, display.viewport.width, display.viewport.height, C_BLACK);
}
display.changed = false;
}
Expand Down Expand Up @@ -461,16 +460,10 @@ bool rg_display_sync(bool block)
return !rg_task_messages_waiting(display_task_queue);
}

void rg_display_write(int left, int top, int width, int height, int stride, const uint16_t *buffer, uint32_t flags)
void rg_display_write_rect(int left, int top, int width, int height, int stride, const uint16_t *buffer, uint32_t flags)
{
RG_ASSERT_ARG(buffer);

// Offsets can be negative to indicate N pixels from the end
if (left < 0)
left += display.screen.width;
if (top < 0)
top += display.screen.height;

// calc stride before clipping width
stride = RG_MAX(stride, width * 2);

Expand Down Expand Up @@ -523,27 +516,46 @@ void rg_display_write(int left, int top, int width, int height, int stride, cons
lcd_sync();
}

void rg_display_clear(uint16_t color_le)
void rg_display_clear_rect(int left, int top, int width, int height, uint16_t color_le)
{
// We ignore margins here, we want to fill the entire
int screen_width = display.screen.real_width;
int screen_height = display.screen.real_height;

lcd_set_window(0, 0, screen_width, screen_height);

uint16_t color_be = (color_le << 8) | (color_le >> 8);
for (size_t y = 0; y < screen_height;)
const uint16_t color_be = (color_le << 8) | (color_le >> 8);
int pixels_remaining = width * height;
if (pixels_remaining > 0)
{
uint16_t *buffer = lcd_get_buffer(LCD_BUFFER_LENGTH);
size_t num_lines = RG_MIN(LCD_BUFFER_LENGTH / screen_width, screen_height - y);
size_t pixels = screen_width * num_lines;
for (size_t j = 0; j < pixels; ++j)
buffer[j] = color_be;
lcd_send_buffer(buffer, pixels);
y += num_lines;
lcd_set_window(left + display.screen.margin_left, top + display.screen.margin_top, width, height);
while (pixels_remaining > 0)
{
uint16_t *buffer = lcd_get_buffer(LCD_BUFFER_LENGTH);
int pixels = RG_MIN(pixels_remaining, LCD_BUFFER_LENGTH);
for (size_t j = 0; j < pixels; ++j)
buffer[j] = color_be;
lcd_send_buffer(buffer, pixels);
pixels_remaining -= pixels;
}
}
}

void rg_display_clear_except(int left, int top, int width, int height, uint16_t color_le)
{
// Clear everything except the specified area
// FIXME: Do not ignore left/top...
int left_offset = -display.screen.margin_left;
int top_offset = -display.screen.margin_top;
int horiz = (display.screen.real_width - width + 1) / 2;
int vert = (display.screen.real_height - height + 1) / 2;
rg_display_clear_rect(left_offset, top_offset, horiz, display.screen.real_height, color_le); // Left
rg_display_clear_rect(left_offset + horiz + width, top_offset, horiz, display.screen.real_height, color_le); // Right
rg_display_clear_rect(left_offset + horiz, top_offset, display.screen.real_width - horiz * 2, vert, color_le); // Top
rg_display_clear_rect(left_offset + horiz, top_offset + vert + height, display.screen.real_width - horiz * 2, vert, color_le); // Bottom
}

void rg_display_clear(uint16_t color_le)
{
// We ignore margins here, we want to fill the entire screen
rg_display_clear_rect(-display.screen.margin_left, -display.screen.margin_top, display.screen.real_width,
display.screen.real_height, color_le);
}

void rg_display_deinit(void)
{
rg_task_send(display_task_queue, &(rg_task_msg_t){.type = RG_TASK_MSG_STOP});
Expand Down
4 changes: 3 additions & 1 deletion components/retro-go/rg_display.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,9 @@ typedef struct

void rg_display_init(void);
void rg_display_deinit(void);
void rg_display_write(int left, int top, int width, int height, int stride, const uint16_t *buffer, uint32_t flags);
void rg_display_write_rect(int left, int top, int width, int height, int stride, const uint16_t *buffer, uint32_t flags);
void rg_display_clear_rect(int left, int top, int width, int height, uint16_t color_le);
void rg_display_clear_except(int left, int top, int width, int height, uint16_t color_le);
void rg_display_clear(uint16_t color_le);
bool rg_display_sync(bool block);
void rg_display_force_redraw(void);
Expand Down
4 changes: 2 additions & 2 deletions components/retro-go/rg_gui.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ void rg_gui_copy_buffer(int left, int top, int width, int height, int stride, co
}
else
{
rg_display_write(left, top, width, height, stride, buffer, 0);
rg_display_write_rect(left, top, width, height, stride, buffer, 0);
}
}

Expand Down Expand Up @@ -600,7 +600,7 @@ void rg_gui_draw_icons(void)

void rg_gui_draw_hourglass(void)
{
rg_display_write((gui.screen_width / 2) - (image_hourglass.width / 2),
rg_display_write_rect((gui.screen_width / 2) - (image_hourglass.width / 2),
(gui.screen_height / 2) - (image_hourglass.height / 2),
image_hourglass.width,
image_hourglass.height,
Expand Down

0 comments on commit 157ae61

Please sign in to comment.