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.
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.
The default of [0, 50] makes sense for FPS/UPS graphs, but does not for
things like the import graph. The latter should not take more than 5 ms
for sure.
This commit allows the min/max y-axis value to be specified when registering
the graph.
Now that we are drawing with damage rects, when the window is hidden and
then exposed the window may not get fully redrawn. This provides
`app_invalidateWindow` for the display server backend to call when the
screen needs a full redraw.
This is necessary in case overlays change size. When this happens, we must
damage the larger of the overlays' rectangles this frame and last frame.
This erases the overlay from where it is no longer appears.
In order to do this, we must keep track of the rectangles for every overlay
with no exception. We cannot short-circuit the generation of rectangles if
we run out of buffer space, and we must allocate space for MAX_OVERLAY_RECTS
rectangles for every frame. Otherwise, we will not know where to erase the
overlay if it disappears.
While the renderer can internally track this it would be better to
simply provide this information to the renderer directly so it can make
better decisions on how best to update the screen.
1. Use atomics and return exact cursor positions from egl_cursor_render
to avoid race conditions between cursor render and update.
2. Instead of messing with lastCursorValid in various overlays, simply use
the hasOverlay/hadOverlay logic for cursor damage. This simplifies the
logic greatly.
As a result, I believe all cursor-related artifacts are fixed.
Note to reviewer: as atomic_init and atomic_store are implemented as macros,
it is currently not possible to pass structs as compound literals due to the
comma being interpreted as an argument separator by the preprocessor.
Instead of using the desktop <GL/gl.h>, we properly use the OpenGL ES 3.x
headers. Also, we now use GL_EXT_buffer_storage for MAP_PERSISTENT_BIT_EXT
and MAP_COHERENT_BIT_EXT as the core versions are only available in desktop
OpenGL 4.4. Similarly, we need GL_EXT_texture_format_BGRA8888 for GL_BGRA_EXT
as GL_BGRA is desktop-only.
Instead of damaging the entire surface when rendering a cursor move,
we can use the EGL_KHR_swap_buffers_with_damage extension to only
damage the part of the window covered by the cursor. This should
reduce the cursor movement latency on Wayland.
We previously used strstr, which can be prone to false positives when
the name of one extension is a substring of another extension.
This commit creates the helper function util_hasGLExt, which asserts
that the substring found in extension list is bounded by either spaces
or the beginning/end of the string.
This commit fixes the issues with the meaning of useNearest being flipped
by removing the variable and use enumerations.
We define an enumeration EGL_DesktopScaleType to express the type of scaling
needed to be performed: no scaling, upscaling, or downscaling. This is
updated when either the frame size or the viewport size changes.
Previously, we only updated the useNearest when the frame size changes.
The desktop shader can now support an enumeration of scaling algorithms,
although only nearest and linear are currently implemented.
Like before, nearest is used when not scaling or upscaling, and linear is
used when downscaling.
Before, if you want to see the FPS, you need to close the client and
restart it with the -k switch to see the FPS. This is annoying.
This PR introduces a new keybind, ScrollLock+D, which, when pressed,
toggles the display of the FPS.
This is implemented for both EGL and OpenGL backends.
This should prevent the looking-glass-client window from having an alpha
channel. On Wayland, the alpha channel is used to compose the window onto
the desktop, so the wallpaper would bleed through unless set to complete
opaque.
We worked around this by using constant alpha for rendering, but it was
not sustainable. Instead, we should just ask for 24-bit context.
This effectively reverts 4bceaf5.
Upstream ticket: https://gitlab.freedesktop.org/mesa/mesa/-/issues/4180
Commit 941c651 makes working around the hang in LG itself not as
annoying as before.
In the future, we can bypass this entire issue by implementing our own
swapchain and listening to frame callbacks ourselves.
Build failed with _FORTIFY_SOURCE enabled because the compiler couldn't
ensure the switch statements didn't hit the default arm and thus wouldn't
define the variables. Adding a statically failing assert makes sure that
all code paths either define the variables or fail early.
$ cd client
$ env CFLAGS='-O1 -D_FORTIFY_SOURCE=1' cmake -B build/
$ make -C build
[...]
client/renderers/EGL/egl.c: In function ‘egl_calc_mouse_size’:
client/renderers/EGL/egl.c:299:36: error: ‘h’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
299 | (this->mouseHeight * (1.0f / h)) * this->scaleY
| ~~~~~~^~~~
If the guest has it's output rotated (ie, landscape) we must rotate and
translate the pointer draw location, as well as all the translations of
cursor coordinate spaces based on the rotation, along with any local
rotations that may also be applied.
This makes it a compile-time error to call a function that semantically
takes no parameters with a nonzero number of arguments.
Previously, such code would still compile, but risk blowing up the stack
if a compiler chose to use something other than caller-cleanup calling
conventions.
This commit makes Looking Glass always use the OpenGL renderer when
running on Wayland. The EGL renderer is broken on Wayland and can't
reasonably be fixed until SDL is dropped entirely (as per
https://github.com/gnif/LookingGlass/issues/306).
Until that time, the OpenGL renderer provides a much better
Wayland-native experience.
eglSwapBuffers is allowed to block when called with a nonzero interval
parameter. On Wayland, Mesa will block until a frame callback arrives.
If an application is not visible, a compositor is free to not schedule
frame callbacks (in order to save CPU time rendering something that is
entirely invisible).
Currently, starting Looking Glass from a terminal, hiding it
entirely, and sending ^C will cause Looking Glass to hang joining the
render thread until the window is made visible again.
Calling eglDestroySurface is insufficient to unblock eglSwapBuffers, as
it attempts to grab the same underlying mutex.
Instead, this commit makes it so that we pass a 0 interval to
eglSwapBuffers when running on Wayland, such that we don't block waiting
for a frame callback. This is not entirely ideal as it *does* mean
Looking Glass submits buffers while hidden, but it seems better than
hanging on exit.
It also forces opengl:vsync and egl:vsync flags to off when running on
Wayland, as they are meaningless there.
Note: This only works with the KVMFR kernel module in a VM->VM
configuration. If this causes issues it can be disabled with the new
option `app:allowDMA`
[Why]
Recent versions of Mesa may have trouble with surface creation, resulting in
errors like:
egl.c:428 | egl_render_startup | Failed to create EGL surface (eglError: 0x300b)
[How]
Replace eglGetDisplay() with eglGetPlatformDisplay(). Requires EGL 1.5, but should
be supported with any desktop driver released in the past few years.
This changes the method of the memory copy from the host application to
the guest. Instead of performing a full copy from the capture device
into shared memory, and then flagging the new frame, we instead set a
write pointer, flag the client that there is a new frame and then copy
in chunks of 1024 bytes until the entire frame is copied. The client
upon seeing the new frame flag begins to poll at high frequency the
write pointer and upon each update copies as much as it can into the
texture.
This should improve latency but also slightly increase CPU usage on the
client due to the high frequency polling.