Skip to content

Commit efdd0bd

Browse files
committed
perf(map): optimize map rendering loop and fix zoom refresh
- Tune mapRenderTask yield to 40ms/25FPS, doubling continuous draw time. - Fix UI desync forcing async redraw on zoom and GPS toggle events. - Unroll render passes. Iterate layers once instead of twice, removing redundant pass checks and the intermediate renderNavFeature function.
1 parent dc6d194 commit efdd0bd

3 files changed

Lines changed: 68 additions & 61 deletions

File tree

lib/gui/src/mainScr.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,7 @@ void mapToolBarEvent(lv_event_t *event)
363363
lv_obj_clear_flag(navArrow, LV_OBJ_FLAG_HIDDEN);
364364
lv_subject_set_int(&subject_map_offset_x, mapView.offsetX);
365365
lv_subject_set_int(&subject_map_offset_y, mapView.offsetY);
366+
triggerMapRedraw();
366367
}
367368
else
368369
{
@@ -521,6 +522,7 @@ void zoomEvent(lv_event_t *event)
521522
mapView.updateMap();
522523
lv_subject_set_int(&subject_map_offset_x, mapView.offsetX);
523524
lv_subject_set_int(&subject_map_offset_y, mapView.offsetY);
525+
triggerMapRedraw();
524526
lv_label_set_text_fmt(zoomLabel, "%2d", zoom);
525527
}
526528

lib/maps/src/maps.cpp

Lines changed: 66 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -603,44 +603,82 @@ void Maps::mapRenderTask(void* pvParameters)
603603
uint32_t lastYield = millis();
604604
uint32_t loopCounter = 0;
605605

606-
for (uint8_t pass = 1; pass <= 2 && !aborted; pass++)
606+
for (int i = 0; i < 16 && !aborted; i++)
607607
{
608-
for (int i = 0; i < 16 && !aborted; i++)
609-
{
610-
const auto& layer = instance->layers[i];
611-
if (layer.empty())
612-
continue;
608+
const auto& layer = instance->layers[i];
609+
if (layer.empty())
610+
continue;
613611

614-
for (uint16_t idx : layer)
612+
// Pass 1: Polygons, Points, and LineString Outlines (Casing)
613+
for (uint16_t idx : layer)
614+
{
615+
if ((++loopCounter & 31) == 0)
615616
{
616-
if ((++loopCounter & 15) == 0)
617+
uint32_t now = millis();
618+
if (now - lastYield > 40)
617619
{
618-
uint32_t now = millis();
619-
if (now - lastYield > 20)
620+
instance->mapTempSprite.endWrite();
621+
xSemaphoreGiveRecursive(instance->mapMutex);
622+
vTaskDelay(pdMS_TO_TICKS(2));
623+
if (xSemaphoreTakeRecursive(instance->mapMutex, pdMS_TO_TICKS(100)) != pdTRUE)
624+
{
625+
aborted = true;
626+
break;
627+
}
628+
if (!instance->pendingTiles.empty())
620629
{
621-
instance->mapTempSprite.endWrite();
622-
xSemaphoreGiveRecursive(instance->mapMutex);
623-
vTaskDelay(1);
624-
if (xSemaphoreTakeRecursive(instance->mapMutex, pdMS_TO_TICKS(100)) != pdTRUE)
625-
{
626-
aborted = true;
627-
break;
628-
}
629-
if (!instance->pendingTiles.empty())
630-
{
631-
aborted = true;
632-
break;
633-
}
634-
instance->mapTempSprite.startWrite();
635-
lastYield = millis();
630+
aborted = true;
631+
break;
636632
}
633+
instance->mapTempSprite.startWrite();
634+
lastYield = millis();
637635
}
636+
}
637+
638+
const auto& feat = instance->featurePool[idx];
639+
if (feat.geomType == NavGeomType::Polygon)
640+
instance->renderNavPolygon(feat, instance->mapTempSprite);
641+
else if (feat.geomType == NavGeomType::Point)
642+
instance->renderNavPoint(feat, instance->mapTempSprite);
643+
else if (feat.geomType == NavGeomType::LineString)
644+
instance->renderNavLineString(feat, instance->mapTempSprite, feat.casing);
645+
}
646+
647+
if (aborted) break;
638648

639-
const auto& feat = instance->featurePool[idx];
640-
instance->renderNavFeature(feat, instance->mapTempSprite, pass, instance->placedLabelsCache);
649+
// Pass 2: LineString bodies and Texts
650+
for (uint16_t idx : layer)
651+
{
652+
if ((++loopCounter & 31) == 0)
653+
{
654+
uint32_t now = millis();
655+
if (now - lastYield > 40)
656+
{
657+
instance->mapTempSprite.endWrite();
658+
xSemaphoreGiveRecursive(instance->mapMutex);
659+
vTaskDelay(pdMS_TO_TICKS(2));
660+
if (xSemaphoreTakeRecursive(instance->mapMutex, pdMS_TO_TICKS(100)) != pdTRUE)
661+
{
662+
aborted = true;
663+
break;
664+
}
665+
if (!instance->pendingTiles.empty())
666+
{
667+
aborted = true;
668+
break;
669+
}
670+
instance->mapTempSprite.startWrite();
671+
lastYield = millis();
672+
}
641673
}
642-
esp_task_wdt_reset();
674+
675+
const auto& feat = instance->featurePool[idx];
676+
if (feat.geomType == NavGeomType::LineString && feat.casing)
677+
instance->renderNavLineString(feat, instance->mapTempSprite, false);
678+
else if (feat.geomType == NavGeomType::Text)
679+
instance->renderNavText(feat, instance->mapTempSprite, instance->placedLabelsCache);
643680
}
681+
esp_task_wdt_reset();
644682
}
645683

646684
if (aborted)
@@ -1457,38 +1495,6 @@ void Maps::renderNavPoint(const FeatureRef& ref, TFT_eSprite& map)
14571495
map.fillCircle(px, py, 3, ref.color);
14581496
}
14591497

1460-
/**
1461-
* @brief Dispatches rendering calls based on geometry type and render pass.
1462-
*
1463-
* @details Orchestrates the drawing sequence in two phases:
1464-
* - **Pass 1:** Renders Polygons, Points, and LineString outlines (casing).
1465-
* - **Pass 2:** Renders LineString main bodies and Text labels.
1466-
*
1467-
* @param ref Reference to the feature data and styling metadata.
1468-
* @param map The target sprite for rendering.
1469-
* @param pass The rendering stage (1 for base/background, 2 for foreground/text).
1470-
* @param placedLabels Tracking list for collision detection and label placement.
1471-
*/
1472-
void Maps::renderNavFeature(const FeatureRef& ref, TFT_eSprite& map, uint8_t pass, std::vector<LabelRect, PsramAllocator<LabelRect>>& placedLabels)
1473-
{
1474-
if (pass == 1)
1475-
{
1476-
if (ref.geomType == NavGeomType::Polygon)
1477-
renderNavPolygon(ref, map);
1478-
else if (ref.geomType == NavGeomType::Point)
1479-
renderNavPoint(ref, map);
1480-
else if (ref.geomType == NavGeomType::LineString)
1481-
renderNavLineString(ref, map, ref.casing);
1482-
}
1483-
else if (pass == 2)
1484-
{
1485-
if (ref.geomType == NavGeomType::LineString && ref.casing)
1486-
renderNavLineString(ref, map, false);
1487-
else if (ref.geomType == NavGeomType::Text)
1488-
renderNavText(ref, map, placedLabels);
1489-
}
1490-
}
1491-
14921498
/**
14931499
* @brief Renders NAV text labels with collision detection.
14941500
*

lib/maps/src/maps.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,6 @@ class Maps
191191
std::vector<uint16_t, PsramAllocator<uint16_t>> ringEndsCache;
192192
std::vector<LabelRect, PsramAllocator<LabelRect>> placedLabelsCache;
193193

194-
void renderNavFeature(const FeatureRef& ref, TFT_eSprite& map, uint8_t pass, std::vector<LabelRect, PsramAllocator<LabelRect>>& placedLabels);
195194
void renderNavLineString(const FeatureRef& ref, TFT_eSprite& map, bool isCasing = false);
196195
void renderNavPolygon(const FeatureRef& ref, TFT_eSprite& map);
197196
void renderNavPoint(const FeatureRef& ref, TFT_eSprite& map);

0 commit comments

Comments
 (0)