mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-11-01 10:21:59 +00:00
perf(l2): nothing drawn under the map tiles
- The map screen's own fill is only painted where the map area doesn't cover it (the strip it uncovers as it drifts in); the area and the opaque status bar hide the rest. ~2 ms a frame. - With every visible cell holding a tile, the map area drops its fill and grid, which lie under the tiles anyway, and still reports that it covers what's below (coversOwnArea, shared with the frozen popup image). The Home minimap drops them the same way. ~5 ms a frame. Full map frame ~50 -> 46-48 ms on the L2. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -723,6 +723,7 @@ void UITask::homeMapLayout() {
|
||||
double lat = atan(sinh(M_PI * (1 - 2 * s_cy / (double)n))) * 180.0 / M_PI;
|
||||
s_grid = { left, top, mapview::gridStep(s_z, lat, _prefs && _prefs->units_imperial, 48, sl, sizeof(sl)) };
|
||||
lv_obj_invalidate(s_area);
|
||||
bool tiled = true;
|
||||
for (int j = 0; j < ROWS; j++) {
|
||||
for (int i = 0; i < COLS; i++) {
|
||||
lv_obj_t* cell = s_cells[j * COLS + i];
|
||||
@@ -743,7 +744,11 @@ void UITask::homeMapLayout() {
|
||||
show = mapview::cachedAncestor(s_z, wx, ty, k);
|
||||
}
|
||||
}
|
||||
if (!show) { lv_obj_add_flag(cell, LV_OBJ_FLAG_HIDDEN); continue; }
|
||||
if (!show) {
|
||||
lv_obj_add_flag(cell, LV_OBJ_FLAG_HIDDEN);
|
||||
if (px < w && py < h) tiled = false;
|
||||
continue;
|
||||
}
|
||||
if (lv_image_get_src(img) != &show->dsc) lv_image_set_src(img, &show->dsc);
|
||||
lv_image_set_scale(img, LV_SCALE_NONE << k);
|
||||
int m = (1 << k) - 1;
|
||||
@@ -753,6 +758,7 @@ void UITask::homeMapLayout() {
|
||||
shown++;
|
||||
}
|
||||
}
|
||||
mapview::showTiled(s_area, s_grid, tiled);
|
||||
for (int i = 0; i < s_npts; i++) {
|
||||
double x = mapview::lonToTileX(s_pts[i].lon / 1e6, s_z) * mapview::TILE_PX - left;
|
||||
double y = mapview::latToTileY(s_pts[i].lat / 1e6, s_z) * mapview::TILE_PX - top;
|
||||
|
||||
@@ -69,6 +69,7 @@ static double latToTileY(double lat, int z) {
|
||||
struct Grid {
|
||||
double left = 0, top = 0; // world px of the view's top-left
|
||||
double step_px = 0; // 0: none
|
||||
bool tiled = false; // every visible cell holds a tile: grid and fill are under them
|
||||
};
|
||||
static Grid s_grid; // the main map's
|
||||
static lv_obj_t* s_scale_bar = nullptr;
|
||||
@@ -96,7 +97,7 @@ static double gridStep(int z, double lat, bool imperial, int min_px, char* lbl,
|
||||
// user data is the Grid.
|
||||
static void drawGrid(lv_event_t* e) {
|
||||
const Grid* g = (const Grid*)lv_event_get_user_data(e);
|
||||
if (!g || g->step_px < 8) return;
|
||||
if (!g || g->step_px < 8 || g->tiled) return;
|
||||
lv_obj_t* o = (lv_obj_t*)lv_event_get_target(e);
|
||||
lv_area_t a;
|
||||
lv_obj_get_coords(o, &a);
|
||||
@@ -118,6 +119,38 @@ static void drawGrid(lv_event_t* e) {
|
||||
}
|
||||
}
|
||||
|
||||
// A map area whose visible cells all hold a tile: its fill and grid lie
|
||||
// under them (~5 ms a frame on the main map), so it drops both -- and with
|
||||
// tiledCovers still tells LVGL it hides what's below, so that isn't drawn
|
||||
// either.
|
||||
static void showTiled(lv_obj_t* area, Grid& g, bool tiled) {
|
||||
g.tiled = tiled;
|
||||
lv_opa_t opa = tiled ? LV_OPA_TRANSP : LV_OPA_COVER;
|
||||
if (lv_obj_get_style_bg_opa(area, LV_PART_MAIN) != opa) lv_obj_set_style_bg_opa(area, opa, 0);
|
||||
}
|
||||
static void tiledCovers(lv_event_t* e) { // LV_EVENT_COVER_CHECK, user data the Grid
|
||||
if (((const Grid*)lv_event_get_user_data(e))->tiled) coversOwnArea(e);
|
||||
}
|
||||
|
||||
// The screen under the main map: the map area and the status bar hide all of
|
||||
// it but a strip the area uncovers as it drifts in (Anim.h screenIn). Filled
|
||||
// whole it cost ~2 ms a frame; now only what shows is. User data: the area.
|
||||
static void fillAroundMap(lv_event_t* e) {
|
||||
lv_obj_t* scr = (lv_obj_t*)lv_event_get_target(e);
|
||||
lv_area_t s, m;
|
||||
lv_obj_get_coords(scr, &s);
|
||||
lv_obj_get_coords((lv_obj_t*)lv_event_get_user_data(e), &m);
|
||||
s.y1 = belowStatusBar();
|
||||
const lv_area_t strips[] = { { s.x1, s.y1, s.x2, m.y1 - 1 }, { s.x1, m.y2 + 1, s.x2, s.y2 },
|
||||
{ s.x1, m.y1, m.x1 - 1, m.y2 }, { m.x2 + 1, m.y1, s.x2, m.y2 } };
|
||||
lv_draw_rect_dsc_t d;
|
||||
lv_draw_rect_dsc_init(&d);
|
||||
d.bg_color = lv_obj_get_style_bg_color(scr, LV_PART_MAIN);
|
||||
lv_layer_t* layer = lv_event_get_layer(e);
|
||||
for (const lv_area_t& a : strips)
|
||||
if (a.x1 <= a.x2 && a.y1 <= a.y2) lv_draw_rect(layer, &d, &a);
|
||||
}
|
||||
|
||||
// Markers, remembered so layout can reposition them. `idx` is the Nearby row
|
||||
// (MK_NODE), the waypoint index (MK_WAYPOINT) or the live-share slot (MK_LIVE).
|
||||
enum : uint8_t { MK_NODE, MK_WAYPOINT, MK_LIVE };
|
||||
@@ -347,6 +380,10 @@ void UITask::buildMap() {
|
||||
lv_obj_set_style_bg_color(body, lv_color_hex(0x1A1A1E), 0); // unloaded / missing tiles
|
||||
lv_obj_set_style_bg_opa(body, LV_OPA_COVER, 0);
|
||||
lv_obj_add_event_cb(body, mapview::drawGrid, LV_EVENT_DRAW_MAIN_END, &mapview::s_grid);
|
||||
lv_obj_add_event_cb(body, mapview::tiledCovers, LV_EVENT_COVER_CHECK, &mapview::s_grid);
|
||||
lv_obj_t* scr = lv_obj_get_screen(body);
|
||||
lv_obj_set_style_bg_opa(scr, LV_OPA_TRANSP, 0);
|
||||
lv_obj_add_event_cb(scr, mapview::fillAroundMap, LV_EVENT_DRAW_MAIN, body);
|
||||
lv_obj_add_flag(body, LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_obj_add_event_cb(body, onMapPress, LV_EVENT_PRESSED, NULL);
|
||||
lv_obj_add_event_cb(body, onMapPress, LV_EVENT_PRESSING, NULL);
|
||||
@@ -479,6 +516,7 @@ void UITask::layoutMap() {
|
||||
int n = 1 << _map_z;
|
||||
bool have_provider = mapview::s_available;
|
||||
int shown = 0, missing = 0, over = 0;
|
||||
bool tiled = true;
|
||||
_map_pending = false;
|
||||
|
||||
for (int j = 0; j < mapview::GRID_ROWS; j++) {
|
||||
@@ -518,9 +556,11 @@ void UITask::layoutMap() {
|
||||
if (k > over && !stand_in) over = k;
|
||||
} else {
|
||||
lv_obj_add_flag(cell, LV_OBJ_FLAG_HIDDEN);
|
||||
if (on_screen) tiled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
mapview::showTiled(_map_area, mapview::s_grid, tiled);
|
||||
|
||||
mapview::labels::layout(left, top, w, h, _map_z, have_provider && mapview::s_provider == &mapview::s_vector && mapview::s_vector.hasData(),
|
||||
_map_nav ? navmap::BAR_H : 0);
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
SET_LOOP_TASK_STACK_SIZE(16 * 1024);
|
||||
#endif
|
||||
#include <new>
|
||||
#include <src/core/lv_obj_event_private.h> // lv_cover_check_info_t (freeze::imgCovers)
|
||||
#include <src/core/lv_obj_event_private.h> // lv_cover_check_info_t (coversOwnArea)
|
||||
#include <stdarg.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
@@ -221,6 +221,24 @@ static lv_obj_t* dimOverlay(lv_obj_t* parent) {
|
||||
return o;
|
||||
}
|
||||
|
||||
// LV_EVENT_COVER_CHECK: an opaque thing LVGL can't tell is (an image, a box
|
||||
// drawn by its children) hides all under its own area, and LVGL then starts
|
||||
// drawing from it.
|
||||
static void coversOwnArea(lv_event_t* e) {
|
||||
lv_cover_check_info_t* info = (lv_cover_check_info_t*)lv_event_get_param(e);
|
||||
lv_area_t a;
|
||||
lv_obj_get_coords((lv_obj_t*)lv_event_get_current_target(e), &a);
|
||||
const lv_area_t* r = info->area;
|
||||
if (info->res != LV_COVER_RES_MASKED && r->x1 >= a.x1 && r->y1 >= a.y1 && r->x2 <= a.x2 && r->y2 <= a.y2)
|
||||
info->res = LV_COVER_RES_COVER;
|
||||
}
|
||||
|
||||
static lv_obj_t* s_status_bar = nullptr; // on the top layer, opaque
|
||||
// Where the screen shows below the status bar (its top when the bar is hidden).
|
||||
static int32_t belowStatusBar() {
|
||||
return s_status_bar && !lv_obj_has_flag(s_status_bar, LV_OBJ_FLAG_HIDDEN) ? lv_obj_get_y2(s_status_bar) + 1 : 0;
|
||||
}
|
||||
|
||||
// The screen under an open popup, frozen: once the dim is up, the screen is
|
||||
// drawn once into an image, darkened as the dim layer darkens it, and shown
|
||||
// opaque on top of the screen with the dim layer cleared -- LVGL then draws
|
||||
@@ -248,16 +266,6 @@ namespace freeze {
|
||||
s_owner = s_strip = nullptr;
|
||||
if (s_img) lv_obj_delete(s_img);
|
||||
}
|
||||
// The image hides all under it: LVGL then starts drawing from it. Its own
|
||||
// check says no, an image widget having no background.
|
||||
static void imgCovers(lv_event_t* e) {
|
||||
lv_cover_check_info_t* info = (lv_cover_check_info_t*)lv_event_get_param(e);
|
||||
lv_area_t a;
|
||||
lv_obj_get_coords((lv_obj_t*)lv_event_get_current_target(e), &a);
|
||||
const lv_area_t* r = info->area;
|
||||
if (info->res != LV_COVER_RES_MASKED && r->x1 >= a.x1 && r->y1 >= a.y1 && r->x2 <= a.x2 && r->y2 <= a.y2)
|
||||
info->res = LV_COVER_RES_COVER;
|
||||
}
|
||||
static bool moving(lv_obj_t* scr) { // a screen still sliding / fading in
|
||||
if (lv_display_get_screen_prev(NULL)) return true;
|
||||
for (uint32_t i = 0; i < lv_obj_get_child_count(scr); i++)
|
||||
@@ -298,7 +306,7 @@ namespace freeze {
|
||||
lv_obj_remove_flag(s_img, LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_obj_set_pos(s_img, 0, 0);
|
||||
lv_obj_add_event_cb(s_img, imgDeleted, LV_EVENT_DELETE, buf);
|
||||
lv_obj_add_event_cb(s_img, imgCovers, LV_EVENT_COVER_CHECK, NULL);
|
||||
lv_obj_add_event_cb(s_img, coversOwnArea, LV_EVENT_COVER_CHECK, NULL); // no background: its own check says no
|
||||
if (!top) lv_obj_move_foreground(overlay); // the image under the popup, over the rest
|
||||
s_owner = overlay;
|
||||
lv_obj_set_style_bg_opa(overlay, LV_OPA_TRANSP, 0);
|
||||
@@ -1815,6 +1823,7 @@ void UITask::buildStatusBar() {
|
||||
lv_obj_set_style_text_align(tl, LV_TEXT_ALIGN_CENTER, 0);
|
||||
lv_obj_add_flag(_toast, LV_OBJ_FLAG_HIDDEN);
|
||||
lv_obj_t* bar = lv_obj_create(lv_layer_top());
|
||||
s_status_bar = bar;
|
||||
styleOpaque(bar, theme::BG);
|
||||
lv_obj_remove_flag(bar, LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_obj_remove_flag(bar, LV_OBJ_FLAG_CLICKABLE);
|
||||
|
||||
Reference in New Issue
Block a user