LookingGlass

GitHub

An extremely low latency KVMFR (KVM FrameRelay) implementation for guests with VGA PCI Passthrough.

RAW Doc

Doc/Audio

.. _client_audio:

Audio and microphone
####################

The client selects audio independently from video and input. The current LGMP
transport does not provide audio, so SPICE normally supplies it in an IDD
setup. Selecting SPICE as the primary video transport also uses its audio
provider.

.. warning::

Do not use Scream for a Looking Glass setup. Use the built-in classic SPICE
or USB audio path. Scream over IVSHMEM can also conflict with the shared
device used for Looking Glass frames.

Looking Glass offers two SPICE audio paths:

USB audio (recommended)
Presents an emulated Looking Glass USB Audio Class 2 device to Windows over
a SPICE USB channel. It supports stereo, quadraphonic, 5.1 and 7.1 playback
using 24-bit PCM at up to 192 kHz. It also provides asynchronous playback
feedback and a lower-latency clock relationship with supported Linux audio
backends. This path is enabled by default when it is available.

Classic SPICE audio
Uses a virtual guest sound card and SPICE playback and record channels.
QEMU limits it to stereo, 16-bit samples at 48 kHz. Use it as a compatibility
fallback when the emulated USB audio device is not available.

Set `spice:audio=no to disable both paths.

.. _client_usb_audio:

USB audio setup
---------------

USB audio requires:

* a client built with libusbredirparser-0.5 version 0.7.1 or newer;
* at least one unused SPICE USB redirection channel in the VM; and
* a working client playback backend.

For libvirt, add a USB redirection device:

.. code:: xml

<redirdev bus='usb' type='spicevmc'/>

In virt-manager, this is a USB Redirector device using the SPICE channel.
It is dedicated to the virtual Looking Glass audio device while USB audio is
active.

The emulated USB audio device is enabled by default. Its settings are:

.. code-block:: ini

[spice]
audio=yes
usbAudio=yes

Playback supports stereo, quadraphonic, 5.1 and 7.1 speaker layouts using
24-bit PCM at sample rates up to 192 kHz. Recording supports stereo at up to
192 kHz.

After the device connects, select the Looking Glass USB Audio speakers as the
Windows output device.

If USB audio could not be created at startup, the client falls back to classic
SPICE audio and logs the reason. A working USB audio device also requires the
SPICE USB redirection channel to connect; if the channel is absent, add it to
the VM rather than reinstalling the Windows endpoint.

Classic SPICE setup
-------------------

Add an Intel HDA sound device and a SPICE audio backend to the VM as shown in
:ref:
libvirt_spice_server, then select the classic path:

.. code-block:: ini

[spice]
audio=yes
usbAudio=no

QEMU's classic SPICE audio implementation exposes a fixed stereo format: two
channels, 16-bit samples at 48 kHz. Use the emulated USB audio device when
other sample rates, sample formats or channel layouts are required.

Microphone access
-----------------

PipeWire supports playback and recording. The current PulseAudio backend does
not provide microphone recording. Press :kbd:
ScrLk + :kbd:E to toggle
recording when it is available.

When a guest application opens the microphone, audio:micDefault controls
the response:

prompt
Ask before sending microphone audio. This is the default.

allow
Allow requests automatically.

deny
Refuse requests automatically.

Press :kbd:ScrLk + :kbd:C to cycle this policy. Keep
audio:micShowIndicator=yes to show when recording is active.

Latency settings
----------------

audio:periodSize requests the audio backend period in samples. The default
is 512; 0 requests a 10 ms period. Smaller values may reduce latency but also
make underruns more likely.

audio:latencyOffset applies only to classic SPICE audio. It adds safety
margin to the calculated minimum buffer; the default is 6 ms. Reduce it only
after confirming that classic SPICE playback remains free of dropouts under
load.

audio:resampler also applies only to classic SPICE audio. The default
auto setting chooses the appropriate path; the other choices are
libsamplerate and backend. The emulated USB audio device instead uses
feedback to adjust the Windows packet rate.

Set audio:debug=yes to log ring-buffer level, backend delay, clock feedback
and underrun or overrun counts. Disable it after diagnosis to keep the normal
log concise.

---

Doc/Build

.. _building:

Build the Linux client
######################

The Looking Glass Client is currently distributed as source code. Building it
is a normal part of installation, not an optional developer step. These
instructions require basic familiarity with a Linux shell.

.. _download_source:

Downloading
-----------

Visit the Looking Glass Download Page <https://looking-glass.io/downloads>__,
and download the stable version (Recommended).
You can also download a bleeding-edge version, or the latest RC version
during a Release Candidate cycle.

Developers can clone the source code repo with git.

.. code:: bash

git clone --recursive https://github.com/gnif/LookingGlass.git

.. warning::

Please only clone from Git if you're a developer, and know what you're
doing. Looking Glass requires git submodules that must be setup and updated
when building. Source code downloads from the website come bundled with the
necessary submodules.

.. note::

The current client, IDD and OBS plugin must come from the same Looking Glass
release. Bleeding-edge builds must be paired with their matching
bleeding-edge components. Legacy Host users must instead use the complete
matching B7 stack described in :ref:
legacy_host_policy.

.. _build_client_section:

Client Application
------------------

.. _installing_build_dependencies:

Installing build dependencies
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

These required libraries and tools should be installed first.

.. note::

The below list of dependencies is for Debian. A community maintained list of
dependencies for other distributions for the current stable version of
Looking Glass is maintained on the wiki at:
https://looking-glass.io/wiki/Installation_on_other_distributions

.. _client_dependencies:

Required dependencies
^^^^^^^^^^^^^^^^^^^^^

..
Editor note: Listed dependencies are Debian packages containing the
required resources. All dependencies must be explicitly defined.
Omitting required dependencies that happen to be pulled in via
Depends: or Recommends: from another listed package is not allowed.
All required packages must be listed.

- cmake
-
binutils
-
gcc, g++ \| clang
-
libegl-dev
-
libgl-dev
-
libgles-dev
-
libfontconfig-dev
-
libgmp-dev
-
libspice-protocol-dev
-
libxkbcommon-dev
-
make
-
nettle-dev
-
pkg-config

.. _client_deps_may_be_disabled:

May be disabled
<<<<<<<<<<<<<<<

These dependencies are required by default, but may be omitted if their
feature is disabled when running :ref:
cmake <client_building>.

- Disable with cmake -DENABLE_BACKTRACE=no ..

- libdw-dev
-
libunwind-dev

- Disable with cmake -DENABLE_X11=no ..

- libx11-dev
-
libxfixes-dev
-
libxi-dev
-
libxinerama-dev
-
libxss-dev
-
libxcursor-dev
-
libxpresent-dev
-
libxrandr-dev

- Disable with cmake -DENABLE_WAYLAND=no ..

- libwayland-bin
-
libwayland-dev

- Disable all audio support with cmake -DENABLE_AUDIO=no ..

- libpipewire-0.3-dev
-
libpulse-dev
-
libsamplerate0-dev
-
libusbredirparser-dev

- Disable with cmake -DENABLE_PIPEWIRE=no ..

- libpipewire-0.3-dev

- Disable with cmake -DENABLE_PULSEAUDIO=no ..

- libpulse-dev

- Disable USB audio with cmake -DENABLE_USB_AUDIO=no ..

- libusbredirparser-dev version 0.7.1 or newer

libsamplerate0-dev is required whenever audio support remains enabled.

.. _client_deps_recommended:

Recommended
<<<<<<<<<<<

- fonts-dejavu-core (This is the default UI font, but a random font will
be chosen if not available).

.. _client_fetching_with_apt:

Fetching with APT
^^^^^^^^^^^^^^^^^

You can fetch these dependencies with the following command:

.. warning::

The command below builds both PipeWire and PulseAudio playback backends.
Omit one development package only when also disabling its backend in CMake.
Microphone recording requires PipeWire; the current PulseAudio backend is
playback-only.

.. code:: bash

apt-get install binutils cmake make fonts-dejavu-core libdw-dev \
libfontconfig-dev libgmp-dev libunwind-dev gcc g++ pkg-config \
libegl-dev libgl-dev libgles-dev libspice-protocol-dev nettle-dev \
libx11-dev libxcursor-dev libxfixes-dev libxi-dev libxinerama-dev \
libxpresent-dev libxrandr-dev libxss-dev libxkbcommon-dev \
libwayland-bin libwayland-dev \
libpipewire-0.3-dev libpulse-dev libsamplerate0-dev \
libusbredirparser-dev

You may omit some dependencies if you disable the feature which requires them
when running :ref:
cmake <client_building>.
(See :ref:
client_deps_may_be_disabled)

.. _client_building:

Building
~~~~~~~~

If you've downloaded the source code as a zip file, simply unzip and cd
into the new directory. If you've cloned the repo with
git, then cd
into the LookingGlass directory.

.. code:: bash

mkdir client/build
cd client/build
cmake ../
make

This will build the looking-glass-client binary, which is used to display
frames from the guest. It also produces
looking-glass-client.debug. Keep
this file with the matching binary to obtain source locations in crash stack
traces. The install target places it in the standard
bin/.debug location
automatically.

You can then :ref:continue installing Looking Glass <client_install>, or run
it directly from the build directory:

.. code:: bash

./looking-glass-client

.. seealso::

- :ref:Client installation <client_install>
- :ref:
Client usage <client_usage>

.. note::

For users running GNOME on Wayland, you may want to enable libdecor when
building.

.. code:: bash

cmake -DENABLE_LIBDECOR=ON ../

For details, see :ref:the FAQ <gnome_wayland_decorations>.

.. note::

The most common compile error is related to backtrace support. Try disabling
this when building:

.. code:: bash

cmake -DENABLE_BACKTRACE=0 ../

If you disable this and need support for a crash, use gdb to obtain a
backtrace manually.

---

Doc/Build Host

.. _host_building:

Legacy Host Application build
#############################

.. warning::

The Host Application is a legacy server application. New installations should
use the prebuilt :doc:
Looking Glass IDD <install_idd>. These build
instructions are retained for the complete matching B7 stack described in
:ref:
legacy_host_policy.

.. note::

Host in this context refers to the Looking Glass (LG) host server application,
to which the LG client connects to, it thus does not refer to the
host OS!

A common setup is to have a host OS running a guest VM. In such a setup
the
client application runs on the host OS; and the host application
on the
guest VM.

The term Host application was chosen over Guest application, because LG
can be run in a VM to VM configuration, in which case both Host Application and
Client Application are run inside VM Guests.

These instructions help you build the host yourself from the
:ref:
downloaded source code <download_source>.

.. warning::
:name: dont-build-the-host

Building the host from source code is not recommended for most purposes,
and should only be attempted by users who are prepared to handle issues
on their own. Please download the pre-built binary installers from
https://looking-glass.io/downloads for stability, and increased support.

.. note::

The pre-built binaries also include NvFBC support built in, which is
only available to current Nvidia SDK license holders, and cannot
be enabled when building the host without also having a license.

(link <#dont-build-the-host>_)

.. _host_win_on_win:

For Windows on Windows
~~~~~~~~~~~~~~~~~~~~~~

1. Download and install msys2 x86_64 from
http://www.msys2.org/ <http://www.msys2.org/>__ following the setup
instructions provided

2. Run the MSYS2 shell

3. Download build dependencies with pacman

.. code:: bash

pacman -Fy
pacman -Sy git make mingw-w64-x86_64-gcc mingw-w64-x86_64-cmake

4. Change directory to the source tree with cd

5. Configure the project and build it

.. code:: bash

mkdir host/build
cd host/build
cmake -G "MSYS Makefiles" ..
make

.. _host_linux_on_linux:

For Linux on Linux
~~~~~~~~~~~~~~~~~~

Make a host/build directory, then run cmake

.. code:: bash

mkdir host/build
cd host/build
cmake ..
make

.. _host_win_cross_on_linux:

For Windows cross compiling on Linux
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Like :ref:host_linux_on_linux, but using the mingw64 toolchain to
cross-compile a Windows
.exe file.

.. code:: bash

mkdir host/build
cd host/build
cmake -DCMAKE_TOOLCHAIN_FILE=../toolchain-mingw64.cmake ..
make

.. _host_build_installer:

Building the Windows installer
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

1. :ref:Build <host_win_cross_on_linux> the host on Linux.

2. Install nsis

.. code:: bash

apt-get install nsis

3. Use makensis to build the installer.

.. code:: bash

cd host/build/platform/Windows
makensis installer.nsi

.. _host_questions:

This will build looking-glass-host-setup.exe under
host/build/platform/Windows/looking-glass-host-setup.exe

.. seealso::

:ref:Installing the Host <host_install>

---

Doc/Credits

.. _looking_glass_team:

Looking Glass team
##################

A list of the wonderful people who make this possible.

.. _lg_devs:

Developers
------------------

* gnif (Geoffrey McRae)
* quantum (Guanzhong Chen)
* xyene (Tudor Brindus)
* spencercw (Chris Spencer)

.. _lg_documentation_guys:

Documentation
-------------

* JJRcop (Jonathan Rubenstein)

---

Doc/Display

.. _client_display:

Display and image quality
#########################

The EGL renderer is the supported client renderer and is selected
automatically. The older OpenGL renderer is deprecated, does not provide direct
DMA imports or native HDR, and should only be used to diagnose a compatibility
problem.

Wayland and X11 are both built by default. Automatic selection prefers Wayland
when
WAYLAND_DISPLAY is set, then X11 when DISPLAY is set. To force X11
from a Wayland session for diagnosis, preserve
DISPLAY and unset
WAYLAND_DISPLAY for the client process.

Window and guest resolution
---------------------------

With the IDD, win:setGuestRes=yes asks Windows to match the client viewport
when its size changes. Press :kbd:
ScrLk + :kbd:= to request the current
size immediately. The IDD creates this as its dynamic ExtraMode using the
default refresh configured in the IDD helper.

If a requested resolution does not fit in IVSHMEM, the IDD refuses it and the
helper reports the required size. See :ref:
libvirt_determining_memory.

Useful window options include:

win:autoResize
Resize the client window when the guest resolution changes.

win:keepAspect
Preserve the guest aspect ratio while resizing.

win:fullScreen
Start in borderless full-screen mode.

win:rotate
Rotate the image by 0, 90, 180 or 270 degrees.

Scaling and filters
-------------------

The overlay's EGL filters page controls scaling, sharpening and custom
processing. Filters run from top to bottom and can be reordered. Save useful
combinations as named presets, then select one at startup with
egl:preset.

The built-in filters include:

* a configurable downscaler;
* AMD FidelityFX Super Resolution (FSR); and
* AMD FidelityFX Contrast Adaptive Sharpening (CAS).

The egl:scale option selects automatic, nearest-neighbor or linear
scaling when a filter does not provide the required scaling. Additional
mpv-style GLSL shaders may be loaded from
eglFilter:glslPath. The
Anime4K <https://github.com/bloc97/Anime4K>_ project provides compatible
GLSL filters.

.. _client_hdr:

HDR
---

The IDD exposes HDR only when the Windows runtime provides the required IddCx
interfaces and the IDD is using a hardware render adapter. This normally means
a compatible Windows 11 guest. Windows 10 and IDD software processing remain
on the SDR path.

Native HDR output on Linux requires all of the following:

* the EGL renderer;
* a Wayland compositor with
color-management-v1 support;
* an HDR-capable monitor and output configuration; and
* a host graphics driver that can present the required color format.

With egl:mapHDRtoSDR=yes the client tone-maps HDR frames for an SDR desktop.
Use
egl:peakLuminance to describe the SDR display target and
egl:maxCLL to limit the assumed content light level.

X11 presentation is SDR. The EGL renderer tone-maps HDR to SDR there by
default. Native Wayland PQ output also requires compositor support for ST 2084
and BT.2020, while scRGB requires compositor scRGB support.

Presentation latency
--------------------

The defaults favor low latency rather than conventional buffered rendering.
Do not enable
egl:vsync or egl:doubleBuffer merely to chase a reported
frame-rate number; either can add presentation delay. Use the timing graphs to
confirm the result on the actual compositor and GPU.

win:jitRender delays rendering toward the expected presentation deadline.
It can reduce the age of a frame at display time, but depends on stable timing.
Leave it disabled while diagnosing stalls or an unstable refresh cadence.

---

Doc/Faq

Frequently asked questions
##########################

General
-------

.. _how_does_looking_glass_work:

How does Looking Glass work?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The Windows IDD creates a virtual monitor and places completed frames in an
IVSHMEM region shared with Linux. The client imports the newest frame, renders
it and returns input through the available transport. The image is not encoded
as a video stream, which avoids codec latency and quality loss.

See :doc:overview for the current components. A detailed video explanation
is also available at https://www.youtube.com/watch?v=U44lihtNVVM.

.. _can_i_feed_the_vm_directly_into_obs:

Can I feed the VM directly into OBS?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Yes. The :doc:OBS plugin <obs> is an independent frame consumer and does not
capture the client window.

.. _why_is_my_ups_so_low:

Why is UPS lower than the guest refresh rate?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

UPS counts frames delivered to that consumer, not every frame Windows may
render. The IDD publishes to the deadline requested by the fastest active
client and can skip guest frames that have already been superseded. This saves
memory bandwidth without deliberately adding a frame of latency.

If UPS is below the active consumer's requested rate, use
:ref:
client_performance to locate the slow stage. High resolution, software
processing, memory bandwidth, host scheduling and compositor presentation can
all impose a lower limit.

.. _is_my_gpu_supported:

Is a passed-through GPU required?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

No. The IDD can create an SDR display using software processing when it cannot
use a Windows render adapter. A hardware adapter is strongly recommended for
lower latency, higher refresh rates, HDR, and cadence scheduling.

The Linux client still needs an EGL-capable host graphics driver. Direct
DMA-BUF import depends on the host GPU and driver; the client falls back to a
copy when it is unavailable.

.. _why_do_i_need_spice_if_i_dont_want_a_spice_display_device:

Do I need SPICE?
~~~~~~~~~~~~~~~~

SPICE is not required for the primary IDD video or direct input paths. It is
still useful for clipboard, audio, input fallback and automatic video fallback.
These services are selected independently.

Set spice:enable=no or use -s to disable SPICE completely. Disable an
individual service with
spice:input, spice:clipboard or
spice:audio instead when the other services are still wanted.

.. _where_is_the_host_application_for_linux:

Which application runs on Linux?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The Looking Glass Client runs on the Linux host operating system. The IDD runs
inside the Windows guest. The older product named the Host Application is a
legacy Windows server; “Host” in that name does not mean the Linux host OS.

Input and window system
-----------------------

.. _gnome_wayland_decorations:

Why is there no title bar on GNOME Wayland?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

GNOME does not implement the standard Wayland server-side decoration
protocol. Build Looking Glass with libdecor support:

.. code:: bash

cmake -DENABLE_LIBDECOR=ON ../

Install libdecor-0-dev first on Debian-based systems. Alternatively, hold
the Super key and right-click the window to use the compositor's move and
resize menu.

.. _the_mouse_is_jumpy_slow_laggy_when_using_spice:

Why is SPICE fallback mouse movement different?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The IDD's direct input path uses absolute positioning for normal desktop use
and relative movement in capture mode. SPICE input is relative-only, so guest
mouse acceleration can change its feel or cause temporary position error.

Use the direct IDD input path when available. For a game, use capture mode and
consider
input:rawMouse=yes.

.. _the_cursor_position_doesnt_update_until_i_click:

Should I add a virtual tablet?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

No. Looking Glass does not require an additional virtio tablet, mouse or
keyboard. Direct IDD input provides its own absolute and relative devices, and
SPICE fallback uses the VM's default PS/2 input devices.

Audio
-----

Does Looking Glass support microphone input and surround sound?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Yes. The recommended emulated USB Audio 2.0 device provides stereo,
quadraphonic, 5.1 and 7.1 playback plus stereo recording at rates up to
192 kHz. Classic SPICE audio also provides playback and recording. Client
microphone recording currently requires the PipeWire backend. See
:doc:
audio.

Legacy Host Application
-----------------------

The sections below apply only to the legacy Windows Host Application. New
installations should use the IDD. See :ref:
legacy_host_policy.

.. _faq_host:

Where is the legacy Host log?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The application log is:

%ProgramData%\Looking Glass (host)\looking-glass-host.txt

The service log is:

%ProgramData%\Looking Glass (host)\looking-glass-host-service.txt

.. _faq_host_admin_privs:

Why does the legacy Host require administrator privileges?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The legacy capture APIs use privileged functions for GPU scheduling, NvFBC
setup and secure-desktop capture. The installer runs it as a Windows service
under the SYSTEM account. This is not how the current IDD is configured.

.. _nvfbc_nvidia_capture_api_doesnt_work:

Why does NvFBC not work?
~~~~~~~~~~~~~~~~~~~~~~~~

NvFBC is a legacy Host capture method and requires supported NVIDIA hardware
and SDK licensing. It is not part of the IDD path.

.. _the_screen_stops_updating_when_left_idle_for_a_time:

Why does a legacy captured display stop when idle?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Windows may turn off the physical or dummy display captured by the legacy
Host. Disable display sleep for that monitor. The IDD virtual-monitor path does
not require a physical display.

.. _a_note_about_ivshmem_and_scream_audio:

Can Scream and Looking Glass share IVSHMEM?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Do not use Scream with Looking Glass. Use the built-in classic SPICE or USB
audio path instead. In particular, Scream's IVSHMEM transport can select or
interfere with the shared device used for Looking Glass frames.

Technical details
-----------------

.. toctree::
:maxdepth: 1

tech_faq

---

Doc/Host Usage

.. _host_usage:

Legacy Host Application configuration
#####################################

.. warning::

This page applies only to the legacy Windows Host Application. New
installations should use the IDD. B7 is the last recommended complete stack
when non-capture mouse input through the Host Application is required.

The legacy Host normally selects a compatible frame path automatically. Its
persistent configuration file is:

C:\Program Files\Looking Glass (host)\looking-glass-host.ini

Use options from the same release as the Host binary. Do not copy a current
Host configuration into B7 or combine a B7 Host with a current client.

.. _host_capture:

Capture interface
-----------------

The legacy Host captures an existing Windows display through Desktop
Duplication or NvFBC. It does not use Windows Graphics Capture. Select an
interface only when automatic selection fails:

.. code-block:: ini

[app]
capture=d12

.. _host_capture_d12:

D12
The preferred Direct3D 12 Desktop Duplication path on supported systems. It
can copy directly toward shared memory and supports damage tracking.

.. _host_capture_dxgi:

DXGI
The Direct3D 11 Desktop Duplication compatibility path. It may require an
additional staging copy and can show cursor-related capture jitter.

.. _host_capture_nvfbc:

NvFBC
An NVIDIA SDK path available only with supported hardware and licensing.
It is not required by the IDD or the normal legacy D12 path.

The exact capture-interface options can change between releases. Consult the
binary's help and the configuration comments supplied with that release.

.. _host_select_ivshmem:

Select an IVSHMEM device
------------------------

The legacy Host selects the first IVSHMEM device by default. When the VM has
more than one,
os:shmDevice selects by zero-based device order:

.. code-block:: ini

[os]
shmDevice=1

Check the Host log after changing it; the selected device is marked with an
asterisk. This option is for the legacy Host and is not an IDD helper setting.

.. _host_downsampling:

Downsampling
------------

The legacy Host can reduce a captured resolution before transport. Rules use
source:target syntax and may match resolutions greater than a threshold:

.. code-block:: ini

; Downsample exactly 3840x2160 to 1920x1080
downsample=3840x2160:1920x1080

; Downsample anything larger than 1920x1080
downsample=>1920x1080:1920x1080

This saves transport bandwidth but does not reduce the guest application's
rendering work. IDD users should request the required virtual monitor
resolution instead.

---

Doc/Idd Configuration

.. _idd_configuration:

Configure the IDD
#################

Right-click the Looking Glass (IDD) icon in the Windows notification area
and select Open configuration. The icon and its tooltip also show whether
the driver is using GPU acceleration or software processing.

Display modes
-------------

The mode list controls the resolutions and refresh rates that Windows may use
for the Looking Glass monitor.

* Select a mode to edit its width, height or refresh rate, then select
Update.
* Select <add new>, enter a mode in the fields below the list and select
Update to add it.
* Select Delete to remove the selected mode.
* Select Load default to replace the working list with the standard modes.
* Enable prefer on the mode that Windows should prefer. Only one mode can
be preferred.

Refresh rates may contain up to three decimal places. For example, enter
119.970 rather than rounding it to 120 Hz. Accepted values range from
23.900 Hz to 1000.000 Hz. Width may range from 640 to 16384 pixels and height
from 480 to 16384 pixels.

Edits to the mode list are not applied immediately. Select Save & reload
driver when the list is ready. This saves the list, removes and recreates the
virtual monitor, and can make the display blink briefly. Revert discards
unsaved mode and default-refresh changes.

Default refresh
---------------

Default refresh is used when the client asks the IDD to create a dynamic
resolution. It also supplies the refresh rate when Load default rebuilds
the standard mode list.

Changing this value does not rewrite refresh rates already saved in the normal
mode list. On reload, an existing dynamic mode keeps its resolution and adopts
the new default refresh rate.

The client option win:setGuestRes enables automatic dynamic resolution
requests when the client window changes size. The default is enabled when the
server in the guest supports it. Press the client's escape key together with
= to request the current window resolution manually.

Preferences
-----------

Make LG the only monitor
Makes the Looking Glass display the only active Windows monitor. This is
enabled by default and the helper restores the topology when required.
Disable it if you intentionally use other guest displays at the same time.
Disabling it stops future enforcement but does not automatically restore
displays that Windows has already disabled.

Disable no GPU warning
Suppresses the notification shown when the IDD has fallen back to software
processing. It does not enable GPU acceleration or change the active
adapter.

Unlike mode-list edits, preference checkboxes are saved when clicked.

Software processing
-------------------

If no suitable Windows render adapter is available, the IDD can use software
processing. This provides a display but is slower, cannot provide predictable
high-rate cadence and is limited to SDR. Check the IDD log to see which render
adapter was selected and whether software processing is active.

Modes that do not fit in shared memory
--------------------------------------

At startup the IDD removes modes that cannot fit in the configured IVSHMEM
region. If every suitable mode is filtered, the monitor cannot start. A
dynamic resolution request that is too large is refused and the helper reports
the minimum power-of-two IVSHMEM size needed.

Increase the IVSHMEM size in the VM configuration and restart the VM. The IDD
reads the new capacity when it starts; another helper reload is not normally
required. Allocating more shared memory than required does not improve
performance; it only reserves additional host RAM.

---

Doc/Idd Diagnostics

.. _idd_diagnostics:

IDD status and logs
###################

The IDD helper in the Windows notification area is the first place to check
when the virtual display is missing or slow. Its icon and tooltip report
whether the driver is using GPU acceleration or software processing.

Right-click the helper and open the log directory. The files are stored in:

C:\ProgramData\Looking Glass (IDD)

Collect these files when reporting an IDD fault:

* looking-glass-idd.txt: display creation, GPU selection, modes,
transport and frame scheduling;
*
looking-glass-input.txt: direct keyboard and mouse device activity;
*
looking-glass-idd-service.txt: service and driver control requests; and
*
looking-glass-idd-helper.txt: configuration, topology and user
notifications.

Each log rotates through suffixes .1 to .4. Include the current file
and rotated files when the problem happened before the most recent restart.

Useful IDD lines
----------------

Render adapter
Shows the Windows GPU selected by the IDD. A software-processing warning
explains why HDR, cadence and high frame rates are unavailable.

IVSHMEM size
Confirms which device was opened and its capacity. Compare this with the VM
configuration and :ref:
libvirt_determining_memory.

Filtered mode
A configured mode was omitted because its frame buffers do not fit. Increase
IVSHMEM or remove the oversized mode.

IddCx capabilities
Shows whether the runtime HDR and wide-color-gamut interfaces are
available. Their absence on Windows 10 is expected and does not prevent SDR
use.

Frame schedule owner
Reports the fastest active client's requested rate, guest acquisition rate
and how many frames were published or skipped. Skipping excess guest frames
is expected; it saves memory bandwidth while preserving the newest frame
needed by the client.

Input owner
Identifies the client currently allowed to send direct input. Only one
client can own it at a time.

Client information
------------------

Run the client from a terminal and retain its complete output. Include:

* the client, IDD and OBS versions;
* Linux distribution and kernel;
* X11 or Wayland and the compositor name;
* host and guest GPU models and drivers;
* whether
lgmp:allowDMA is enabled;
* the guest resolution and refresh rate; and
* exact steps that reproduce the fault.

Do not copy only the final error line. Startup output records the selected
transport, renderer, display server, audio backend and import method, which are
often needed to explain it.

---

Doc/Index

Looking Glass |release| documentation
=====================================

Looking Glass is an open-source, low-latency way to use a Windows virtual
machine from Linux. The current setup uses a virtual display in the Windows
guest, shared memory for frames, and a native Linux client for display and
input.

.. toctree::
:maxdepth: 2

overview
requirements
quickstart

build
install

usage
troubleshooting
obs
faq

legacy_host

.. toctree::
:hidden:

credits

More information:

* Official Website <https://looking-glass.io/>_
*
GitHub <https://github.com/gnif/LookingGlass>_
*
Discord <https://discord.gg/52SMupxkvt>_
*
Forum <https://level1techs.com/lg>_
*
Community wiki <https://looking-glass.io/wiki/>_
* IRC - #LookingGlass on
libera.chat <https://libera.chat/>_

Donate:

* GitHub <https://github.com/sponsors/gnif>__
*
Ko-Fi <https://ko-fi.com/lookingglass>_
*
Patreon <https://www.patreon.com/gnif>_
*
PayPal <https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=ESQ72XUPGKXRY>_

Expand a cryptocurrency address to copy it:

.. raw:: html

<details class="donation-address">
<summary>Bitcoin (BTC)</summary>
<code>14ZFcYjsKPiVreHqcaekvHGL846u3ZuT13</code>
</details>
<details class="donation-address">
<summary>Ethereum (ETH)</summary>
<code>0x6f8aEe454384122bF9ed28f025FBCe2Bce98db85</code>
</details>
<details class="donation-address">
<summary>Monero (XMR)</summary>
<code>47xM4zG7b2tEj4mnSywHve4ydZzn3wzhf22snDRB7aSEcXrgUBpoT2Z4phTnyFMi1sMyQtHbdufMYRQ2PzMn3PGUJAE1dpc</code>
</details>

---

Doc/Input

.. _client_input:

Keyboard and mouse input
########################

The current IDD provides keyboard and mouse input directly over LGMP. It uses
absolute positioning for normal desktop use and relative movement in capture
mode. SPICE remains available as a fallback when direct input is unavailable.

The client changes input provider automatically. If the displayed video has
fallen back to SPICE, the client also uses SPICE input so that the picture and
pointer always refer to the same guest.

Only one LGMP client controls direct input at a time. Starting another client
does not give both clients simultaneous control. Disconnecting or restarting
the IDD releases held keys and buttons before ownership changes.

Normal input
------------

Move the pointer into the guest view to use absolute desktop input. This keeps
the guest pointer aligned without requiring capture.

Direct IDD input supports the keyboard, media keys and up to 32 mouse buttons.
SPICE fallback uses relative mouse input and supports fewer extra buttons.

Capture mode
------------

Press the escape key, :kbd:ScrLk by default, to capture the mouse. Capture
mode confines the pointer and sends relative motion, which is appropriate for
games and applications that lock the cursor. Press the escape key again to
leave capture mode.

Common capture options are:

input:captureOnFocus
Enter capture mode whenever the client receives focus.

input:captureOnStart
Start captured.

input:captureOnly
Disable guest input outside capture mode.

input:rawMouse
Use raw relative mouse input in capture mode. This is usually best for
games.

input:mouseSens
Adjust relative sensitivity from -9 to 9. The default is 0.

input:hideCursor
Hide the host cursor while Looking Glass renders the guest cursor.

Automatic keyboard capture
--------------------------

Set input:autoCapture=yes to grab the keyboard when the pointer enters the
guest view. Looking Glass predicts when the next mouse movement would leave
the guest area and releases the keyboard before that movement. This makes it
possible to move naturally between Looking Glass and the Linux desktop without
using the escape key for the keyboard.

Automatic keyboard capture is disabled by input:captureOnly=yes. It also
keeps the keyboard grabbed while a mouse button is held so that dragging does
not unexpectedly leave the guest.

This is separate from full mouse capture: the pointer remains in normal
absolute mode. Use regular capture mode when an application requires relative
mouse input.

input:grabKeyboardOnFocus instead keeps the keyboard grabbed while the
guest view is active.
input:grabKeyboard controls whether full capture
mode grabs the keyboard.

SPICE fallback
--------------

Keep spice:input=yes when SPICE input fallback is wanted. It uses the VM's
default PS/2 keyboard and mouse, so no additional virtio input devices or
tablet are required.

To disable all SPICE input while keeping SPICE audio or clipboard services:

.. code-block:: ini

[spice]
input=no

If direct input is also unavailable, the client will display video without
being able to control the guest.

Evdev capture
-------------

Advanced users may list Linux evdev devices in input:evdev. They become
active whenever Looking Glass grabs the keyboard, including capture mode and
automatic keyboard capture. The client user must be allowed to read those
devices. Keep
input:evdevExclusive=yes unless duplicate input from the
window system is specifically required.

---

Doc/Install

.. _installing:

Installation
############

The Linux client must currently be built from source before it can be
installed. Follow the pages below in order for a new setup:

Configure the VM and shared memory, install the IDD in Windows, then install
the Linux client. The legacy Host page is an alternative for old workflows;
do not install both Windows servers.

.. toctree::

install_libvirt
install_idd
install_client

---

Doc/Install Client

.. _installing_client:

Client Application Installation
###############################

.. _client_install:

For Linux
---------

The Looking Glass Client receives frames from an implementation of the Looking
Glass Server on Windows and displays them on Linux. It also handles input,
audio, overlays and optional SPICE services.

There are currently no Linux distribution packages for the client. First
:ref:
build it from source <build_client_section>, then run the following from
the client build directory as root::

make install

To install for the current user only, configure the build with a user-local
prefix before installing::

cmake -DCMAKE_INSTALL_PREFIX="$HOME/.local" ..
make install

Ensure $HOME/.local/bin is in your PATH when using the user-local
installation.

---

Doc/Install Host

.. _installing_host:
.. _host_install:

Legacy Host Application installation
####################################

.. warning::

The Host Application is the legacy implementation of the Looking Glass
Server. New installations should use the :doc:
Looking Glass IDD
<install_idd>.

B7 is the last recommended release when non-capture mouse input through the
Host Application is required. Use the matching B7 client and documentation
for that workflow. Do not combine a B7 Host with current components.

The legacy Looking Glass Host Application captures frames from the guest using a
capture API, and sends them to the
:ref:
client <client_install>—be it on the host OS (hypervisor) or another
Virtual Machine—through a low-latency transfer protocol over shared memory.

You can get the host program in two ways:

- Download a matching legacy binary from https://looking-glass.io/downloads

- Download the source code as described in :ref:building, then
:ref:
build the host <host_building>.

.. _host_install_linux:

For Linux
^^^^^^^^^

While the host application can be compiled and is somewhat functional for Linux
it is currently considered incomplete and not ready for usage. As such use at
your own risk and do not ask for support.

.. _host_install_osx:


For OSX
^^^^^^^

Currently there is no support or plans for support for OSX due to technical
limitations.

.. _host_install_windows:

For Windows
^^^^^^^^^^^

To begin, you must first run the Windows VM with the changes noted in the
:doc:
install_libvirt section.

.. _installing_the_ivshmem_driver:

Installing the IVSHMEM driver
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Since B6 the host installer available on the official Looking Glass website
comes with the IVSHMEM driver and will install this for you. If you are running
an older version of Looking Glass please refer to the documentation for your
version.

.. _host_install_service:

Installing the Looking Glass service
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

After installing your IVSHMEM driver, we can now install the Looking Glass Host
onto our Windows Virtual Machine.

1. First, run looking-glass-host-setup.exe as an administrator
(:ref:
Why? <faq_host_admin_privs>)
2. You will be greeted by an intro screen. Press
Next to continue.
3. You are presented with the |license| license. Please read and agree to the
license by pressing
Agree.
4. You can change the install path if you wish, otherwise press
Next to
continue.
5. You may enable or disable options on this screen to configure the
installation. The default values are recommended for most users.
Press
Install to begin installation.
6. After a few moments, installation will complete, and you will have a
running instance of Looking Glass. If you experience failures, you can
see them in the install log appearing in the middle of the window.
7. Press
Close to exit the installer.

Command line users can run looking-glass-host-setup.exe /S to execute a
silent install with default options selected. Further configuration from the
command line can be done with flags. You can list all available flags by
running
looking-glass-host-setup.exe /?.

Legacy configuration
~~~~~~~~~~~~~~~~~~~~

.. toctree::
:maxdepth: 1

host_usage
build_host

---

Doc/Install Idd

.. _installing_idd:

Looking Glass IDD
#################

.. _install_idd:

The Looking Glass IDD is the recommended Looking Glass server implementation for
Windows guests. Download the
looking-glass-idd-setup.exe installer that
matches the client release, run it as an administrator inside the Windows guest
and follow the installer.

The installer includes the display driver, direct input driver and IDD helper.
It can also install the IVSHMEM driver. If the legacy Host service is present,
allow the installer to disable it so that only one Looking Glass server is
active.

The display may briefly disappear while Windows installs or reloads the
driver. Restart Windows if the installer requests it.

Install
-------

1. Download the IDD installer from the same release as the client source.
2. Run
looking-glass-idd-setup.exe as an administrator in Windows.
3. Select IVSHMEM Driver if a suitable IVSHMEM driver is not already
installed in the guest.
4. Leave Indirect Display Driver (IDD) selected.
5. If offered, leave Disable old host app selected. Running two servers
against the same shared-memory device is not supported.
6. Complete the installation and restart Windows if requested.

After installation, Windows should show a display named Looking Glass and the
IDD helper should appear in the notification area. The helper icon reports
whether the IDD is using GPU acceleration or software processing.

The IDD installer also installs its direct input driver. There is no separate
input package to install.

Upgrade
-------

Close active clients and OBS sources, then run the new matching IDD installer
over the existing installation. Upgrade the Linux client and OBS plugin to the
same release before using them again.

Windows may briefly remove and recreate the virtual display. Restart Windows
when the installer reports that a restart is required.

Uninstall
---------

Remove Looking Glass (IDD) from Windows Installed apps or Programs
and Features. This removes both the display and input drivers and deletes
custom IDD modes and preferences. The optional IVSHMEM files are removed from
the Looking Glass installation directory, but an IVSHMEM driver package that
was already installed in Windows is not uninstalled.

If you are returning to the legacy Host Application, re-enable or reinstall
its service only after the IDD has been removed.

Silent installation
-------------------

The installer accepts these options for managed installations:

/S
Install silently. The uppercase spelling is required.

/ivshmem
Install the bundled IVSHMEM driver when it is present in the installer.

/D=path
Change the installation directory. This must be the final option and must
not be quoted.

Configuration and diagnostics
-----------------------------

.. toctree::
:maxdepth: 1

idd_configuration

For faults, the helper can open the IDD log directory directly. See
:ref:
idd_diagnostics for the files to collect.

---

Doc/Install Libvirt

.. _installing_libvirt:

libvirt/QEMU Installation
#########################

This article assumes you already have a working libvirt Windows virtual
machine. If you use
virt-manager, this guide also applies because
virt-manager uses libvirt as its back end. A passed-through or virtual GPU
is strongly recommended, but the IDD can start in software mode without one.

.. _libvirt_determining_memory:

Determining memory
^^^^^^^^^^^^^^^^^^

Calculate the IVSHMEM requirement as:

.. math::

\text{REQUIRED BYTES} =
\left(\left\lceil\frac{\text{WIDTH} \times 4}{256}\right\rceil
\times 256\right) \times \text{HEIGHT} \times 3
+ (4 \times 1024 \times 1024)

Convert the result to MiB and round it up to the next power of two. The common
values below have already been rounded.

If a configured mode does not fit, the IDD omits it from the Windows mode list.
If a client-requested dynamic resolution does not fit, the helper refuses it
and reports the minimum power-of-two size to configure. The current IDD does
not publish a truncated frame.

.. note::
Increasing this value beyond what you need does not improve performance. It
only reserves more host RAM for the VM.

.. list-table:: Common IDD values
:widths: 60 40
:header-rows: 1

* - Maximum resolution
- Total IVSHMEM size (MiB)
* - 1920x1080 (1080p)
- 32
* - 1920x1200
- 32
* - 2560x1440 (1440p)
- 64
* - 3440x1440
- 64
* - 3840x2160 (4K)
- 128
* - 5120x1440
- 128
* - 5120x2880 (5K)
- 256
* - 7680x4320 (8K)
- 512

.. _libvirt_determining_memory_hdr:

HDR uses the same 32-bit IDD transport allocation as SDR, so it does not double
the IVSHMEM requirement. Native Linux HDR presentation has separate compositor
and display requirements; see :ref:
client_hdr.

.. _libvirt_ivshmem:

IVSHMEM
^^^^^^^

There are two methods of configuring IVSHMEM, using shared memory directly, or
using the KVMFR kernel module. While the KVMFR module is slightly more
complicated to configure, it substantially improves performance as it allows
Looking Glass to use your GPUs DMA engine to transfer the frame data.

.. toctree::
:maxdepth: 1

ivshmem_kvmfr
ivshmem_shm

.. seealso::

:ref:igpu_kvmfr_recommended


.. _libvirt_spice_server:

Keyboard/mouse/display/audio
^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The IDD provides the primary video, keyboard and mouse paths directly over
LGMP. SPICE is optional, but is recommended for display fallback, clipboard
and audio services.

.. note::
The current client owns its SPICE connection and service settings. The
canonical options are
spice:enable, spice:input,
spice:clipboard, spice:audio and spice:usbAudio.

Keep a <graphics type='spice'> device if you want these services. For a
usable display fallback, set the VM's
<video> model to vga.

The direct IDD input path supports absolute desktop positioning, relative
capture-mode input, keyboards, media keys and extended mouse buttons. SPICE
fallback uses the VM's default PS/2 keyboard and mouse. Looking Glass does not
require additional virtio keyboard, mouse or tablet devices for either path.

For classic SPICE audio, add a standard Intel HDA audio device:

.. code:: xml

<sound model='ich9'>
<audio id='1'/>
</sound>
<audio id='1' type='spice'/>

The recommended emulated USB audio path does not need this HDA device. It
requires a SPICE USB channel and is covered in :ref:
client_usb_audio. For
clipboard synchronization, continue with
:ref:
libvirt_clipboard_synchronization.

.. _libvirt_clipboard_synchronization:

Clipboard synchronization
^^^^^^^^^^^^^^^^^^^^^^^^^

Looking Glass can synchronize the clipboard between the host and guest using
the SPICE guest agent.

1. Install the SPICE guest tools from
https://www.spice-space.org/download.html#windows-binaries.

2. Configure your VM to enable the SPICE guest agent:

- QEMU

.. code:: bash

-device virtio-serial-pci \
-chardev spicevmc,id=vdagent,name=vdagent \
-device virtserialport,chardev=vdagent,name=com.redhat.spice.0

- libvirt

.. code:: xml

<channel type="spicevmc">
<target type="virtio" name="com.redhat.spice.0"/>
<address type="virtio-serial" controller="0" bus="0" port="1"/>
</channel>

.. _libvirt_apparmor:

AppArmor
^^^^^^^^

For libvirt versions before 5.10.0, if you are using AppArmor, you
need to add permissions for QEMU to access the shared memory file. This
can be done by adding the following to
/etc/apparmor.d/local/abstractions/libvirt-qemu::

/dev/shm/looking-glass rw,

then, restart AppArmor.

.. code:: bash

sudo systemctl restart apparmor

.. _libvirt_memballoon_tweak:

Memballoon
^^^^^^^^^^

The VirtIO memballoon device enables the host to dynamically reclaim memory
from your VM by growing the balloon inside the guest, reserving reclaimed
memory. Libvirt adds this device to guests by default.

However, this device causes major performance issues with VFIO passthrough
setups, and should be disabled.

Find the <memballoon> tag and set its type to none:

.. code:: xml

<memballoon model="none"/>

.. _libvirt_additional_tuning:

Additional tuning
^^^^^^^^^^^^^^^^^

Looking Glass is latency sensitive and as such it may suffer microstutters if
you have not properly tuned your virtual machine. The physical display output
of your GPU will usually not show such issues due to the nature of the hardware
but be sure that if you are experiencing issues the following tuning is
required to obtain optimal performance.

1. Do not assign all your CPU cores to your guest VM, you must at minimum
reserve two CPU cores (4 threads) for your host system to use. For example,
if you have a 6 core CPU, only assign 4 cores (8 threads) to the guest.

2. Ensure you correctly pin your VMs vCPU threads to the correct cores for your
CPU architecture.

3. If you are on a NUMA architecture (dual CPU, or early Threadripper) be sure
that you pin the vCPU threads to the physical CPU/die attached to your GPU.

4. Just because your GPU is in a slot that is physically x16 in size, does not
mean your GPU is running at x16, this is dependent on how your motherboard
is physically wired and the physical slot may be limited to x4 or x8.

5. Be sure to set your CPU model type to host-passthrough so that your guest
operating system is aware of the acceleration features of your CPU and can
make full use of them.

6. AMD users be sure that you have the CPU feature flag topoext enabled or
your guest operating system will not be aware of which CPU cores are
hyper-thread pairs.

How to perform these changes is left as an exercise to the reader.

---

Doc/Ivshmem Kvmfr

:orphan:
.. _ivshmem_kvmfr:

IVSHMEM with the KVMFR module (Recommended)
###########################################

The kernel module exposes IVSHMEM to Looking Glass and can export its frame
buffers for direct GPU import.

.. _ivshmem_kvmfr_prereq:

Prerequisites
-------------

The Linux kernel headers for your kernel version are required for building
along with
dkms to manage the module when you upgrade your kernel.

.. code:: bash

apt-get install linux-headers-$(uname -r) dkms

Then switch to the module/ directory

.. code:: bash

cd module/

.. _ivshmem_kvmfr_dkms:

Installing
~~~~~~~~~~

To install the module into DKMS, run

.. code:: bash

dkms install "."

.. _ivshmem_kvmfr_loading:

Loading
~~~~~~~

Using the value you should have already calculated as per
:ref:
Determining Memory <libvirt_determining_memory>, simply use
modprobe with the parameter static_size_mb, for example:

.. code:: bash

modprobe kvmfr static_size_mb=64

Alternatively you can make this setting permanent by creating the file
/etc/modprobe.d/kvmfr.conf with the following content.

.. code:: text

options kvmfr static_size_mb=64

After this has been done, simply running modprobe kvmfr is all that is
required.

.. note::

Don't forget to adjust static_size_mb to your needs.

.. _ivshmem_kvmfr_systemd:

systemd-modules-load
~~~~~~~~~~~~~~~~~~~~

For convenience, you may load the KVMFR module when starting your computer.
We can use the
systemd-modules-load.service(8) service for this task.

Create the file /etc/modules-load.d/kvmfr.conf with the following
contents::

# KVMFR Looking Glass module
kvmfr

This will now run the next time you start your machine.

.. _ivshmem_kvmfr_verification:

Verification
~~~~~~~~~~~~

If everything has been done correctly you should see the following output in
dmesg:

.. code:: text

kvmfr: creating 1 static devices

You should now also have the character device /dev/kvmfr0

.. code:: bash

$ ls -l /dev/kvmfr0
crw------- 1 root root 242, 0 Mar 5 05:53 /dev/kvmfr0

.. warning::

If you start the VM prior to loading the module, QEMU will create the file
/dev/kvmfr0 as a regular file. You can confirm if this has happened by
running
ls -l /dev/kvmfr0 and checking if the file size is greater than
zero, or the permissions do not start with
c. If this has occurred, you
must stop the VM before deleting the regular file. Load the KVMFR module,
confirm that it recreated
/dev/kvmfr0 as a character device whose
permissions start with
c, then start the VM again.

.. _ivhsmem_kvmfr_permissions:

Permissions
~~~~~~~~~~~

The module will create the /dev/kvmfr0 node, which represents the KVMFR
interface. To use the interface, you need permission to access it by either
creating a udev rule to ensure your user can read and write to it, or simply
change its ownership manually, i.e.:

.. code:: bash

sudo chown user:kvm /dev/kvmfr0

(replace user with your username)

As an example, you can create a new file in /etc/udev/rules.d/70-kvmfr.rules
with the following contents::

SUBSYSTEM=="kvmfr", GROUP="kvm", MODE="0660", TAG+="uaccess"

.. note::

Make sure the udev rule file name ordinal value is below (lexically sorts before) 73-seat-late.rules
to allow the uaccess tag to be processed properly.

.. _ivshmem_kvmfr_libvirt:

libvirt
~~~~~~~

Using the module in libvirt requires adding a <qemu:commandline> block to
your libvirt XML configuration. That block, in turn, requires modifying the
XML domain namespace. To modify the namespace edit the
<domain> tag at
the top of your XML config to:

.. code:: xml

<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>

then add one of the <qemu:commandline> blocks below based on your
QEMU/libvirt versions.

.. note::

Make sure to add both the block and the domain namespace change in a
single editing session prior to saving it. Failure to do so will cause
libvirt to reject the changes.

Starting with QEMU 6.2 and libvirt 7.9, JSON style QEMU configuration is the
default syntax. Users running QEMU 6.2 or later and libvirt 7.9 or later,
should use this XML block to configure their VM for kvmfr:

.. code:: xml

<qemu:commandline>
<qemu:arg value="-device"/>
<qemu:arg value="{'driver':'ivshmem-plain','id':'shmem0','memdev':'looking-glass'}"/>
<qemu:arg value="-object"/>
<qemu:arg value="{'qom-type':'memory-backend-file','id':'looking-glass','mem-path':'/dev/kvmfr0','size':67108864,'share':true}"/>
</qemu:commandline>

.. note::

- The 'size' tag represents the size of the shared memory device in
bytes. Once you determine the proper size of the device as per
:ref:
Determining Memory <libvirt_determining_memory>, use the figure you
got to calculate the size in bytes:

size_in_MB x 1024 x 1024 = size_in_bytes

If you are running QEMU older than 6.2 or libvirt older than 7.9, please use
legacy syntax for IVSHMEM setup:

.. code:: xml

<qemu:commandline>
<qemu:arg value="-device"/>
<qemu:arg value="ivshmem-plain,id=shmem0,memdev=looking-glass"/>
<qemu:arg value="-object"/>
<qemu:arg value="memory-backend-file,id=looking-glass,mem-path=/dev/kvmfr0,size=64M,share=yes"/>
</qemu:commandline>

.. note::

Using the legacy syntax on QEMU 6.2/libvirt 7.9 may cause QEMU to
abort with the following error message:
"
error: internal error: ... PCI: slot 1 function 0 not available for pcie-root-port, in use by ivshmem-plain"

Running libvirt this way violates AppArmor and cgroups policies, which will
block the VM from running. These policies must be amended to allow the VM
to start.

.. tip::

If you are not sure, you likely have cgroups also as this is usually deployed
and configured by default by most distributions when you install libvirt.

AppArmor
^^^^^^^^

Create /etc/apparmor.d/local/abstractions/libvirt-qemu if it doesn't exist
and add the following:

.. code:: text

# Looking Glass
/dev/kvmfr0 rw,

cgroups
^^^^^^^

Edit the file /etc/libvirt/qemu.conf and uncomment the
cgroup_device_acl block, adding /dev/kvmfr0 to the list. Restart
libvirtd to apply it:

.. code:: bash

sudo systemctl restart libvirtd.service

.. _ivshmem_kvmfr_qemu:

QEMU
~~~~

If you are using QEMU directly without libvirt, add the following arguments to your
qemu command line::

-device ivshmem-plain,id=shmem0,memdev=looking-glass
-object memory-backend-file,id=looking-glass,mem-path=/dev/kvmfr0,size=64M,share=yes

.. note::

The size argument must be the same size you passed
to the
static_size_mb argument when loading the kernel module.

---

Doc/Ivshmem Shm

:orphan:
.. _ivshmem_shm:

IVSHMEM with standard shared memory
###################################

Use this method only when the KVMFR kernel module is unavailable. A standard
shared-memory file cannot provide KVMFR's DMA-BUF export, so the client must
copy the frame before uploading it to the host GPU.

Add the following to your libvirt machine configuration inside the
'devices' section by running
virsh edit <VM> where <VM> is the name of
your virtual machine.

.. code:: xml

<shmem name='looking-glass'>
<model type='ivshmem-plain'/>
<size unit='M'>64</size>
</shmem>

.. note::
If you are using QEMU directly without libvirt the following arguments are
required instead.

Add the following to the commands to your QEMU command line, adjusting
the
bus parameter to suit your particular configuration:

.. code:: bash

-device ivshmem-plain,memdev=ivshmem,bus=pcie.0 \
-object memory-backend-file,id=ivshmem,share=on,mem-path=/dev/shm/looking-glass,size=64M

The example uses 64 MiB. Replace it with the value from
:ref:
Determining memory <libvirt_determining_memory> when using a larger
resolution.

.. warning::
Stop the VM before changing this size. You may need to remove the existing
/dev/shm/looking-glass file so QEMU can recreate it at the new size.
Check its permissions afterward; see :ref:
libvirt_shmfile_permissions.

.. _libvirt_shmfile_permissions:

Permissions
~~~~~~~~~~~

The shared memory file used by IVSHMEM is found in /dev/shm/looking-glass.
By default, it is owned by QEMU, and does not give read/write permissions to
your user, which are required for Looking Glass to run properly.

You can use systemd-tmpfiles to create the file before running your VM,
granting the necessary permissions which allow Looking Glass to use the file
properly.

Create a new file /etc/tmpfiles.d/10-looking-glass.conf, and populate it
with the following::

# Type Path Mode UID GID Age Argument

f /dev/shm/looking-glass 0660 user kvm -

Change UID to the user name you will run Looking Glass with, usually your
own.

---

Doc/Legacy Host

.. _legacy_host:

Legacy Host Application
#######################

.. warning::

The Host Application is a legacy server application. New installations should
use the prebuilt :doc:
Looking Glass IDD <install_idd>. These build
instructions are retained for the complete matching B7 stack described in
:ref:
legacy_host_policy.

.. note::

Host in this context refers to the Looking Glass (LG) host server application,
to which the LG client connects to, it thus does not refer to the
host OS!

A common setup is to have a host OS running a guest VM. In such a setup
the
client application runs on the host OS; and the host application
on the
guest VM.

The term Host application was chosen over Guest application, because LG
can be run in a VM to VM configuration, in which case both Host Application and
Client Application are run inside VM Guests.

The Windows Host Application is no longer the recommended server implementation.
It is missing many of the features available in the Looking Glass IDD, such as:

* No additional video capture overhead;
* Usage without a monitor or dummy plug connected;
* Automatically resizing the guest to fit the client application viewport;
* HDR support; or
* Usage in virtual machines without GPU acceleration.

B7 is the last recommended version of the legacy host application for users who
require its non-capture mouse input workflow. Use the complete matching B7 stack
for that workflow rather than mixing B7 and current components.

The documentation is included here for completeness.


.. toctree::
:maxdepth: 1

Installation <install_host>
Configuration <host_usage>
Building from source <build_host>

---

Doc/Obs

.. _obs_plugin:
.. _open_broadcaster_software:

OBS plugin
##########

The Looking Glass OBS plugin reads video from LGMP directly instead of
capturing the client window. The client can stay hidden or show overlays
without adding them to the OBS source. This source does not provide audio or
input; add the required audio source separately in OBS.

Use an OBS plugin from the same Looking Glass release as the IDD and client.
The shared-memory protocol is versioned and mismatched components will not
connect.

.. _obs_building:

Build and install
-----------------

On Debian-based systems, install the OBS headers and the small set of build
dependencies used by the plugin:

.. code:: bash

apt-get install cmake gcc libobs-dev libdw-dev libunwind-dev make pkg-config

Use -DENABLE_BACKTRACE=no when configuring if libdw-dev and
libunwind-dev are intentionally omitted.

From the Looking Glass source directory, build the plugin for the current
user:

.. code:: bash

mkdir -p obs/build
cd obs/build
cmake -DUSER_INSTALL=1 ../
make
make install

For a system-wide installation, omit -DUSER_INSTALL=1 and run
sudo make install.

Add the source
--------------

1. Start OBS after installing the plugin.
2. In Sources, select Add and then Looking Glass Client.
3. Set SHM File to the same KVMFR device or shared-memory file used by the
VM.
4. Enable Hide mouse cursor if OBS should omit the guest pointer.
5. Leave Use DMABUF import enabled with KVMFR unless the OBS log reports
that the host graphics driver cannot import it.

The OBS process needs read and write access to /dev/kvmfr0. Use the same
udev rule as the Looking Glass client; see :ref:
ivhsmem_kvmfr_permissions.

.. figure:: images/Looking-Glass-OBS-Source-Add.png
:alt: Adding a Looking Glass source in OBS

Adding the Looking Glass source

DMA-BUF and CPU copy
--------------------

DMA-BUF import is available with OBS 27 or newer and is enabled by default.
It imports KVMFR into the GPU and makes a full-frame GPU snapshot into
OBS-owned storage before releasing the shared frame. It avoids the CPU upload,
but it is not a zero-copy path to the final OBS texture. If import or the
snapshot fails, the plugin falls back to a CPU copy and records the failure in
the OBS log. A plain POSIX shared-memory file always uses the CPU path.

Disabling DMA-BUF is useful for diagnosis, but it increases CPU and memory
bandwidth use at high resolutions.

HDR
---

HDR-aware OBS color-space support requires OBS 28 or newer. The plugin reports
the source color space from the IDD frame, but OBS must also be configured with
an HDR canvas and a suitable recording or streaming output. An SDR OBS project
will not become HDR merely because the guest frame is HDR.

Frame rate and multiple clients
-------------------------------

An active OBS source requests the global frame rate configured under OBS
Settings > Video. There is no separate FPS control in the Looking Glass
source. The IDD uses the fastest request among all active consumers, so a 120
Hz client can raise the server cadence while OBS records at 60 FPS. Each
consumer still selects the newest frame for its own deadline.

The OBS source releases its cadence request while it is inactive or hidden.
IDD log lines that report acquired, skipped and published frames are expected:
frames newer than the previous publication may be acquired and superseded
without copying all of them through IVSHMEM.

Troubleshooting
---------------

No source image
Check KVMFR permissions, the selected device and component versions. The
OBS log reports both expected protocol versions when they do not match.

High CPU use
Confirm that DMA-BUF stayed enabled and that import succeeded. Also check
whether OBS and the client are both performing expensive scaling.

Jitter when another client starts
Confirm OBS is using a current matching plugin. Current cadence support
allows consumers with different refresh rates without forcing OBS to
display every frame requested by the fastest client.

HDR looks washed out
Check the OBS canvas color space, output format and the guest HDR state. Do
not apply the client's HDR-to-SDR settings to the independent OBS source.

OBS is available from https://obsproject.com/ and is packaged by most Linux
distributions as
obs-studio or obs.

---

Doc/Options

.. _client_options:
.. _client_cli_options:
.. _client_full_command_options:

Client option reference
#######################

The exact option set depends on how the client was built. Use this command for
the complete reference, including defaults and short forms:

.. code:: bash

looking-glass-client --help

Use only the canonical names shown by that command. Older configuration names
may remain as compatibility aliases, but they print a warning and can be
removed in a later release.

Syntax
------

Long options use section:name=value:

.. code:: bash

looking-glass-client win:fullScreen=yes lgmp:allowDMA=no

Short options may take a separate argument:

.. code:: bash

looking-glass-client -F -f /dev/kvmfr1

Configuration files use the section as an INI heading:

.. code-block:: ini

[win]
fullScreen=yes

[lgmp]
allowDMA=no

Common options
--------------

.. list-table:: Application and transport
:widths: 34 16 50
:header-rows: 1

* - Option
- Default
- Purpose
* -
app:transport
-
lgmp
- Select the primary transport, normally
lgmp or spice
* -
lgmp:shmDevice
- automatic
- Select the KVMFR device or shared-memory file
* -
lgmp:allowDMA
-
yes
- Permit direct GPU imports when supported
* -
spice:enable
-
yes
- Enable the built-in SPICE transport and fallback services
* -
spice:host
-
127.0.0.1
- Set the SPICE server address or Unix socket
* -
spice:port
-
5900
- Set the SPICE port; 0 selects a Unix socket
* -
spice:input
-
yes
- Permit SPICE input fallback
* -
spice:clipboard
-
yes
- Permit SPICE clipboard service
* -
spice:audio
-
yes
- Permit SPICE audio service
* -
spice:usbAudio
-
yes
- Use the recommended emulated USB audio device instead of classic SPICE
audio

.. list-table:: Window and display
:widths: 34 16 50
:header-rows: 1

* - Option
- Default
- Purpose
* -
win:size
-
1024x768
- Set the initial client window size
* -
win:fullScreen
-
no
- Start full screen
* -
win:autoResize
-
no
- Follow guest resolution changes
* -
win:setGuestRes
-
yes
- Ask a supporting server to follow the client viewport
* -
win:fpsMin
- automatic
- Set the minimum redraw rate; 0 disables it and is not recommended
* -
win:jitRender
-
no
- Render close to the predicted presentation deadline
* -
win:showFPS
-
no
- Show the FPS and UPS widget
* -
egl:mapHDRtoSDR
-
yes
- Tone-map HDR frames for an SDR output
* -
egl:preset
- none
- Load a named filter preset at startup

.. list-table:: Input
:widths: 34 16 50
:header-rows: 1

* - Option
- Default
- Purpose
* -
input:escapeKey
-
KEY_SCROLLLOCK
- Set the capture/menu key; use
help to list accepted names
* -
input:autoCapture
-
no
- Grab the keyboard inside the guest view and release it before exit
* -
input:captureOnly
-
no
- Enable guest input only while captured
* -
input:grabKeyboard
-
yes
- Grab the keyboard in capture mode
* -
input:rawMouse
-
no
- Use raw relative movement in capture mode
* -
input:mouseRedraw
-
yes
- Repaint at display cadence when only the cursor changes

.. list-table:: Audio and clipboard
:widths: 34 16 50
:header-rows: 1

* - Option
- Default
- Purpose
* -
clipboard:toVM
-
yes
- Allow clipboard transfers to the guest
* -
clipboard:toLocal
-
yes
- Allow clipboard transfers from the guest
* -
audio:periodSize
-
512
- Request an audio backend period in samples
* -
audio:latencyOffset
-
6
- Add safety margin to the classic SPICE audio buffer in milliseconds
* -
audio:resampler
-
auto
- Select classic SPICE resampling with
auto, libsamplerate or the
backend
* -
audio:micDefault
-
prompt
- Select
prompt, allow or deny for microphone requests
* -
audio:debug
-
no
- Log detailed audio synchronization statistics

Advanced options
----------------

Polling intervals, renderer damage handling, display-server protocol choices
and audio-device selectors are intentionally omitted here. They are useful for
diagnosis but can make latency or reliability worse when changed without a
specific reason. Consult
--help and record the original value before
experimenting.

---

Doc/Overview

.. _overview:

Overview
########

Looking Glass displays a Windows virtual machine in a low-latency Linux
window. It transfers completed frames through shared memory instead of sending
compressed video over a network. The current IDD provides video and direct
input through LGMP, while SPICE normally provides audio, clipboard and fallback
services.

The names used throughout this guide are:

Linux host
The physical machine running KVM/QEMU and the Looking Glass Client.

Windows guest
The Windows virtual machine shown by Looking Glass.

Looking Glass Client
The Linux application that displays the guest and sends user input. There
are currently no distribution packages for it, so it must be built from
source before installation.

Looking Glass Server
The Windows guest application that generates the video feed for the Looking
Glass client. There are broadly two implementations of the server: the
Looking Glass IDD and the legacy host application.

Looking Glass IDD
The recommended Windows Indirect Display Driver. It creates a virtual
monitor, sends its frames to the client and provides direct keyboard and
mouse input. The installer also includes the IDD helper and input driver.

Legacy Host Application
The older Windows capture application. It captures an existing display
rather than creating a virtual one. It is documented for existing B7
workflows, but is no longer recommended for current installations.

KVMFR and IVSHMEM
The shared-memory path between the Windows guest and Linux host. KVMFR is
the recommended Linux kernel module because it permits direct GPU imports
where supported.

LGMP
The protocol used by Looking Glass components over shared memory.

SPICE
An optional fallback transport for video, input, audio and clipboard
services. With the IDD active, Looking Glass normally uses its direct input
path and uses SPICE only for services that are enabled and available.

Recommended setup
-----------------

For a new installation, use:

* the current Looking Glass Client on the Linux host;
* KVMFR shared memory attached to the Windows guest;
* the matching Looking Glass IDD in the Windows guest; and
* SPICE only for the fallback or convenience services you need.

Use matching Looking Glass releases for the current client, IDD, and OBS plugin.
The shared-memory protocol changes between releases and incompatible components
will not connect. Users of the legacy host application must use the complete
matching B7 stack described below.

.. _legacy_host_policy:

Legacy Host Application
-----------------------

The Host Application is the legacy implementation of the Looking Glass server.
The IDD is recommended because it does not require a physical monitor or dummy
plug and supports current display, input and scheduling features.

If your workflow specifically requires non-capture mouse input with the Host
Application, B7 is the last recommended release. Use the matching B7 client,
Host Application and B7 documentation together; do not mix B7 components with
current releases.

Download the complete B7 release from https://looking-glass.io/downloads and see
the :ref:
legacy_host section.

---

Doc/Performance

.. _client_performance:

Measure performance and latency
###############################

Press :kbd:ScrLk + :kbd:D for the compact FPS and UPS display. Press
:kbd:
ScrLk + :kbd:T for the timing graphs.

FPS and UPS
-----------

FPS
How often the client completed a render and swap. Cursor-only and overlay
redraws can raise this without a new desktop frame.

UPS
How often this client consumed a new guest frame. It can be lower than the
guest render rate because cadence deliberately skips frames that were
superseded before the client's next deadline.

A higher number is not automatically lower latency. Use the stage graph to
find where time is spent and confirm that the displayed rate meets the output
you are actually using.

Frame latency graphs
--------------------

The Minimum, Maximum and Average panels show a running history in
200 ms buckets. Each colored band is a sequential stage. The thickness of a
band is its duration; its height above zero includes all earlier bands. The top
of the final Swap band is the plotted total through return from EGL swap.

The current incomplete bucket is not plotted. This keeps the newest point from
jumping as samples arrive. Each panel also keeps a stable vertical scale with
hysteresis, so read the millisecond axis when comparing panels.

.. list-table:: Capture and transport stages
:widths: 18 82
:header-rows: 1

* - Band
- What it measures
* - Capture
- Time spent successfully acquiring the next IDD swap-chain buffer. This
is not Windows Graphics Capture and does not include guest application
rendering or the wait between unsuccessful acquisition attempts.
* - Post
- IDD preparation before the measured copy, including format and damage
processing, synchronization and any required compute effect.
* - Copy
- IDD work that copies the selected frame into retained or transport
storage. It may include more than one copy when the selected path needs
it.
* - Ready
- Remaining IDD queue, fence, finalization and publication overhead not
included in Post, Copy or Hold.
* - Hold
- Time a prepared hardware frame waits for the cadence deadline before
its final transport copy starts. This is intentional scheduling time.
Software processing does not use cadence and reports zero.
* - Transport
- Inferred publication-to-client delay for a frame matched to a cadence
deadline. It is not an “IVSHMEM copy” measurement and is omitted when
server and client timing cannot be matched safely.

.. list-table:: Client EGL stages
:widths: 18 82
:header-rows: 1

* - Band
- What it measures
* - Import
- Work needed to make the frame usable by EGL, such as a CPU staging copy
or DMA import and snapshot submission.
* - Dispatch
- Remaining frame-thread validation, format, damage and queueing work
after Import.
* - Queue
- Time from queueing the accepted update until the render thread begins.
This includes waiting for display cadence and deliberate JIT slack.
* - Prepare
- Client render-thread preparation such as commands, resize handling,
geometry and invalidation decisions.
* - Setup
- EGL state, damage history, HDR and pointer setup before desktop drawing.
* - Effects
- Evaluation of the active EGL filter chain.
* - Desktop
- Completion of the frame texture and drawing the guest desktop, with
Effects shown separately.
* - Compose
- Cursor, letterbox, damage diagnostics and HDR composition around the
desktop. The interactive UI overlay is deliberately excluded.
* - Swap
- Time inside the display-server EGL swap call. It may include blocking
in EGL or compositor submission, but not later physical scanout.

Only guest frames actually consumed by EGL contribute server samples.
Superseded frames are not treated as latency samples. The minimum and maximum
for each band are calculated independently, so the top of a minimum or maximum
stack can combine stages from different frames. Use those panels to locate
stage spikes, not as the measured total of one specific frame.

Cadence and Hold
----------------

The Linux display and Windows guest have independent clocks. Looking Glass
does not subtract their raw timestamps. The server reports durations, while
periods, generations and deadlines identify a matching cadence event. The
Transport band is left absent when that match is not valid.

At equal nominal rates, a Hold sawtooth is normally a beat pattern between
two free-running refresh cycles. The age of the newest guest frame ramps as
their phase moves, then wraps when a newer frame reaches the next client
deadline. This is not accumulated cross-VM clock error.

Configure the IDD with the physical display's exact refresh rate to minimize
this pattern. For example, use 119.970 Hz when that is the rate reported for
the display instead of rounding it to 120 Hz.

Investigate when Hold repeatedly exceeds roughly one guest frame period, or
when jumps occur with large Post, Copy or Ready spikes. Those patterns can
indicate server work or scheduling delays rather than normal phase drift.

Frame and photon summaries
--------------------------

The compact FRAME plot is the interval between completed client
render-and-swap loops. It includes cadence waits and cursor-only or overlay-only
redraws, so it is not the CPU time spent rendering one frame.

On Wayland compositors that support wp_presentation, PHOTON measures
from immediately before the EGL swap request until the compositor reports
presentation. It includes Swap and must not be added to the stacked total. The
displayed reciprocal “Hz” describes average latency, not the actual monitor
presentation rate.

Finding a bottleneck
--------------------

* High Copy points to guest GPU or system-memory bandwidth and the IDD copy
path.
* High Hold alone usually reflects cadence phase; correlate it with other
stages before changing anything.
* High Import with DMA disabled points to the client-side memory copy.
* High Queue can be intentional cadence or JIT waiting. Disable
win:jitRender while diagnosing unstable timing.
* High Effects, Desktop or Compose points to client GPU rendering.
* A stable high Swap or PHOTON value can be expected when cadence
matching waits for the correct presentation cycle. It does not by itself
indicate an actual end-to-end latency increase. Investigate unexpected
variation or missed cycles instead.

Keep the guest resolution and refresh realistic for the available memory
bandwidth. Reserve at least two physical CPU cores for Linux and avoid changing
poll intervals as a first response to a spike.

---

Doc/Quickstart

.. _quick_start:

Quick start
###########

This is the shortest path to a current Looking Glass installation. It assumes
that KVM/QEMU and the Windows guest are already working.

1. :doc:Check the requirements <requirements>.
2. :ref:
Download and build the Linux client <build_client_section>. Current
releases are not provided as Linux distribution packages.
3. :doc:
Configure KVMFR and IVSHMEM <install_libvirt> for the largest guest
resolution you intend to use.
4. :doc:
Install the matching Looking Glass IDD <install_idd> inside the
Windows guest. Install the bundled IVSHMEM driver when required.
5. :doc:
Install the client <install_client> from its build directory.
6. Start the Windows guest, then run:

.. code:: bash

looking-glass-client

The client selects /dev/kvmfr0 automatically when it is present, and
otherwise uses
/dev/shm/looking-glass. If your path differs, select it with
-f or lgmp:shmDevice.

The first connection should show the virtual Looking Glass display created by
the IDD. If it does not, follow :doc:
the no-display checks
<troubleshooting> before changing performance settings.

.. note::

SPICE is optional for the primary IDD video and input paths. Keep it enabled
if you want clipboard, audio or display fallback services.

---

Doc/Requirements

.. _requirements:

Requirements and compatibility
##############################

.. _minimum:

Required
--------

Linux host
A Linux system capable of running KVM/QEMU and building the Looking Glass
Client. The client requires an EGL-capable graphics driver. X11 and Wayland
are supported. For a responsive passthrough setup, use at least six CPU
cores with twelve hardware threads.

Windows guest
A Windows 10 version 1803 or newer, or Windows 11, virtual machine. The
recommended IDD path can create its own virtual monitor and does not require
a physical monitor or dummy plug.

Shared memory
An IVSHMEM device large enough for the maximum guest resolution. The KVMFR
kernel module is recommended and is required for direct GPU imports.

Matching components
Use the current client, IDD and OBS plugin from the same Looking Glass
release. A protocol version mismatch is not supported. Legacy Host users
must use the complete matching B7 stack described below.

The IDD can fall back to software processing if the Windows guest has no
suitable render GPU. This is useful for compatibility, but hardware processing
is strongly recommended for lower latency and higher frame rates. Software
mode is SDR-only and does not provide the same performance as the GPU path.

.. _recommended:

Recommended
-----------

For a responsive high-resolution setup, use:

* a host CPU with eight cores and sixteen threads or better, with full
performance cores around 3 GHz or faster;
* KVMFR rather than a plain shared-memory file;
* a host GPU and driver that support direct DMA imports;
* a hardware render adapter in the Windows guest; and
* enough memory bandwidth for the chosen resolution and refresh rate.

Do not assign every CPU core to the guest. Reserve at least two physical CPU
cores, or four threads, for Linux. Looking Glass, QEMU, the Linux desktop and
audio server all need host CPU time. High refresh rates also raise
shared-memory and GPU bandwidth requirements.

For a passed-through GPU, PCIe bandwidth can also limit performance. Use at
least eight PCIe 3.0 lanes or four PCIe 4.0 lanes where practical.

.. _connected_display:

Physical display and dummy plugs
--------------------------------

The recommended IDD does not require a physical display or dummy plug. It
creates a virtual Windows monitor, including on systems without a
passed-through display output.

A physical display, dummy plug or another virtual monitor is only required
when using the :doc:
legacy Host Application <install_host>, because that
application captures an existing Windows display.

.. _igpu_kvmfr_recommended:

Host GPU notes
--------------

AMD and Intel host GPUs commonly support the DMA-BUF path used by KVMFR. This
can reduce CPU work and avoid an extra system-memory copy. It is particularly
important for integrated GPUs, which already share memory bandwidth with the
CPU.

NVIDIA host GPUs require a driver configuration that supports DMA-BUF import.
If direct import is unavailable, the client falls back to a software copy.
Looking Glass still works, but uses more CPU and memory bandwidth.

Windows and HDR
---------------

Windows 10 remains supported. Current HDR and wide-color-gamut display features
depend on newer IddCx interfaces that the driver checks at runtime, so they are
normally available only on a compatible Windows 11 installation. The IDD
continues to use its SDR-compatible path when those interfaces are unavailable.

Native HDR presentation on Linux requires the EGL renderer, Wayland
color-management-v1 support in the compositor, and an HDR-capable output.
When native HDR is unavailable, the client can map HDR content to SDR.

---

Doc/Tech Faq

Technical notes
###############

This page explains a few implementation choices. It is not required for normal
installation.

.. _ivshmemshared_ram:

IVSHMEM and shared memory
-------------------------

.. _what_exactly_is_the_ivshmem_device:

What is the IVSHMEM device?
~~~~~~~~~~~~~~~~~~~~~~~~~~~

IVSHMEM maps the same reserved memory into QEMU, the Windows guest and Linux.
KVMFR provides the Linux character-device interface used by the client and OBS
and can export regions for direct GPU import.

The IDD stores frame queues, frame metadata, pointer updates and input protocol
state in this region. It uses three frame buffers so a server and multiple
clients can progress without overwriting a frame that is still in use.

.. _what_is_the_ivshmem_device_being_used_for:

Why is the allocation larger than one image?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In addition to three aligned images, the region contains LGMP queues and GPU
resource alignment. Use :ref:
libvirt_determining_memory rather than
multiplying width and height once.

.. _why_do_you_need_the_mouse_positional_information:

Why are there both absolute and relative mouse paths?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Desktop interaction needs absolute positioning so the host and guest pointers
stay aligned without capture. Games that lock the cursor need unbounded
relative movement. The IDD exposes both and the client selects the appropriate
path when capture mode changes.

SPICE fallback remains relative-only. Pointer position messages are also used
to render the guest cursor independently from desktop frame updates.

.. _why_does_lg_poll_for_updates_instead_of_using_interrupts:

Why does Looking Glass poll for updates?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Polling avoids the high overhead and batching behavior seen with virtual
interrupts, especially for high-rate pointer updates. The polling intervals
are configurable for diagnosis, but lowering them without evidence increases
CPU usage and does not guarantee lower latency.

How does cadence reduce bandwidth?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Clients publish their presentation period and deadline in the shared protocol.
The IDD prepares guest frames as they arrive, but transports only the newest
frame needed for the fastest active consumer. Other consumers independently
select the newest frame appropriate for their own rate. Clock-domain feedback
is exchanged as periods and deadlines rather than comparing raw timestamps
from Windows and Linux.

---

Doc/Troubleshooting

Troubleshooting
###############

Start with the symptom below. Avoid changing polling, synchronization or
renderer options until the basic server, shared-memory and version checks
pass.

.. toctree::
:maxdepth: 1

idd_diagnostics

.. _when_launching_looking_glass_the_desktop_doesnt_appear:

The Looking Glass monitor is missing in Windows
-----------------------------------------------

1. Confirm that the guest runs Windows 10 version 1803 or newer, or Windows 11.
2. Confirm that the IDD installer completed and restart Windows if requested.
3. Open the IDD helper and its log directory. See :ref:
idd_diagnostics.
4. In
looking-glass-idd.txt, confirm that IVSHMEM opened with the expected
size and that at least one configured display mode fits.
5. Increase IVSHMEM if every suitable mode was filtered. Restart the VM after
changing its size.
6. Ensure the legacy Host service is disabled. Only one Looking Glass Server
implementation should use the Looking Glass IVSHMEM device.

A missing passed-through GPU does not by itself prevent the IDD display from
appearing. The IDD can start in software mode, although that mode is slower and
SDR-only.

The client remains on the waiting screen
----------------------------------------

* Confirm that the Windows Looking Glass monitor is active and producing a
desktop.
* Check that the client selected the same KVMFR device or shared-memory file as
the VM.
* Confirm that the Linux user has read and write access to that device.
* Use matching client and IDD releases. A KVMFR or LGMP protocol mismatch is a
hard incompatibility.
* If
/dev/kvmfr0 is a regular file instead of a character device, stop the
VM, remove that accidental file and load KVMFR before starting the VM again.

The image is slow or stutters
-----------------------------

Open the timing graphs with :kbd:ScrLk + :kbd:T and follow
:ref:
client_performance. Also check:

* the IDD helper reports GPU acceleration rather than software processing;
*
lgmp:allowDMA=yes is using a direct import when the host driver supports
it;
* enough CPU cores remain available to Linux;
* the guest resolution and refresh do not exceed available memory bandwidth;
* the compositor is not adding an unexpected frame queue; and
* the fastest active client or OBS source is requesting the intended cadence.

Do not set the guest to an extreme refresh rate merely to raise UPS. The IDD
can acquire newer frames and skip superseded ones before transport, but the
guest still pays the cost of rendering them.

Keyboard or mouse input does not work
-------------------------------------

* Press :kbd:ScrLk + :kbd:I to ensure guest input is enabled.
* Check
looking-glass-input.txt and the client's selected input provider.
* Only one LGMP client owns direct input. Close another controlling client if
necessary.
* If SPICE video fallback is active, keep
spice:input=yes. The client uses
the VM's default PS/2 keyboard and mouse and intentionally switches input
with the video source.
* If
input:captureOnly=yes, press :kbd:ScrLk to enter capture mode.

See :ref:client_input for normal, automatic keyboard and capture modes.

.. _the_clipboard_is_not_working:

The clipboard is not working
----------------------------

- Is clipboard synchronization enabled?

- Before you can copy or paste content between the guest and host,
:ref:
clipboard
synchronization <libvirt_clipboard_synchronization>
must be enabled.

- Did you install the Spice Guest Tools?

- The SPICE Guest Tools
driver <https://www.spice-space.org/download.html>_ must be installed
inside the Windows guest to synchronize the clipboard.
The download is labeled "spice-guest-tools".

.. warning::

Do NOT install the QEMU Guest Tools driver.
These are not the same.

- Is it installed twice?

- The Spice VDAgent is available in both Spice Guest Tools, and
standalone as a separate installer. Check your installed programs
and uninstall the VDAgent if it's installed separately.

.. _keyboard_shortcuts_not_captured_on_gnome_wayland:

Keyboard shortcuts are not captured on GNOME Wayland
-----------------------------------------------------

Capture mode may fail to capture compositor shortcuts like
ALT+Tab or ALT+Middle Mouse - they go to GNOME instead of the guest VM.

When Looking Glass first requests to inhibit shortcuts, GNOME shows a
dialog asking for permission. If you clicked "Deny" (or dismissed the dialog),
GNOME permanently blocks the application and never shows the dialog again.

Use the flatpak command to view or grant the permission, this works even
if LookingGlass is not a Flatpak application, as GNOME stores these permissions
in Flatpak's database:

.. code:: bash

flatpak permission-set gnome shortcuts-inhibitor looking-glass-client.desktop GRANTED

To verify the permission was set:

.. code:: bash

flatpak permissions gnome shortcuts-inhibitor

USB audio does not appear or play
---------------------------------

* Confirm that the client was built with libusbredirparser-0.5 version
0.7.1 or newer.
* Add an unused SPICE USB Redirector device to the VM.
* Keep
spice:enable=yes, spice:audio=yes and
spice:usbAudio=yes.
* In Windows Sound settings, select the Looking Glass USB Audio speakers as
the output device.
* Check the client startup log. If USB audio creation failed before
connection, Looking Glass falls back to classic SPICE audio and reports why.

The microphone is unavailable
------------------------------

The current PipeWire backend supports recording; the PulseAudio backend does
not. Ensure the client selected PipeWire, then check
audio:micDefault and
the microphone indicator. Press :kbd:
ScrLk + :kbd:C to change the default
permission and :kbd:
ScrLk + :kbd:E to toggle recording.

---

Doc/Usage

.. _client_usage:

Use the client
##############

Start the client after the Windows guest and IDD are running:

.. code:: bash

looking-glass-client

The client uses LGMP over /dev/kvmfr0 automatically when that device is
available. Otherwise it uses
/dev/shm/looking-glass. Select another device
with
-f or the canonical lgmp:shmDevice option:

.. code:: bash

looking-glass-client -f /dev/kvmfr1

Use looking-glass-client --help to see the options supported by the
installed build. Command-line options override configuration files.

.. _client_key_bindings:

Default key bindings
--------------------

Looking Glass uses :kbd:ScrLk as its escape key by default. Press it by
itself to enter or leave capture mode. Hold it to display the available
commands. Change it with
input:escapeKey or -m if the keyboard does
not have :kbd:
ScrLk.

.. list-table:: Default client commands
:widths: 35 65
:header-rows: 1

* - Command
- Action
* - :kbd:
ScrLk
- Enter or leave capture mode
* - :kbd:
ScrLk + :kbd:Q
- Quit
* - :kbd:
ScrLk + :kbd:F
- Toggle full screen
* - :kbd:
ScrLk + :kbd:V
- Toggle the video stream
* - :kbd:
ScrLk + :kbd:R
- Rotate clockwise by 90 degrees
* - :kbd:
ScrLk + :kbd:=
- Ask the IDD to match the client window resolution
* - :kbd:
ScrLk + :kbd:I
- Toggle guest input
* - :kbd:
ScrLk + :kbd:O
- Enter or leave interactive overlay mode
* - :kbd:
ScrLk + :kbd:D
- Toggle the FPS and UPS widget
* - :kbd:
ScrLk + :kbd:T
- Toggle the frame-timing graphs
* - :kbd:
ScrLk + :kbd:N
- Toggle EGL night vision
* - :kbd:
ScrLk + :kbd:E
- Toggle microphone recording when the audio backend supports it
* - :kbd:
ScrLk + :kbd:C
- Cycle the default microphone permission
* - :kbd:
ScrLk + :kbd:M
- Send mute to the guest
* - :kbd:
ScrLk + :kbd:Up or :kbd:Down
- Send volume up or down to the guest
* - :kbd:
ScrLk + :kbd:Insert or :kbd:Delete
- Adjust capture-mode mouse sensitivity
* - :kbd:
ScrLk + :kbd:LWin or :kbd:RWin
- Send that Windows key to the guest
* - :kbd:
ScrLk + :kbd:F1 through :kbd:F12
- Send :kbd:
Ctrl + :kbd:Alt + that function key to a Linux guest

The microphone commands are registered only when the client was built with
audio recording support. Night vision is an EGL feature. The virtual-console
bindings are registered only when the selected guest type is Linux.

.. _client_config_options_file:

Configuration files
-------------------

The client loads these files in order when they exist:

* /etc/looking-glass-client.ini
*
~/.looking-glass-client.ini
*
$XDG_CONFIG_HOME/looking-glass/client.ini

Later files override earlier files. The usual per-user path is
~/.config/looking-glass/client.ini. Files use INI syntax:

.. code-block:: ini

[win]
fullScreen=yes
setGuestRes=yes

[input]
autoCapture=yes

[spice]
clipboard=yes
audio=yes

[egl]
preset=my-preset

Boolean values accept yes or no. Long command-line options use
section:name=value, for example:

.. code:: bash

looking-glass-client win:fullScreen=yes input:autoCapture=yes

.. _client_overlay_mode:
.. _client_config_widget:

Interactive overlay
-------------------

Press :kbd:ScrLk + :kbd:O to make the overlay interactive. Press
:kbd:
Esc or the same binding to leave it. The overlay can:

* enable and arrange the FPS and timing widgets;
* select and configure EGL filters;
* save filter settings as presets; and
* enable diagnostic views such as damage rectangles.

Widget positions and sizes are stored in
$XDG_CONFIG_HOME/looking-glass/imgui.ini. EGL filter presets are stored in
$XDG_CONFIG_HOME/looking-glass/presets. Do not edit either while the
client is running.

Runtime changes are not all written to the main client configuration. Put
options that must apply at every start in
client.ini.

User guides
-----------

.. toctree::
:maxdepth: 1

input
display
audio
performance
options

---

Doc/Words

Anime4K
backend
backends
backtrace
BigNavi
borderless
Brindus
cadence
cgroups
checkboxes
clang
cmake
codec
compositor
config
CopySleep
Debian
dejavu
deuteranope
dev
dir
DirectX
distros
dmabuf
dmesg
downsample
downsampling
downscaler
downscaling
EGL
evdev
ExtraMode
Flatpak
framebuffer
fullscreen
gcc
globalFullScreen
gnif
Guanzhong
HDR
hypervisor
i3
IddCx
ie
imgui
ini
kvmfr
laggy
lexically
libdecor
libpipewire
libpulse
libvirt
linux
LookingGlass
Losslessly
luminance
memballoon
MiB
microstutters
mingw
mipmapping
modprobe
mpv
msys
multisampling
namespace
Navi
NvFBC
Nvidia
overlayed
overrun
oversized
pacman
passthrough
performant
pre
prebuilt
protanope
QEMU
quadraphonic
Quadro
queueing
radeon
realtime
renderer
repo
resampler
Rubenstein
runtime
scanout
Scream
scRGB
SDR
shaders
shm
spencercw
submodule
submodules
systemd
th
Threadripper
toolchain
tooltip
tritanope
tunable
uaccess
udev
UEFI
uncheck
uncomment
underrun
underruns
Unigine
unix
upscaled
upscaler
upscales
upscaling
viewport
VirtIO
virtio
VM
vsync
wayland
xdg
Xorg
xyene

---

README

Looking Glass

Looking Glass lets you use a Windows virtual machine from Linux with very low
display and input latency. The current recommended setup uses the Looking Glass
Indirect Display Driver (IDD) in the Windows guest and the Looking Glass Client
on the Linux host.

* Project Website: https://looking-glass.io
* Documentation: https://looking-glass.io/docs

Start here

The Linux client is currently distributed as source code and must be built
before it can be installed. The end-user guide covers the complete process:

1. Build the Linux client.
2. Configure shared memory for the virtual machine.
3. Install the Looking Glass IDD in Windows.
4. Install and run the client.

See the Looking Glass documentation for the
current requirements and setup guide.

Source archives

❕❕❕ IMPORTANT ❕❕❕

This project contains submodules that must be checked out if building from the
git repository! If you are not a developer and just want to compile Looking
Glass, please download the source archive from the website instead:

https://looking-glass.io/downloads

Source code for the documentation can be found in the doc directory.

You may view this locally as HTML by running make html with python3-sphinx
and
python3-sphinx-rtd-theme` installed.

---