The cursorThread prevents the host from going to sleep when the
video feed is disabled as it's subscribed to the cursor queue. Stopping
the cursorThread will unsubscribe from the queue and allow the host
application to disable capture.
This commit adds check for the extensions that we need and then calls
the functions indirectly through gl_dynprocs.
This should improve compatibility with older versions of OpenGL, as we
now fallback to the ARB extensions if possible, and in the case of
glGenerateMipmap, we can handle the function not existing at all.
The Linux OpenGL ABI does not guarantee that glXSwapIntervalEXT will be
exported statically from any library, and indeed on some systems this
function does not link at load time, e.g. with amdgpu-pro. All other
GLX functions that we use are from GLX 1.0, which is guaranteed to be
exported statically.
This commit solves this issue by using glXGetProcAddressARB to load the
function. Note that only the ARB version of glXGetProcAddress is
guaranteed to exist by the Linux OpenGL ABI, which is why we must use
it.
This prevents attempts to grab the pointer after the guest side warp
finishes if the pointer has left the window in the meantime. On Wayland,
this would result in the pointer moving to the middle of the window when
the confine is created.
Previously, all progress made during sleep is reset, so if the thread keeps
getting interrupted before the sleep finishes, the sleep will never complete.
This saves a lot of GPU power for partial updates. Running testufo with
lanczos downscaling and FSR upscaling consumed over 90 W, but with this
commit, consumed only 75 W.
The translucent white modal background sort of cancels out the dark
background we apply to the overlay, which is undesirable. It should
instead further darken the background.
For consistency, we now use igGetColorU32Col(ImGuiCol_ModalWindowDimBg)
to draw the overlay background, to avoid hardcoding the same colour in
multiple places.
Currently, this is visible through how fast the cursor blinks, with it
blinking faster at higher refresh rates. This commit makes the timing
consistent.
This new function dumps all options marked as preset instead of dumping
individual sections. This should allow filter options to not be all grouped
into the [eglFilter] section.
imgui really hates it when we update the modifier key state after igNewFrame.
The result is:
void ImGui::ErrorCheckEndFrameSanityChecks(): Assertion
`(key_mod_flags == 0 || g.IO.KeyMods == key_mod_flags) &&
"Mismatching io.KeyCtrl/io.KeyShift/io.KeyAlt/io.KeySuper vs io.KeyMods"'
failed.
Therefore, we buffer the modifier state information and update it in the IO
object right before we call igNewFrame.
This avoids warping the host cursor when the guest-side warp has not finished,
which will result in the host cursor exiting at the wrong position if it exits
at that moment.
Using 4x4 means that some pixels will be outside of the lanczos window. The
ideal lanczos function should in fact be zero in those areas, so we shouldn't
waste time processing those pixels.
I can't notice any difference in the results.
According to the documentation for eglQueryString:
> EGL_BAD_DISPLAY is generated if display is not an EGL display connection,
> unless display is EGL_NO_DISPLAY and name is EGL_EXTENSIONS.
Therefore, we should check EGL by doing:
eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS)
Indeed, the old way of eglQueryString(EGL_NO_DISPLAY, EGL_VERSION) works on
libglvnd but not using mesa's libEGL.so directly.
Also added a warning to make it more obvious that EGL is not available.
With the new keymap feature, we are now able to properly support letting
the user enter exact values into the sliders. This commit adds a tooltip
to help the user discover this feature.
Note that this currently only works on Wayland. The X11 backend will need
to call app_handleKeyboardModifiers.
Due to the way assert is defined in standard C, compilers in release mode
will not treat it as unreachable. This explains a lot about those pesky
uninitialized variable bugs, actually.
This also displays a tooltip to explain that quality can be changed by
altering guest resolution and also show the resolutions needed to achieve
each quality mode.
This prevents issues like obscure characters getting transformed in symbol
names, resulting in an endless game of whack-a-mole finding symbols that are
replaced, such as 58964ce317.
gl_Position is expected to be using homogeneous coordinates, which requires
w to be a coordinate scale factor, usually 1.0. z should also be set in order
for depth to be well-defined. Therefore, we should set gl_Position.zw to
vec2(0.0, 1.0).
This avoids race conditions in GL drivers when attempting to render and
call glEGLImageTargetTexture2DOES on the same texture.
Also, when using glEGLImageTargetTexture2DOES, we do not need to allocate
storage for textures.
External events like launching other applications can cause latency
spikes while X11 initializes the application, we should only start
adjusting our delay if we see excessive skips over a 1s period.
`process` and `bind` are called from the same thread in order, there is
no need for atomic usage here.
This reverts commit 3d7dbd6371.
This reverts commit b3db1ba10b.
It used to be the case that we overwrite this->sync even if it was non-zero
when updating the texture, without deleting the sync object. If we update
faster than we render, the result would be leaking sync objects.
This commit ensures that sync objects are deleted when they are replaced.
Invalidating the entire window on an Expose event causes poor WM
performance when dragging the window around. Instead flag to redraw and
wait for the expose events to stop for 100ms before doing it.
This uses the same line sweep algorithm originally created to copy DXGI
textures to IVSHMEM to implement the copy from IVSHMEM to memory-mapped
pixel buffer objects.
It looks really weird having a separator right after a sentence ending in :.
A separator makes the list look detached from the paragraph that introduces
it, which looks awkward. Instead, this commit moves the separator before the
introducing paragraph.
Also added logic to properly pluralize the sentence.
The display servers and renderers may want to register their own
overlays in the future, as such we need g_state.overlays to be
initialized to allow for this.
Since we only update imgui's cursor location when the overlay is
enabled, if the last cursor position was showing a shape that is
incorrect when we re-enter the overlay the cursor will be wrong. This
corrects this by updating the location as we enter overlay mode.
This adds a new `earlyInit` call which allows the overlay to register
options before actually being intialized. Also the keybind handling and
state tracking for each overlay has been moved internal to the overlay
itself.
When entering overlay mode if the cursor was previously grabbed we
should restore the state when exiting overlay mode. This will also
correct the pointer setting it to NONE or SQUARE depending on the prior
grab state.
X11 needs to calibrate to get the best possible latency, as such it
needs the scene to render so that the render time of the scene can be
accounted for in the delay calculation.
This replaces the scaled `destRect` with a version that uses doubles
correcting the rounding error that is causing a failure to properly
clear the black bar areas.
This mesh will later be used to render only damaged portions of the desktop.
We also moved the coordinate transformation for damage overlay into a matrix
and computed by the shader.
XPresent doesn't give us the time before presentation, but the time just
after. This code calculates and calibrates a delay to sleep for before
signaling the wait event for render when using jitRender
After the damage queue PR, EGL damage count 0 means no change, and -1 means
invalidate the entire window. However, several other places have different
semantics, and we are not handling them correctly:
1. KVMFR uses 0 to signal invalidating the entire frame, so if we receive 0
rectangles in egl_on_frame, we should set damage count to -1.
2. The damage overlay treated 0 as full damage, which is now incorrect. This
is fixed, and now it treats 0 as no update, and -1 as full damage.
The way things were handled in EGLTexture is not only very hard to
follow, but broken. This change set breaks up EGLTexture into a modular
design making it easier to implement the various versions.
Note that DMABUF is currently broken and needs to be re-implemented.
There used to be a possible race when a bunch of rectangle is appended, but
the total count is not updated before it's read. Using a lock eliminates
all such races.
Without configuring Wayland compositors to send frame callbacks as late as
possible, JIT rendering can increase latency by more than one frame.
For example, by default, sway asks applications to render right after a
vblank, and does its own composition right after a vblank, resulting in
~2 frame's worth of latency. If max_render_time is set on the output,
it composes that many milliseconds before the vblank, losing ~1 frame's
worth of latency. If max_render_time is set on the window also, the frame
callback is sent that many milliseconds before composition, and we achieve
perfectly low latency.
Therefore, out of the box, JIT rendering should not be enabled, as manual
compositor configuration is required for optimal results.
For reference, the following sway settings results in the best latency:
output <insert output name> max_render_time 1
for_window [app_id="looking-glass-client"] max_render_time 1
This reverts commit 3baed05728.
If we invalidate the window, we used to not update this->cursorLast, and
this causes us to lose track of the cursor. Now we update this->cursorLast
unconditionally, and this fixes the issue.
Version 3 does not send xdg_output.done events, instead guaranteeing that
all xdg_output.* events are sent before wl_output.done. This saves us from
doing the work twice.
The method used is not guaranteed to work on all Wayland compositors,
so offer a way out. We need to support it anyways in case xdg_output
or wp_viewporter protocols are not available.
Currently, we scale the desktop up to the next largest integer, and rely on
the wayland compositor to scale it back down to the correct size.
This is obviously undesirable.
In this commit, we attempt to detect the actual fractional scaling by finding
the current active mode in wl_output, and dividing it by the logical screen
size reported by xdg_output, taking into consideration screen rotation.
We then use wp_viewporter to set the exact buffer and viewport sizes if
fractional scaling is needed.
When requested, JIT render mode will be used if the display server supports it.
Otherwise, a warning is generated instead.
This essentially uses the signalNextFrame logic for imgui, but for everything.
We automatically enable this mode when overlay is on.
Currently, this exposes some damage tracking bugs in the EGL renderer.
This prevents damage from being overwritten when frames are received
faster than could be rendered.
This implementation cycles between two queues, removing all need for
memory allocation.
This method takes an LGEvent and signals it when the next frame should be
rendered in time for the next vblank.
We will be using this to render imgui at screen refresh rate, but this could
potentially be used later to implement a better form of vsync for supported
display servers.
This must be invoked before swapping buffers.
The imgui overlay requires input even if the display is not captured and
operating in raw mode. XInput2 correctly only sends
XI_Press/ReleaseButton events if the device has not been captured, as
such it's safe to handle both raw and non raw buttons events at the same
time.
We look for the client config in $XDG_CONFIG_HOME/looking-glass/client.ini.
This is done because it's more conventional, and also allows us to add
additional configuration files, e.g. for the host.
We fallback to $HOME/.config as is standard, and then as a last resort use
getpwuid(getuid())->pw_dir. This is also recommended by the getpwuid manpage:
> An application that wants to determine its user's home directory should
> inspect the value of HOME (rather than the value getpwuid(getuid())->pw_dir)
> since this allows the user to modify their notion of "the home directory"
> during a login session.
Currently, we load /etc/looking-glass-client.ini and/or
~/.config/looking-glass-client.ini as long as they exist, even if they are
not files. We should only load them if they are files.
We don't want to encourage craziness of people making the client suid to
bypass permission issues on the shm file.
Note: I see no evidence of this happening in the wild, but let's be
proactive.
The refresh-copyright script now automatically updates the copyright string
embedded in config.c. In order to achieve this, refresh-copyright gained the
ability to reflow text as the situation needs.
We now give ImGui the true logical size of the window and tell it to scale
the framebuffer. To fix the blurry fonts, we continue to load fonts at the
scale necessary for the DPI and use FontGlobalScale to shrink the fonts back
to the logical size. The font rectangle is then expanded by the framebuffer
scaling, resulting in good text rendering.
This method has the advantage of not messing up the sizes of resizable
overlays when moving across monitors.