Skip to content

batocera-splash: fix rotation from wrong connector - #16331

Open
Pyohwan wants to merge 2 commits into
batocera-linux:masterfrom
Pyohwan:upstream-splash-connector-rotate-fix
Open

Pyohwan wants to merge 2 commits into
batocera-linux:masterfrom
Pyohwan:upstream-splash-connector-rotate-fix

Conversation

@Pyohwan

@Pyohwan Pyohwan commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Ssystem-splash's fallback (used when batocera-boot.conf has no display.rotate entry yet) grabbed whichever display.rotate.<connector> line came first in the sysconfig file, regardless of which connector was active. Boards defining more than one such line (e.g. a secondary panel that needs rotating while the primary doesn't) get whatever the file ordering happens to be - on the ODROID-M1, an HDMI-only boot picked up the DSI panel's rotation and rendered the boot logo sideways.

Fix: detect the active connector (same batocera-drminfo approach S65values4boot already uses) and match its own display.rotate.<connector> key, falling back to a bare display.rotate= default, then to the old first-match behavior only if the connector can't be detected yet.

Verified on hardware (HDMI-only, secondary panel disabled): with the fix, rotation resolves to none and the logo renders upright; reverting just the connector-detection block back to the old first-match logic reproduces the sideways logo.

@Pyohwan
Pyohwan marked this pull request as ready for review August 30, 2026 03:24
@dmanlfc

dmanlfc commented Aug 30, 2026

Copy link
Copy Markdown
Collaborator

@Pyohwan please use less of the GenAI commentary and keep comments to a minimum in code and the details of the problem too. we don't have the time to read pages of GenAI justification blurb and testing scenarios to state a simple fact or problem.

@Pyohwan
Pyohwan force-pushed the upstream-splash-connector-rotate-fix branch from 4576fa4 to b50fd94 Compare August 30, 2026 05:21
@Pyohwan

Pyohwan commented Aug 30, 2026

Copy link
Copy Markdown
Contributor Author

Trimmed the code comment and PR description. Thanks for the feedback.

@Pyohwan Pyohwan changed the title batocera-splash: match the active connector's rotate key, not the first one batocera-splash: fix rotation from wrong connector Aug 30, 2026
@dmanlfc

dmanlfc commented Aug 30, 2026

Copy link
Copy Markdown
Collaborator

In the snippet, grep is running inside the for loop for every card, and then piped to head -1. It is cleaner and more efficient to let the loop emit all output, then pipe once into grep and head.

@Pyohwan

Pyohwan commented Aug 30, 2026

Copy link
Copy Markdown
Contributor Author

Good catch, fixed - grep now runs once after the loop instead of once per card.

@Pyohwan
Pyohwan force-pushed the upstream-splash-connector-rotate-fix branch from b50fd94 to 26b304c Compare August 30, 2026 06:01
…st one

Ssystem-splash's fallback (used when batocera-boot.conf has no display.rotate entry yet) grabbed whichever display.rotate.<connector> line came first in the sysconfig file, regardless of which connector was active. Boards defining more than one such line (e.g. a secondary panel that needs rotating while the primary doesn't) get whatever the file ordering happens to be - on the ODROID-M1, an HDMI-only boot picked up the DSI panel's rotation and rendered the boot logo sideways.

Fix: detect the active connector (same batocera-drminfo approach S65values4boot already uses) and match its own display.rotate.<connector> key, falling back to a bare display.rotate= default, then to the old first-match behavior only if the connector can't be detected yet.
@Pyohwan
Pyohwan force-pushed the upstream-splash-connector-rotate-fix branch from 26b304c to 4e8a0c7 Compare August 30, 2026 06:05
@dmanlfc

dmanlfc commented Aug 30, 2026

Copy link
Copy Markdown
Collaborator

There is just one last small detail you should bring back: whitespace stripping at the end.
If you use just cut -d'=' -f2, any trailing newline or spaces in the config file will stay in $video_rotation.
Adding | tr -d '[:space:]' ensures it is always a clean value (e.g. "1" instead of "1 ").

@Pyohwan

Pyohwan commented Aug 30, 2026

Copy link
Copy Markdown
Contributor Author

This is already handled - there's an unconditional video_rotation=$(echo "${video_rotation}" | tr -d '[:space:]') a few lines below (outside this diff's context), which runs after both the batocera-boot.conf and MODEL_CONF fallback paths regardless of which one set it. So no gap here.

@dmanlfc

dmanlfc commented Aug 30, 2026

Copy link
Copy Markdown
Collaborator

actually we probably need to handle this better...

try this...

#!/bin/sh

# This is the BATOCERA system splash service
# It shows the unique BATOCERA logo in early boot stage

LOG_FILE="/var/log/splash.log"

do_start () {
    LOG_DIR="${LOG_FILE%/*}"
    [ -d "${LOG_DIR}" ] || mkdir -p "${LOG_DIR}"
    exec >> "${LOG_FILE}" 2>&1
    
    if [ ! -e /dev/fb0 ]; then
        i=0
        while [ ! -e /dev/fb0 ] && [ $i -lt 50 ]; do
            sleep 0.1
            i=$((i + 1))
        done
        if [ ! -e /dev/fb0 ]; then
            echo "Error: Framebuffer device /dev/fb0 not found."
            exit 1
        fi
    fi
    
    # Default image
    image="/usr/share/batocera/splash/boot-logo.png"
    # Standard FBV options
    FBV_OPTS="-f -e -i -y"   
    # Variables for screen dimensions
    WIDTH=""
    HEIGHT=""

    # Detect active DRM connector type (batocera-drminfo returns "EDP", "DSI", "HDMIA", etc.)
    effectiveDrmOutput=$(for GPU in /dev/dri/card*; do batocera-drminfo "${GPU}" "current" 2>/dev/null | grep -oP '^[0-9]+\.[0-9]+:\K[^ ]+'; done | head -1)

    V_BOARD_MODEL=$(batocera-model)
    video_rotation=""
    BOOT_CONF="/boot/batocera-boot.conf"
    MODEL_CONF="/usr/share/batocera/sysconfigs/batocera.conf.${V_BOARD_MODEL}"

    # Check connector-specific settings
    if [ -n "${effectiveDrmOutput}" ]; then
        if [ -f "${BOOT_CONF}" ]; then
            video_rotation=$(/usr/bin/batocera-settings-get -f "${BOOT_CONF}" "display.rotate.${effectiveDrmOutput}")
        fi
        if [ -z "${video_rotation}" ] && [ -f "${MODEL_CONF}" ]; then
            video_rotation=$(grep -iE "^display\.rotate\.${effectiveDrmOutput}=" "${MODEL_CONF}" | head -1 | cut -d'=' -f2)
        fi
    fi

    # Fall back to generic global settings
    if [ -z "${video_rotation}" ]; then
        if [ -f "${BOOT_CONF}" ]; then
            video_rotation=$(/usr/bin/batocera-settings-get -f "${BOOT_CONF}" "display.rotate")
        fi
        if [ -z "${video_rotation}" ] && [ -f "${MODEL_CONF}" ]; then
            video_rotation=$(grep -iE '^display\.rotate=' "${MODEL_CONF}" | head -1 | cut -d'=' -f2)
        fi
    fi

    video_rotation=$(echo "${video_rotation}" | tr -d '[:space:]')
    echo "Active DRM Output: [${effectiveDrmOutput}]"
    echo "Final Rotation Value: [${video_rotation}]"
    
    # Get the screen's physical dimensions
    if [ -r /sys/class/graphics/fb0/modes ]; then
        if read -r MODE_STR < /sys/class/graphics/fb0/modes; then
            DIM_PART=${MODE_STR#*:}
            WIDTH=${DIM_PART%%x*}
            remaining=${DIM_PART#*x}
            HEIGHT=${remaining%%[!0-9]*}
        fi

        if [ -n "${WIDTH}" ] && [ -n "${HEIGHT}" ]; then
            echo "Resolution detected via modes: ${WIDTH}x${HEIGHT}"
            
            # Determine target size for cropping.
            # If rotated 90 or 270 degrees (1 or 3), swap width and height.
            if [ "${video_rotation}" = "1" ] || [ "${video_rotation}" = "3" ]; then
                CROP_WIDTH="${HEIGHT}"
                CROP_HEIGHT="${WIDTH}"
            else
                CROP_WIDTH="${WIDTH}"
                CROP_HEIGHT="${HEIGHT}"
            fi

            # Automatically crops and centers the master logo to target aspect ratio
            cropped_image="/tmp/boot-logo-cropped.bmp"
            if [ -f "${image}" ]; then
                echo "Pre-cropping logo to logical size ${CROP_WIDTH}x${CROP_HEIGHT} via FFmpeg..."
                if ffmpeg -y -threads 1 -sws_flags fast_bilinear \
                    -i "${image}" \
                    -vf "scale=w=${CROP_WIDTH}:h=${CROP_HEIGHT}:force_original_aspect_ratio=increase,crop=${CROP_WIDTH}:${CROP_HEIGHT}" \
                    "${cropped_image}" >/dev/null 2>&1 \
                   && [ -f "${cropped_image}" ]; then
                    image="${cropped_image}"
                fi
            fi
        fi
    fi

    if ! [ -f "${image}" ]; then
        echo "Error: Splash image not found at ${image}"
        exit 1
    fi

    case "${video_rotation}" in
        1|2|3)
            FBV_OPTS="${FBV_OPTS} -o ${video_rotation}"
            echo "Applying FBV rotation: -o ${video_rotation}"
            ;;
    esac

    MODELOPTS="/etc/opts.${V_BOARD_MODEL}"
    [ -e "${MODELOPTS}" ] && . "${MODELOPTS}"

    echo "Executing Command: fbv ${FBV_OPTS} \"${image}\""
    fbv ${FBV_OPTS} "${image}" >/dev/null 2>&1
}

do_stop () {
    [ -e /dev/fb0 ] && dd if=/dev/zero of=/dev/fb0 >/dev/null 2>&1
}

case "$1" in
    start)
        do_start &
        ;;
    stop)
        do_stop
        ;;
    *)
        echo "Usage: $0 {start|stop}"
        exit 1
        ;;
esac

exit $?

let me know

BOOT_CONF's own display.rotate.* lookup still grabbed whichever key
happened to appear first in the file, the same bug MODEL_CONF had.
Extend the active-connector match to both files consistently instead
of only fixing it in one.

Co-Authored-By: dmanlfc <noreply@github.com>
@Pyohwan

Pyohwan commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

Tested this live. Fake key ordering in batocera-boot.conf (display.rotate.FAKE=1 then display.rotate.HDMIA=2), old code grabbed the wrong one, your version matched the active connector correctly regardless of order. Regression test on the dual-connector (HDMI+DSI both active) case also passed, same behavior on both versions.

One thing I noticed: I don't think the BOOT_CONF connector-specific match ever actually fires. emulationstation-standalone writes display.rotate.<key> using whatever batocera-resolution listOutputs returns ("N - NAME" form, e.g. display.rotate.1 - DSI), not batocera-drminfo's bare name (DSI) that this script looks for. Couldn't find anywhere in the codebase that writes a display.rotate.<bare-name> key into batocera-boot.conf, so this specific check looks unreachable as things stand. Not blocking, just flagging it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants