mirror of
https://github.com/meshtastic/firmware.git
synced 2026-11-07 23:04:49 -05:00
fix(screen): compile the MUI mirror out unless it is opted into
setMirror cleared muiOwner outside any guard, so every board without a TFT failed to compile — the member only exists on the MUI path. The assignment was redundant anyway: freeSnapshotLocked() releases the pool and the ownership claim together. The guards were also drawn on HAS_TFT while the code they protect needs a device-ui carrying the flush observer, so a color build that never opts in still carried the rect queue in .bss. Replaces the ad-hoc HAS_SCREEN_MIRROR && defined(MESHTASTIC_MUI_MIRROR) pairs with a single derived HAS_MUI_MIRROR next to HAS_SCREEN_MIRROR, and gates the queue, the pool, the input seam and their declarations on it. Verified on all three build shapes: t-deck-tft with the opt-in, picomputer-s3 (TFT, opted out) and heltec-v3 (no TFT).
This commit is contained in:
1 parent
418843f7b6
commit
2d384a9fa5
6 files changed
+29
-20
No files matched your search
@@ -681,6 +681,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define HAS_SCREEN_MIRROR 0
|
||||
#endif
|
||||
|
||||
// Mirroring MUI (device-ui/LVGL) streams RGB565 dirty rects instead of the
|
||||
// 1bpp framebuffer, and needs a device-ui carrying the flush observer. Until
|
||||
// that lands upstream the whole path - queue, pool and input seam - compiles
|
||||
// out, so a color build that does not opt in carries none of it.
|
||||
#if HAS_SCREEN_MIRROR && HAS_TFT && defined(MESHTASTIC_MUI_MIRROR)
|
||||
#define HAS_MUI_MIRROR 1
|
||||
#else
|
||||
#define HAS_MUI_MIRROR 0
|
||||
#endif
|
||||
|
||||
#ifndef USE_ETHERNET_DEFAULT
|
||||
#define USE_ETHERNET_DEFAULT 0
|
||||
#endif
|
||||
|
||||
@@ -40,7 +40,7 @@ void ScreenMirror::freeSnapshotLocked()
|
||||
}
|
||||
paletteSig = 0;
|
||||
paletteCount = 0;
|
||||
#if HAS_TFT
|
||||
#if HAS_MUI_MIRROR
|
||||
if (muiPool) {
|
||||
memaudit::add("display", -(int32_t)MUI_POOL_BYTES);
|
||||
free(muiPool);
|
||||
@@ -64,14 +64,13 @@ void ScreenMirror::setMirror(bool enabled)
|
||||
// Force an immediate frame so the client doesn't wait for the next
|
||||
// on-screen change.
|
||||
oneShot = true;
|
||||
#if HAS_TFT
|
||||
#if HAS_MUI_MIRROR
|
||||
if (muiRefresh)
|
||||
muiRefresh(); // MUI delivers "a frame" as a full-repaint rect burst
|
||||
#endif
|
||||
} else {
|
||||
oneShot = false;
|
||||
freeSnapshotLocked();
|
||||
muiOwner = nullptr;
|
||||
freeSnapshotLocked(); // also releases the MUI pool and rect ownership
|
||||
}
|
||||
if (changed)
|
||||
LOG_INFO("Screen mirror %s", enabled ? "enabled" : "disabled");
|
||||
@@ -81,7 +80,7 @@ void ScreenMirror::requestFrame()
|
||||
{
|
||||
concurrency::LockGuard g(&lock);
|
||||
oneShot = true;
|
||||
#if HAS_TFT
|
||||
#if HAS_MUI_MIRROR
|
||||
if (muiRefresh)
|
||||
muiRefresh();
|
||||
#endif
|
||||
@@ -212,7 +211,7 @@ bool ScreenMirror::copyPaletteChunk(uint32_t &clientPaletteSig, uint8_t &clientR
|
||||
return true;
|
||||
}
|
||||
|
||||
#if HAS_TFT
|
||||
#if HAS_MUI_MIRROR
|
||||
void ScreenMirror::onMuiRect(int16_t x, int16_t y, uint16_t w, uint16_t h, const uint16_t *pixels)
|
||||
{
|
||||
uint32_t readyId = 0;
|
||||
@@ -309,7 +308,7 @@ bool ScreenMirror::copyMuiChunkLocked(meshtastic_DisplayFrame &out)
|
||||
bool ScreenMirror::hasChunkFor(const void *client, uint32_t clientFrameId, uint16_t clientOffset)
|
||||
{
|
||||
concurrency::LockGuard g(&lock);
|
||||
#if HAS_TFT
|
||||
#if HAS_MUI_MIRROR
|
||||
// One shared rect cursor means one consumer; another connection simply
|
||||
// sees no rects rather than stealing half of each frame.
|
||||
if (muiCount && (muiOwner == nullptr || muiOwner == client))
|
||||
@@ -321,7 +320,7 @@ bool ScreenMirror::hasChunkFor(const void *client, uint32_t clientFrameId, uint1
|
||||
bool ScreenMirror::copyChunk(const void *client, uint32_t &clientFrameId, uint16_t &clientOffset, meshtastic_DisplayFrame &out)
|
||||
{
|
||||
concurrency::LockGuard g(&lock);
|
||||
#if HAS_TFT
|
||||
#if HAS_MUI_MIRROR
|
||||
// MUI rects drain ahead of (and on MUI builds, instead of) mono snapshots.
|
||||
// Spike scope: the rect queue has a single consumer, not per-client cursors.
|
||||
if (muiCount) {
|
||||
|
||||
@@ -58,7 +58,7 @@ class ScreenMirror
|
||||
/// when the client holds the full current palette (or coloring is off).
|
||||
bool copyPaletteChunk(uint32_t &clientPaletteSig, uint8_t &clientRegionOffset, meshtastic_DisplayPalette &out);
|
||||
|
||||
#if HAS_TFT
|
||||
#if HAS_MUI_MIRROR
|
||||
/// MUI path: queues one LVGL dirty rect (native little-endian RGB565).
|
||||
/// Called on the LVGL thread via the device-ui flush observer; copies and returns.
|
||||
void onMuiRect(int16_t x, int16_t y, uint16_t w, uint16_t h, const uint16_t *pixels);
|
||||
@@ -101,7 +101,7 @@ class ScreenMirror
|
||||
uint16_t paletteDefaultOn = 0;
|
||||
uint16_t paletteDefaultOff = 0;
|
||||
|
||||
#if HAS_TFT
|
||||
#if HAS_MUI_MIRROR
|
||||
// MUI dirty-rect queue: FIFO rect headers over a linear pixel pool,
|
||||
// compacted whenever it drains. Spike scope: single consumer.
|
||||
struct MuiRect {
|
||||
@@ -131,7 +131,7 @@ class ScreenMirror
|
||||
|
||||
extern ScreenMirror screenMirror;
|
||||
|
||||
#if HAS_TFT
|
||||
#if HAS_MUI_MIRROR
|
||||
/**
|
||||
* Routes a remote input event straight into device-ui's injection seam.
|
||||
* MUI builds never construct an InputBroker (Modules.cpp skips it when
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include "graphics/driver/DisplayDriver.h"
|
||||
#include "graphics/driver/DisplayDriverConfig.h"
|
||||
#include "input/InputBroker.h"
|
||||
#if defined(MESHTASTIC_MUI_MIRROR)
|
||||
#if HAS_MUI_MIRROR
|
||||
#include "input/InputDriver.h"
|
||||
#endif
|
||||
#include "util/ISpiLock.h"
|
||||
@@ -321,12 +321,9 @@ class ReentrantSpiLock : public ISpiLock
|
||||
|
||||
static ReentrantSpiLock reentrantSpiLock;
|
||||
|
||||
#if HAS_SCREEN_MIRROR && defined(MESHTASTIC_MUI_MIRROR)
|
||||
#if HAS_MUI_MIRROR
|
||||
namespace graphics
|
||||
{
|
||||
// Maps a remote input event onto device-ui's virtual LVGL devices. Note the
|
||||
// LEFT/RIGHT cross-map: the broker's codes were modeled on LVGL keys but
|
||||
// those two are swapped.
|
||||
// Reports MUI's logical panel geometry for DeviceMetadata.display. The BaseUI
|
||||
// `screen` object does not exist on MUI builds, so the dimensions come from
|
||||
// LVGL itself (already rotated to the logical orientation).
|
||||
@@ -347,6 +344,9 @@ bool muiDisplayInfo(uint16_t &width, uint16_t &height, bool &hasTouch)
|
||||
return width > 0 && height > 0;
|
||||
}
|
||||
|
||||
// Maps a remote input event onto device-ui's virtual LVGL devices. Note the
|
||||
// LEFT/RIGHT cross-map: the broker's codes were modeled on LVGL keys but
|
||||
// those two are swapped.
|
||||
bool muiInjectInputEvent(uint32_t eventCode, uint32_t kbChar, uint32_t touchX, uint32_t touchY)
|
||||
{
|
||||
if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR)
|
||||
@@ -412,7 +412,7 @@ void tftSetup(void)
|
||||
I2CKeyboardScanner::setSecondaryBus(i2cProxy);
|
||||
#endif
|
||||
#ifndef ARCH_PORTDUINO
|
||||
#if HAS_SCREEN_MIRROR && defined(MESHTASTIC_MUI_MIRROR)
|
||||
#if HAS_MUI_MIRROR
|
||||
// Must precede DeviceScreen::init: device-ui only builds its virtual input
|
||||
// devices (and the default focus group they need) when injection is asked for.
|
||||
InputDriver::enableInjection();
|
||||
@@ -420,7 +420,7 @@ void tftSetup(void)
|
||||
deviceScreen = &DeviceScreen::create(reentrantSpiLock);
|
||||
PacketAPI::create(PacketServer::init());
|
||||
deviceScreen->init(new PacketClient);
|
||||
#if HAS_SCREEN_MIRROR && defined(MESHTASTIC_MUI_MIRROR)
|
||||
#if HAS_MUI_MIRROR
|
||||
// Stream MUI's dirty rects to local clients (see graphics::ScreenMirror).
|
||||
// Gated on MESHTASTIC_MUI_MIRROR until the device-ui flush observer merges
|
||||
// (jamesarich/device-ui screen-mirror-poc); the vendored pin lacks it.
|
||||
|
||||
+1
-1
@@ -1394,7 +1394,7 @@ extern meshtastic_DeviceMetadata getDeviceMetadata()
|
||||
deviceMetadata.has_xeddsa = true;
|
||||
#endif
|
||||
|
||||
#if HAS_TFT && HAS_SCREEN_MIRROR && defined(MESHTASTIC_MUI_MIRROR)
|
||||
#if HAS_MUI_MIRROR
|
||||
// MUI owns the panel and leaves `screen` null, so ask LVGL instead.
|
||||
uint16_t muiW = 0, muiH = 0;
|
||||
bool muiTouch = false;
|
||||
|
||||
@@ -2186,7 +2186,7 @@ void AdminModule::handleSendInputEvent(const meshtastic_AdminMessage_InputEvent
|
||||
// Wake the device if asleep
|
||||
powerFSM.trigger(EVENT_INPUT);
|
||||
|
||||
#if HAS_SCREEN_MIRROR && defined(MESHTASTIC_MUI_MIRROR)
|
||||
#if HAS_MUI_MIRROR
|
||||
// MUI builds never construct an InputBroker (Modules.cpp skips it when
|
||||
// displaymode is COLOR), so remote input reaches the LVGL UI directly.
|
||||
if (graphics::muiInjectInputEvent(inputEvent.event_code, inputEvent.kb_char, inputEvent.touch_x, inputEvent.touch_y))
|
||||
|
||||
Reference in new issue
Block a user