瀏覽代碼

Revert to EGLFS backend, keep Pi 5 QML rotation

Switch back from linuxfb to EGLFS for proper GPU-accelerated rendering:

- EGLFS provides hardware compositing and proper scene graph management
- Eliminates console bleed-through and partial rendering issues
- No need for forced repaint hacks

Changes:
- run.sh: Use EGLFS with eglfs_kms integration
- install.sh: Generate EGLFS service configuration
- dune-weaver-touch.service: EGLFS environment variables
- main.py: Enable Pi 5 rotation regardless of backend
- main.qml: Remove linuxfb repaint hacks (Canvas, timers, visibility toggle)

Pi 5 rotation is still handled via QML transform (rotationContainer)
since EGLFS may not support native rotation on Pi 5.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
tuanchris 1 月之前
父節點
當前提交
4ef0f1dd00

+ 8 - 5
dune-weaver-touch/dune-weaver-touch.service

@@ -2,17 +2,20 @@
 Description=Dune Weaver Touch Interface
 After=multi-user.target network-online.target
 Wants=network-online.target
+# Wait for DRM/KMS devices to be ready
+After=systemd-udev-settle.service
+Wants=systemd-udev-settle.service
 
 [Service]
 Type=simple
 User=pi
 Group=pi
 WorkingDirectory=/home/pi/dune-weaver-touch
-Environment=QT_QPA_PLATFORM=linuxfb:fb=/dev/fb0
-Environment=QT_QPA_FB_HIDECURSOR=1
-# Hide console cursor before starting (fallback if kernel param not set)
-ExecStartPre=/bin/sh -c 'echo 0 > /sys/class/graphics/fbcon/cursor_blink || true'
-ExecStartPre=/bin/sh -c 'setterm --cursor off > /dev/tty1 || true'
+Environment=QT_QPA_PLATFORM=eglfs
+Environment=QT_QPA_EGLFS_ALWAYS_SET_MODE=1
+Environment=QT_QPA_EGLFS_HIDECURSOR=1
+Environment=QT_QPA_EGLFS_INTEGRATION=eglfs_kms
+Environment=QT_QPA_EGLFS_KMS_ATOMIC=1
 ExecStart=/home/pi/dune-weaver-touch/venv/bin/python /home/pi/dune-weaver-touch/main.py
 Restart=always
 RestartSec=10

+ 11 - 8
dune-weaver-touch/install.sh

@@ -63,26 +63,29 @@ setup_systemd() {
 
     local SERVICE_FILE="/etc/systemd/system/dune-weaver-touch.service"
 
-    # Generate service file with linuxfb backend (works on all Pi models)
-    # Pi 5 rotation is handled in QML (linuxfb rotation parameter requires Qt patch)
-    echo "   ℹ️  Using linuxfb backend"
+    # Generate service file with EGLFS backend (GPU-accelerated, proper compositing)
+    # Pi 5 rotation is handled in QML since EGLFS rotation may not work on Pi 5
+    echo "   ℹ️  Using EGLFS backend (GPU-accelerated)"
 
     cat > "$SERVICE_FILE" << EOF
 [Unit]
 Description=Dune Weaver Touch Interface
 After=multi-user.target network-online.target
 Wants=network-online.target
+# Wait for DRM/KMS devices to be ready
+After=systemd-udev-settle.service
+Wants=systemd-udev-settle.service
 
 [Service]
 Type=simple
 User=$ACTUAL_USER
 Group=$ACTUAL_USER
 WorkingDirectory=$SCRIPT_DIR
-Environment=QT_QPA_PLATFORM=linuxfb:fb=/dev/fb0
-Environment=QT_QPA_FB_HIDECURSOR=1
-# Hide console cursor before starting (fallback if kernel param not set)
-ExecStartPre=/bin/sh -c 'echo 0 > /sys/class/graphics/fbcon/cursor_blink || true'
-ExecStartPre=/bin/sh -c 'setterm --cursor off > /dev/tty1 || true'
+Environment=QT_QPA_PLATFORM=eglfs
+Environment=QT_QPA_EGLFS_ALWAYS_SET_MODE=1
+Environment=QT_QPA_EGLFS_HIDECURSOR=1
+Environment=QT_QPA_EGLFS_INTEGRATION=eglfs_kms
+Environment=QT_QPA_EGLFS_KMS_ATOMIC=1
 ExecStart=$SCRIPT_DIR/venv/bin/python $SCRIPT_DIR/main.py
 Restart=always
 RestartSec=10

+ 4 - 3
dune-weaver-touch/main.py

@@ -120,11 +120,12 @@ def main():
     # Load QML
     engine = QQmlApplicationEngine()
 
-    # Set rotation flag for Pi 5 (linuxfb doesn't support rotation parameter)
-    rotate_display = is_pi5() and 'linuxfb' in os.environ.get('QT_QPA_PLATFORM', '')
+    # Set rotation flag for Pi 5 (display needs 180° rotation via QML)
+    # This applies regardless of Qt backend (eglfs or linuxfb)
+    rotate_display = is_pi5()
     engine.rootContext().setContextProperty("rotateDisplay", rotate_display)
     if rotate_display:
-        logger.info("🔄 Pi 5 detected with linuxfb - enabling QML rotation")
+        logger.info("🔄 Pi 5 detected - enabling QML rotation (180°)")
 
     qml_file = Path(__file__).parent / "qml" / "main.qml"
     engine.load(QUrl.fromLocalFile(str(qml_file)))

+ 1 - 74
dune-weaver-touch/qml/main.qml

@@ -24,28 +24,10 @@ ApplicationWindow {
     property string currentPatternName: ""
     property string currentPatternPreview: ""
 
-    // Property to force full repaint on linuxfb (toggle to trigger update)
-    property bool forceRepaint: false
-
     onCurrentPageIndexChanged: {
         console.log("📱 currentPageIndex changed to:", currentPageIndex)
     }
 
-    // Force full repaint function - call when screen wakes up
-    // On linuxfb, we need to force Qt to redraw the ENTIRE scene graph,
-    // not just individual components. The trick is to briefly hide/show
-    // the content which forces Qt to mark everything as dirty.
-    function triggerFullRepaint() {
-        console.log("🔄 Triggering full repaint for linuxfb")
-        forceRepaint = !forceRepaint
-        fullScreenBackground.requestPaint()
-
-        // Force entire scene graph repaint by toggling visibility
-        // This marks all items as dirty and forces a complete redraw
-        rotationContainer.visible = false
-        repaintRestoreTimer.start()
-    }
-    
     onShouldNavigateToExecutionChanged: {
         if (shouldNavigateToExecution) {
             console.log("🎯 Navigating to execution page")
@@ -91,12 +73,6 @@ ApplicationWindow {
         
         onScreenStateChanged: function(isOn) {
             console.log("🖥️ Screen state changed:", isOn ? "ON" : "OFF")
-            if (isOn) {
-                // Force full repaint when screen wakes up on linuxfb
-                // This is necessary because linuxfb doesn't automatically
-                // redraw the entire framebuffer after unblank
-                repaintTimer.start()
-            }
         }
         
         onBackendConnectionChanged: function(connected) {
@@ -138,56 +114,7 @@ ApplicationWindow {
         id: patternModel
     }
 
-    // Timer to delay repaint slightly after screen wake (ensures framebuffer is ready)
-    Timer {
-        id: repaintTimer
-        interval: 150  // 150ms delay for framebuffer to be ready
-        repeat: false
-        onTriggered: {
-            window.triggerFullRepaint()
-        }
-    }
-
-    // Timer to restore visibility after hiding (completes the force-repaint trick)
-    Timer {
-        id: repaintRestoreTimer
-        interval: 50  // Brief 50ms hide
-        repeat: false
-        onTriggered: {
-            rotationContainer.visible = true
-            console.log("🎨 Full scene repaint completed")
-        }
-    }
-
-    // Full-screen opaque background using Canvas for forced repaint capability
-    // This is essential for linuxfb which doesn't have proper compositing
-    // and shows the Linux console through transparent areas
-    Canvas {
-        id: fullScreenBackground
-        anchors.fill: parent
-        z: -1  // Behind everything else
-
-        // Repaint when forceRepaint toggles or theme changes
-        property color bgColor: Components.ThemeManager.backgroundColor
-        property bool repaintTrigger: window.forceRepaint
-
-        onBgColorChanged: requestPaint()
-        onRepaintTriggerChanged: requestPaint()
-
-        onPaint: {
-            var ctx = getContext("2d")
-            ctx.fillStyle = bgColor
-            ctx.fillRect(0, 0, width, height)
-            console.log("🎨 Full screen background painted:", width, "x", height)
-        }
-
-        Component.onCompleted: {
-            // Force initial paint
-            requestPaint()
-        }
-    }
-
-    // Rotation container for Pi 5 linuxfb
+    // Rotation container for Pi 5
     Item {
         id: rotationContainer
         anchors.fill: parent

+ 15 - 10
dune-weaver-touch/run.sh

@@ -57,17 +57,22 @@ if [[ "$OSTYPE" == "darwin"* ]]; then
     echo "   Platform: macOS (using native cocoa backend)"
     export QT_QPA_PLATFORM=""  # Let Qt use default
 elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
-    # Linux/Raspberry Pi - use linuxfb for all Pi models
-    # Pi 5 rotation is handled in QML (linuxfb rotation parameter requires Qt patch)
-    if [ -e /dev/fb0 ]; then
-        echo "   Platform: Linux (using linuxfb backend)"
-        export QT_QPA_PLATFORM=linuxfb:fb=/dev/fb0
-        export QT_QPA_FB_HIDECURSOR=1
-        # Hide console cursor (the blinking underscore)
-        echo 0 > /sys/class/graphics/fbcon/cursor_blink 2>/dev/null || true
-        setterm --cursor off > /dev/tty1 2>/dev/null || true
+    # Linux - check for DRM devices to determine if eglfs is available
+    if [ -e /dev/dri/card0 ] || [ -e /dev/dri/card1 ]; then
+        echo "   Platform: Linux with DRM (using eglfs backend)"
+        export QT_QPA_PLATFORM=eglfs
+        export QT_QPA_EGLFS_INTEGRATION=eglfs_kms
+        export QT_QPA_EGLFS_KMS_ATOMIC=1
+        export QT_QPA_EGLFS_HIDECURSOR=1
+        export QT_QPA_EGLFS_ALWAYS_SET_MODE=1
+
+        # Use eglfs_config.json if available
+        if [ -f "$SCRIPT_DIR/eglfs_config.json" ]; then
+            echo "   Using eglfs config: $SCRIPT_DIR/eglfs_config.json"
+            export QT_QPA_EGLFS_KMS_CONFIG="$SCRIPT_DIR/eglfs_config.json"
+        fi
     else
-        echo "   Platform: Linux (using xcb/X11 backend)"
+        echo "   Platform: Linux without DRM (using xcb/X11 backend)"
         export QT_QPA_PLATFORM=xcb
     fi
 else