修复了SW2 双击后抖动,
icon 文件改为每帧只加载一次,整帧绘制期间复用,不再每 8 行重复读取。
This commit is contained in:
@@ -55,6 +55,12 @@ typedef struct {
|
||||
size_t step_count;
|
||||
} lcd_direct_request_t;
|
||||
|
||||
typedef struct {
|
||||
lcd_direct_icon_draw_t draw;
|
||||
const lcd_direct_icon_t *icon;
|
||||
lcd_direct_rle_run_t *loaded_runs;
|
||||
} lcd_direct_prepared_icon_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t cmd;
|
||||
uint8_t data[16];
|
||||
@@ -315,19 +321,18 @@ static lcd_direct_rle_run_t *lcd_direct_load_icon_runs(const lcd_direct_icon_t *
|
||||
return runs;
|
||||
}
|
||||
|
||||
static void lcd_direct_overlay_icons(uint16_t *pixel_buffer,
|
||||
uint16_t row_start,
|
||||
uint16_t row_count,
|
||||
const lcd_direct_icon_draw_t *icons,
|
||||
size_t icon_count)
|
||||
static size_t lcd_direct_prepare_icons(const lcd_direct_icon_draw_t *icons,
|
||||
size_t icon_count,
|
||||
lcd_direct_prepared_icon_t *prepared,
|
||||
size_t prepared_capacity)
|
||||
{
|
||||
if (pixel_buffer == NULL || icons == NULL || icon_count == 0U) {
|
||||
return;
|
||||
if (icons == NULL || icon_count == 0U || prepared == NULL || prepared_capacity == 0U) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint16_t row_end = row_start + row_count;
|
||||
for (size_t icon_index = 0; icon_index < icon_count; ++icon_index) {
|
||||
const lcd_direct_icon_draw_t *draw = &icons[icon_index];
|
||||
size_t prepared_count = 0;
|
||||
for (size_t i = 0; i < icon_count && prepared_count < prepared_capacity; ++i) {
|
||||
const lcd_direct_icon_draw_t *draw = &icons[i];
|
||||
const lcd_direct_icon_t *icon = lcd_direct_icon(draw->icon_id);
|
||||
if (icon == NULL || icon->width == 0U || icon->height == 0U) {
|
||||
continue;
|
||||
@@ -337,11 +342,58 @@ static void lcd_direct_overlay_icons(uint16_t *pixel_buffer,
|
||||
}
|
||||
|
||||
lcd_direct_rle_run_t *loaded_runs = NULL;
|
||||
const lcd_direct_rle_run_t *runs = icon->runs;
|
||||
if (runs == NULL) {
|
||||
if (icon->runs == NULL) {
|
||||
loaded_runs = lcd_direct_load_icon_runs(icon);
|
||||
runs = loaded_runs;
|
||||
if (loaded_runs == NULL) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
prepared[prepared_count] = (lcd_direct_prepared_icon_t) {
|
||||
.draw = *draw,
|
||||
.icon = icon,
|
||||
.loaded_runs = loaded_runs,
|
||||
};
|
||||
prepared_count++;
|
||||
}
|
||||
|
||||
return prepared_count;
|
||||
}
|
||||
|
||||
static void lcd_direct_release_prepared_icons(lcd_direct_prepared_icon_t *prepared, size_t prepared_count)
|
||||
{
|
||||
if (prepared == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < prepared_count; ++i) {
|
||||
free(prepared[i].loaded_runs);
|
||||
prepared[i].loaded_runs = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void lcd_direct_overlay_icons(uint16_t *pixel_buffer,
|
||||
uint16_t row_start,
|
||||
uint16_t row_count,
|
||||
const lcd_direct_prepared_icon_t *icons,
|
||||
size_t icon_count)
|
||||
{
|
||||
if (pixel_buffer == NULL || icons == NULL || icon_count == 0U) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint16_t row_end = row_start + row_count;
|
||||
for (size_t icon_index = 0; icon_index < icon_count; ++icon_index) {
|
||||
const lcd_direct_icon_draw_t *draw = &icons[icon_index].draw;
|
||||
const lcd_direct_icon_t *icon = icons[icon_index].icon;
|
||||
if (icon == NULL || icon->width == 0U || icon->height == 0U) {
|
||||
continue;
|
||||
}
|
||||
if (draw->x >= LCD_DIRECT_WIDTH || draw->y >= LCD_DIRECT_HEIGHT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const lcd_direct_rle_run_t *runs = icon->runs != NULL ? icon->runs : icons[icon_index].loaded_runs;
|
||||
if (runs == NULL) {
|
||||
continue;
|
||||
}
|
||||
@@ -358,7 +410,6 @@ static void lcd_direct_overlay_icons(uint16_t *pixel_buffer,
|
||||
const uint16_t overlay_y0 = draw->y;
|
||||
const uint16_t overlay_y1 = draw->y + draw_height;
|
||||
if (overlay_y1 <= row_start || overlay_y0 >= row_end) {
|
||||
free(loaded_runs);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -387,13 +438,11 @@ static void lcd_direct_overlay_icons(uint16_t *pixel_buffer,
|
||||
icon_pixel_pos = run_end;
|
||||
}
|
||||
}
|
||||
|
||||
free(loaded_runs);
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t lcd_direct_draw_rle_memory_image(const lcd_direct_image_t *image,
|
||||
const lcd_direct_icon_draw_t *icons,
|
||||
const lcd_direct_prepared_icon_t *icons,
|
||||
size_t icon_count)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(image != NULL && image->runs != NULL,
|
||||
@@ -448,7 +497,7 @@ static esp_err_t lcd_direct_draw_rle_memory_image(const lcd_direct_image_t *imag
|
||||
}
|
||||
|
||||
static esp_err_t lcd_direct_draw_rle_file_image(const lcd_direct_image_t *image,
|
||||
const lcd_direct_icon_draw_t *icons,
|
||||
const lcd_direct_prepared_icon_t *icons,
|
||||
size_t icon_count)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(image != NULL && image->path != NULL,
|
||||
@@ -547,10 +596,19 @@ static esp_err_t lcd_direct_draw_rle_image(const lcd_direct_image_t *image,
|
||||
ESP_ERR_INVALID_ARG,
|
||||
TAG,
|
||||
"invalid image");
|
||||
lcd_direct_prepared_icon_t prepared_icons[LCD_DIRECT_DEFAULT_ICON_COUNT];
|
||||
size_t prepared_icon_count = lcd_direct_prepare_icons(icons,
|
||||
icon_count,
|
||||
prepared_icons,
|
||||
sizeof(prepared_icons) / sizeof(prepared_icons[0]));
|
||||
esp_err_t err = ESP_OK;
|
||||
if (image->runs != NULL) {
|
||||
return lcd_direct_draw_rle_memory_image(image, icons, icon_count);
|
||||
err = lcd_direct_draw_rle_memory_image(image, prepared_icons, prepared_icon_count);
|
||||
} else {
|
||||
err = lcd_direct_draw_rle_file_image(image, prepared_icons, prepared_icon_count);
|
||||
}
|
||||
return lcd_direct_draw_rle_file_image(image, icons, icon_count);
|
||||
lcd_direct_release_prepared_icons(prepared_icons, prepared_icon_count);
|
||||
return err;
|
||||
}
|
||||
|
||||
static esp_err_t lcd_direct_draw_asset_sequence_once(const lcd_direct_request_t *request)
|
||||
|
||||
Reference in New Issue
Block a user