moonlight-stream / moonlight-qt

GameStream client for PCs (Windows, Mac, Linux, and Steam Link)
GNU General Public License v3.0
10.04k stars 585 forks source link

Enable 'stretch video to full-screen' feature/setting in Moonlight settings for 3D Full-SBS for AR glasses such as XReal Air #1295

Open mvillarg opened 3 months ago

mvillarg commented 3 months ago

Is your feature request related to a problem? Please describe. This request is aimed to "easily" unleash 3D Full-SBS gaming capabilties when Moonlight client is paired with a set of AR glasses such as XReal Air.

Problem is, the hardware/firmware of these type of glasses is very basic, so they cannot convert 3D Half-SBS output coming from Sunshine (i.e 3840x2160 containing 2 frames for both left and right eyes, each one taking 1920x2160 resolution) to their native 3D Full-SBS res of 3840x1080, this is 1920x1080 per eye. In short, they cannot resize/squeeze the bigger frame height from 2160 to 1080 pixels.

Full-SBS only work for a few games (via Geo-11 fix or post-process effect via Reshade + SuperDepth3D) that can handle 3840x1080 resolution. So the idea is to have Geo-11 or Reshade do its own magic at standard 16:9 aspect ratio in whatever resolution (ideally 3840x2160 for best picture quality, but other resolutions such as 3200x1800 or 2560x1440 would also be welcome) and then having Moonlight on the client side streching that image to 3840x1080 / 32:9 aspect ratio (so basically, squeezing height by half).

Right now what's happening is that Moonlight is maintaining the aspect ratio of the source signal (Sunshine) and centering the image, so black bars appear at both sides of the screen, hence ruining the 3D experience!

Describe the solution you'd like It would be nice to have the 'stretch video to full-screen' setting (as in Android's version of Moonlight) in the Windows (aka QT) version too, so that 3D Full-SBS can be achieved when streaming to a client with AR glasses attached (such as XReal Air) at its native 3D resolution of 3840x1080.

Describe alternatives you've considered

Additional context

mvillarg commented 3 months ago

Watching at the code I saw this at moonlight-qt/app/streaming/video/ffmpeg-renderers/d3d11va.cpp > D3D11VARenderer::setupRenderingResources()


    // Scale video to the window size while preserving aspect ratio
    SDL_Rect src, dst;
    src.x = src.y = 0;
    src.w = m_DecoderParams.width;
    src.h = m_DecoderParams.height;
    dst.x = dst.y = 0;
    dst.w = m_DisplayWidth;
    dst.h = m_DisplayHeight;
    StreamUtils::scaleSourceToDestinationSurface(&src, &dst);

    // Convert screen space to normalized device coordinates
    SDL_FRect renderRect;
    StreamUtils::screenSpaceToNormalizedDeviceCoords(&dst, &renderRect, m_DisplayWidth, m_DisplayHeight);

    VERTEX verts[] =
    {
        {renderRect.x, renderRect.y, 0, 1.0f},
        {renderRect.x, renderRect.y+renderRect.h, 0, 0},
        {renderRect.x+renderRect.w, renderRect.y, 1.0f, 1.0f},
        {renderRect.x+renderRect.w, renderRect.y+renderRect.h, 1.0f, 0},
    };

A separate approach should be taken when enabling 'stretch video to full-screen' in Moonlight settings:

    // DO NOT scale!
    SDL_Rect dst;
    dst.x = dst.y = 0;
    dst.w = m_DisplayWidth;
    dst.h = m_DisplayHeight;

    // Convert screen space to normalized device coordinates
    SDL_FRect renderRect;
    StreamUtils::screenSpaceToNormalizedDeviceCoords(&dst, &renderRect, m_DisplayWidth, m_DisplayHeight);

    VERTEX verts[] =
    {
        {renderRect.x, renderRect.y, 0, 1.0f},
        {renderRect.x, renderRect.y+renderRect.h, 0, 0},
        {renderRect.x+renderRect.w, renderRect.y, 1.0f, 1.0f},
        {renderRect.x+renderRect.w, renderRect.y+renderRect.h, 1.0f, 0},
    };
mvillarg commented 3 months ago

I implemented the above change locally and I can confirm IT JUST WORKS AS EXPECTED :-)

The one thing missing in the implementation is the physical/visible option on the Settings menu, though my QT skills are not there just yet!

The way this works in practical terms is as follows (this is for Windows 11, in Linux/Steam OS might differ): 1) Recommended step: Install Virtual Display Driver and set these resolutions that will later be used in the games (all them are 16:9 aspect ratio). Depending on how beefy our GPU is, we could play at glorious 4K or lower down until constant 60 fps is achievable.