mirror of
https://github.com/gnif/LookingGlass.git
synced 2025-11-17 15:38:45 +00:00
Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3df7d30cd5 | ||
|
|
74444f8eed | ||
|
|
6c43650cd3 | ||
|
|
181ee2b4f5 | ||
|
|
5bef733647 | ||
|
|
22cef47bc4 | ||
|
|
5b25e20a2e | ||
|
|
bb5c7a222c | ||
|
|
39ea6b0587 | ||
|
|
ddc6cb5277 | ||
|
|
b13a79880b | ||
|
|
53fdc2e148 | ||
|
|
9872d2e407 | ||
|
|
3ccf6de868 | ||
|
|
12461196c3 | ||
|
|
15ec80e80d | ||
|
|
d6eb72331c | ||
|
|
eea0ced627 | ||
|
|
94684324f4 | ||
|
|
194afa2d75 | ||
|
|
d96b2ef1fb | ||
|
|
ad40ea4195 | ||
|
|
65948034dd | ||
|
|
9d47ca4f12 | ||
|
|
27c7054505 | ||
|
|
02b59ba8f7 | ||
|
|
a5727262cd | ||
|
|
43545a4e17 | ||
|
|
adbe333414 | ||
|
|
5f80ce91e8 | ||
|
|
b6fa296d5a | ||
|
|
2e170ad06f | ||
|
|
a6720db749 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -8,3 +8,5 @@ module/modules.order
|
||||
*.o
|
||||
*.exe
|
||||
*/build
|
||||
__pycache__
|
||||
*.py[co]
|
||||
|
||||
@@ -2,6 +2,17 @@ cmake_minimum_required(VERSION 3.0)
|
||||
project(looking-glass-client C CXX)
|
||||
|
||||
get_filename_component(PROJECT_TOP "${PROJECT_SOURCE_DIR}/.." ABSOLUTE)
|
||||
|
||||
if(PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR)
|
||||
message(FATAL_ERROR
|
||||
"\n"
|
||||
"In-source builds are not supported\n"
|
||||
"See build instructions provided in: "
|
||||
"${PROJECT_TOP}/doc/build.rst\n"
|
||||
"Refusing to continue"
|
||||
)
|
||||
endif()
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${PROJECT_TOP}/cmake/" "${PROJECT_SOURCE_DIR}/cmake/")
|
||||
|
||||
include(CheckSubmodule)
|
||||
|
||||
@@ -217,5 +217,6 @@ void waylandSetPointer(LG_DSPointer pointer)
|
||||
wlWm.cursor = wlWm.cursors[pointer];
|
||||
wlWm.cursorHotX = wlWm.cursorHot[pointer].x;
|
||||
wlWm.cursorHotY = wlWm.cursorHot[pointer].y;
|
||||
wl_pointer_set_cursor(wlWm.pointer, wlWm.pointerEnterSerial, wlWm.cursor, wlWm.cursorHotX, wlWm.cursorHotY);
|
||||
if (wlWm.pointer)
|
||||
wl_pointer_set_cursor(wlWm.pointer, wlWm.pointerEnterSerial, wlWm.cursor, wlWm.cursorHotX, wlWm.cursorHotY);
|
||||
}
|
||||
|
||||
@@ -290,20 +290,53 @@ static const struct wl_keyboard_listener keyboardListener = {
|
||||
.modifiers = keyboardModifiersHandler,
|
||||
};
|
||||
|
||||
static void waylandCleanUpPointer(void)
|
||||
{
|
||||
INTERLOCKED_SECTION(wlWm.confineLock, {
|
||||
if (wlWm.lockedPointer)
|
||||
{
|
||||
zwp_locked_pointer_v1_destroy(wlWm.lockedPointer);
|
||||
wlWm.lockedPointer = NULL;
|
||||
}
|
||||
|
||||
if (wlWm.confinedPointer)
|
||||
{
|
||||
zwp_confined_pointer_v1_destroy(wlWm.confinedPointer);
|
||||
wlWm.confinedPointer = NULL;
|
||||
}
|
||||
});
|
||||
|
||||
if (wlWm.relativePointer)
|
||||
{
|
||||
zwp_relative_pointer_v1_destroy(wlWm.relativePointer);
|
||||
wlWm.relativePointer = NULL;
|
||||
}
|
||||
|
||||
wl_pointer_destroy(wlWm.pointer);
|
||||
wlWm.pointer = NULL;
|
||||
}
|
||||
|
||||
// Seat-handling listeners.
|
||||
|
||||
static void handlePointerCapability(uint32_t capabilities)
|
||||
{
|
||||
bool hasPointer = capabilities & WL_SEAT_CAPABILITY_POINTER;
|
||||
if (!hasPointer && wlWm.pointer)
|
||||
{
|
||||
wl_pointer_destroy(wlWm.pointer);
|
||||
wlWm.pointer = NULL;
|
||||
}
|
||||
waylandCleanUpPointer();
|
||||
else if (hasPointer && !wlWm.pointer)
|
||||
{
|
||||
wlWm.pointer = wl_seat_get_pointer(wlWm.seat);
|
||||
wl_pointer_add_listener(wlWm.pointer, &pointerListener, NULL);
|
||||
waylandSetPointer(wlWm.cursorId);
|
||||
|
||||
if (wlWm.warpSupport)
|
||||
{
|
||||
wlWm.relativePointer =
|
||||
zwp_relative_pointer_manager_v1_get_relative_pointer(
|
||||
wlWm.relativePointerManager, wlWm.pointer);
|
||||
zwp_relative_pointer_v1_add_listener(wlWm.relativePointer,
|
||||
&relativePointerListener, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -375,15 +408,6 @@ bool waylandInputInit(void)
|
||||
wl_seat_add_listener(wlWm.seat, &seatListener, NULL);
|
||||
wl_display_roundtrip(wlWm.display);
|
||||
|
||||
if (wlWm.warpSupport)
|
||||
{
|
||||
wlWm.relativePointer =
|
||||
zwp_relative_pointer_manager_v1_get_relative_pointer(
|
||||
wlWm.relativePointerManager, wlWm.pointer);
|
||||
zwp_relative_pointer_v1_add_listener(wlWm.relativePointer,
|
||||
&relativePointerListener, NULL);
|
||||
}
|
||||
|
||||
LG_LOCK_INIT(wlWm.confineLock);
|
||||
|
||||
return true;
|
||||
@@ -393,8 +417,15 @@ void waylandInputFree(void)
|
||||
{
|
||||
waylandUngrabPointer();
|
||||
LG_LOCK_FREE(wlWm.confineLock);
|
||||
wl_pointer_destroy(wlWm.pointer);
|
||||
wl_keyboard_destroy(wlWm.keyboard);
|
||||
|
||||
if (wlWm.pointer)
|
||||
waylandCleanUpPointer();
|
||||
|
||||
// The only legal way the keyboard can be null is if it never existed.
|
||||
// When unplugged, the compositor must have an inert object.
|
||||
if (wlWm.keyboard)
|
||||
wl_keyboard_destroy(wlWm.keyboard);
|
||||
|
||||
wl_seat_destroy(wlWm.seat);
|
||||
|
||||
if (wlWm.xkbState)
|
||||
@@ -508,7 +539,7 @@ void waylandUncapturePointer(void)
|
||||
*/
|
||||
if (!wlWm.warpSupport || !app_isFormatValid() || app_isCaptureOnlyMode())
|
||||
internalUngrabPointer(false);
|
||||
else
|
||||
else if (wlWm.pointer)
|
||||
{
|
||||
wlWm.confinedPointer = zwp_pointer_constraints_v1_confine_pointer(
|
||||
wlWm.pointerConstraints, wlWm.surface, wlWm.pointer, NULL,
|
||||
|
||||
@@ -95,6 +95,9 @@ static bool waylandInit(const LG_DSInitParams params)
|
||||
if (!waylandPresentationInit())
|
||||
return false;
|
||||
|
||||
if (!waylandCursorInit())
|
||||
return false;
|
||||
|
||||
if (!waylandInputInit())
|
||||
return false;
|
||||
|
||||
@@ -104,9 +107,6 @@ static bool waylandInit(const LG_DSInitParams params)
|
||||
if (!waylandEGLInit(params.w, params.h))
|
||||
return false;
|
||||
|
||||
if (!waylandCursorInit())
|
||||
return false;
|
||||
|
||||
#ifdef ENABLE_OPENGL
|
||||
if (params.opengl && !waylandOpenGLInit())
|
||||
return false;
|
||||
|
||||
@@ -22,11 +22,15 @@
|
||||
#define _H_X11DS_ATOMS_
|
||||
|
||||
#define DEF_ATOMS() \
|
||||
DEF_ATOM(_NET_SUPPORTING_WM_CHECK, True) \
|
||||
DEF_ATOM(_NET_SUPPORTED, True) \
|
||||
DEF_ATOM(_NET_WM_NAME, True) \
|
||||
DEF_ATOM(_NET_REQUEST_FRAME_EXTENTS, True) \
|
||||
DEF_ATOM(_NET_FRAME_EXTENTS, True) \
|
||||
DEF_ATOM(_NET_WM_BYPASS_COMPOSITOR, False) \
|
||||
DEF_ATOM(_NET_WM_STATE, True) \
|
||||
DEF_ATOM(_NET_WM_STATE_FULLSCREEN, True) \
|
||||
DEF_ATOM(_NET_WM_STATE_FOCUSED, True) \
|
||||
DEF_ATOM(_NET_WM_STATE_MAXIMIZED_HORZ, True) \
|
||||
DEF_ATOM(_NET_WM_STATE_MAXIMIZED_VERT, True) \
|
||||
DEF_ATOM(_NET_WM_WINDOW_TYPE, True) \
|
||||
|
||||
@@ -82,8 +82,9 @@ static void x11SetFullscreen(bool fs);
|
||||
static int x11EventThread(void * unused);
|
||||
static void x11XInputEvent(XGenericEventCookie *cookie);
|
||||
static void x11XPresentEvent(XGenericEventCookie *cookie);
|
||||
static void x11GrabPointer(void);
|
||||
|
||||
static void x11DoPresent(void)
|
||||
static void x11DoPresent(uint64_t msc)
|
||||
{
|
||||
static bool startup = true;
|
||||
if (startup)
|
||||
@@ -113,11 +114,19 @@ static void x11DoPresent(void)
|
||||
|
||||
static bool first = true;
|
||||
static uint64_t lastMsc = 0;
|
||||
uint64_t msc = atomic_load(&x11.presentMsc);
|
||||
|
||||
uint64_t refill;
|
||||
if (!first)
|
||||
refill = 50 - (lastMsc - msc);
|
||||
{
|
||||
const uint64_t delta = (lastMsc >= msc) ?
|
||||
lastMsc - msc :
|
||||
~0ULL - msc + lastMsc;
|
||||
|
||||
if (delta > 50)
|
||||
return;
|
||||
|
||||
refill = 50 - delta;
|
||||
}
|
||||
else
|
||||
{
|
||||
refill = 50;
|
||||
@@ -167,6 +176,69 @@ static bool x11EarlyInit(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void x11CheckEWMHSupport(void)
|
||||
{
|
||||
if (x11atoms._NET_SUPPORTING_WM_CHECK == None ||
|
||||
x11atoms._NET_SUPPORTED == None)
|
||||
return;
|
||||
|
||||
Atom type;
|
||||
int fmt;
|
||||
unsigned long num, bytes;
|
||||
unsigned char *data;
|
||||
|
||||
if (XGetWindowProperty(x11.display, DefaultRootWindow(x11.display),
|
||||
x11atoms._NET_SUPPORTING_WM_CHECK, 0, ~0L, False, XA_WINDOW,
|
||||
&type, &fmt, &num, &bytes, &data) != Success)
|
||||
goto out;
|
||||
|
||||
Window * windowFromRoot = (Window *)data;
|
||||
|
||||
if (XGetWindowProperty(x11.display, *windowFromRoot,
|
||||
x11atoms._NET_SUPPORTING_WM_CHECK, 0, ~0L, False, XA_WINDOW,
|
||||
&type, &fmt, &num, &bytes, &data) != Success)
|
||||
goto out_root;
|
||||
|
||||
Window * windowFromChild = (Window *)data;
|
||||
if (*windowFromChild != *windowFromRoot)
|
||||
goto out_child;
|
||||
|
||||
if (XGetWindowProperty(x11.display, DefaultRootWindow(x11.display),
|
||||
x11atoms._NET_SUPPORTED, 0, ~0L, False, AnyPropertyType,
|
||||
&type, &fmt, &num, &bytes, &data) != Success)
|
||||
goto out_child;
|
||||
|
||||
Atom * supported = (Atom *)data;
|
||||
unsigned long supportedCount = num;
|
||||
|
||||
if (XGetWindowProperty(x11.display, *windowFromRoot,
|
||||
x11atoms._NET_WM_NAME, 0, ~0L, False, AnyPropertyType,
|
||||
&type, &fmt, &num, &bytes, &data) != Success)
|
||||
goto out_supported;
|
||||
|
||||
char * wmName = (char *)data;
|
||||
|
||||
for(unsigned long i = 0; i < supportedCount; ++i)
|
||||
{
|
||||
if (supported[i] == x11atoms._NET_WM_STATE_FOCUSED)
|
||||
x11.ewmhHasFocusEvent = true;
|
||||
}
|
||||
|
||||
DEBUG_INFO("EWMH-complient window manager detected: %s", wmName);
|
||||
x11.ewmhSupport = true;
|
||||
|
||||
|
||||
XFree(wmName);
|
||||
out_supported:
|
||||
XFree(supported);
|
||||
out_child:
|
||||
XFree(windowFromChild);
|
||||
out_root:
|
||||
XFree(windowFromRoot);
|
||||
out:
|
||||
return;
|
||||
}
|
||||
|
||||
static bool x11Init(const LG_DSInitParams params)
|
||||
{
|
||||
XIDeviceInfo *devinfo;
|
||||
@@ -272,6 +344,9 @@ static bool x11Init(const LG_DSInitParams params)
|
||||
X11AtomsInit();
|
||||
XSetWMProtocols(x11.display, x11.window, &x11atoms.WM_DELETE_WINDOW, 1);
|
||||
|
||||
// check for Extended Window Manager Hints support
|
||||
x11CheckEWMHSupport();
|
||||
|
||||
if (params.borderless)
|
||||
{
|
||||
if (x11atoms._MOTIF_WM_HINTS)
|
||||
@@ -457,8 +532,12 @@ static bool x11Init(const LG_DSInitParams params)
|
||||
eventmask.mask_len = sizeof(mask);
|
||||
eventmask.mask = mask;
|
||||
|
||||
XISetMask(mask, XI_FocusIn );
|
||||
XISetMask(mask, XI_FocusOut );
|
||||
if (!x11.ewmhHasFocusEvent)
|
||||
{
|
||||
XISetMask(mask, XI_FocusIn );
|
||||
XISetMask(mask, XI_FocusOut);
|
||||
}
|
||||
|
||||
XISetMask(mask, XI_Enter );
|
||||
XISetMask(mask, XI_Leave );
|
||||
XISetMask(mask, XI_Motion );
|
||||
@@ -615,7 +694,7 @@ static bool x11Init(const LG_DSInitParams params)
|
||||
}
|
||||
|
||||
if (x11.jitRender)
|
||||
x11DoPresent();
|
||||
x11DoPresent(0);
|
||||
|
||||
return true;
|
||||
|
||||
@@ -839,6 +918,7 @@ static int x11EventThread(void * unused)
|
||||
}
|
||||
|
||||
case PropertyNotify:
|
||||
|
||||
// ignore property events that are not for us
|
||||
if (xe.xproperty.display != x11.display ||
|
||||
xe.xproperty.window != x11.window ||
|
||||
@@ -860,11 +940,20 @@ static int x11EventThread(void * unused)
|
||||
break;
|
||||
|
||||
bool fullscreen = false;
|
||||
for(int i = 0; i < num; ++i)
|
||||
bool focused = false;
|
||||
for(unsigned long i = 0; i < num; ++i)
|
||||
{
|
||||
Atom prop = ((Atom *)data)[i];
|
||||
if (prop == x11atoms._NET_WM_STATE_FULLSCREEN)
|
||||
fullscreen = true;
|
||||
else if (prop == x11atoms._NET_WM_STATE_FOCUSED)
|
||||
focused = true;
|
||||
}
|
||||
|
||||
if (x11.ewmhHasFocusEvent && x11.focused != focused)
|
||||
{
|
||||
x11.focused = focused;
|
||||
app_handleFocusEvent(focused);
|
||||
}
|
||||
|
||||
x11.fullscreen = fullscreen;
|
||||
@@ -941,6 +1030,9 @@ static void x11XInputEvent(XGenericEventCookie *cookie)
|
||||
{
|
||||
case XI_FocusIn:
|
||||
{
|
||||
if (x11.ewmhHasFocusEvent)
|
||||
return;
|
||||
|
||||
atomic_store(&x11.lastWMEvent, microtime());
|
||||
if (x11.focused)
|
||||
return;
|
||||
@@ -959,6 +1051,9 @@ static void x11XInputEvent(XGenericEventCookie *cookie)
|
||||
|
||||
case XI_FocusOut:
|
||||
{
|
||||
if (x11.ewmhHasFocusEvent)
|
||||
return;
|
||||
|
||||
atomic_store(&x11.lastWMEvent, microtime());
|
||||
if (!x11.focused)
|
||||
return;
|
||||
@@ -1251,10 +1346,10 @@ static void x11XPresentEvent(XGenericEventCookie *cookie)
|
||||
case PresentCompleteNotify:
|
||||
{
|
||||
XPresentCompleteNotifyEvent * e = cookie->data;
|
||||
x11DoPresent(e->msc);
|
||||
atomic_store(&x11.presentMsc, e->msc);
|
||||
atomic_store(&x11.presentUst, e->ust);
|
||||
lgSignalEvent(x11.frameEvent);
|
||||
x11DoPresent();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1556,7 +1651,10 @@ static void x11GrabPointer(void)
|
||||
XISetMask(mask.mask, XI_Enter );
|
||||
XISetMask(mask.mask, XI_Leave );
|
||||
|
||||
Status ret = XIGrabDevice(
|
||||
Status ret;
|
||||
for(int retry = 0; retry < 10; ++retry)
|
||||
{
|
||||
ret = XIGrabDevice(
|
||||
x11.display,
|
||||
x11.pointerDev,
|
||||
x11.window,
|
||||
@@ -1567,6 +1665,18 @@ static void x11GrabPointer(void)
|
||||
XINoOwnerEvents,
|
||||
&mask);
|
||||
|
||||
// on some WMs (i3) for an unknown reason the first grab attempt when
|
||||
// switching to a desktop that has LG on it fails with GrabFrozen, however
|
||||
// adding as short delay seems to resolve the issue.
|
||||
if (ret == GrabFrozen && retry < 9)
|
||||
{
|
||||
usleep(100000);
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret != Success)
|
||||
{
|
||||
x11PrintGrabError("pointer", x11.pointerDev, ret);
|
||||
|
||||
@@ -54,6 +54,11 @@ struct X11DSState
|
||||
Window window;
|
||||
XVisualInfo * visual;
|
||||
|
||||
//Extended Window Manager Hints
|
||||
//ref: https://specifications.freedesktop.org/wm-spec/latest/
|
||||
bool ewmhSupport;
|
||||
bool ewmhHasFocusEvent;
|
||||
|
||||
_Atomic(uint64_t) lastWMEvent;
|
||||
bool invalidateAll;
|
||||
|
||||
|
||||
@@ -326,6 +326,13 @@ bool egl_desktopUpdate(EGL_Desktop * desktop, const FrameBuffer * frame, int dma
|
||||
|
||||
desktop->useDMA = false;
|
||||
|
||||
const char * gl_exts = (const char *)glGetString(GL_EXTENSIONS);
|
||||
if (!util_hasGLExt(gl_exts, "GL_EXT_buffer_storage"))
|
||||
{
|
||||
DEBUG_ERROR("GL_EXT_buffer_storage is needed to use EGL backend");
|
||||
return false;
|
||||
}
|
||||
|
||||
egl_textureFree(&desktop->texture);
|
||||
if (!egl_textureInit(&desktop->texture, desktop->display,
|
||||
EGL_TEXTYPE_FRAMEBUFFER, true))
|
||||
|
||||
@@ -798,12 +798,6 @@ static bool egl_renderStartup(LG_Renderer * renderer, bool useDMA)
|
||||
glGetIntegerv(GL_MAJOR_VERSION, &esMaj);
|
||||
glGetIntegerv(GL_MINOR_VERSION, &esMin);
|
||||
|
||||
if (!util_hasGLExt(gl_exts, "GL_EXT_buffer_storage"))
|
||||
{
|
||||
DEBUG_ERROR("GL_EXT_buffer_storage is needed to use EGL backend");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!util_hasGLExt(gl_exts, "GL_EXT_texture_format_BGRA8888"))
|
||||
{
|
||||
DEBUG_ERROR("GL_EXT_texture_format_BGRA8888 is needed to use EGL backend");
|
||||
@@ -836,7 +830,14 @@ static bool egl_renderStartup(LG_Renderer * renderer, bool useDMA)
|
||||
this->dmaSupport = true;
|
||||
|
||||
if (!this->dmaSupport)
|
||||
{
|
||||
useDMA = false;
|
||||
if (!util_hasGLExt(gl_exts, "GL_EXT_buffer_storage"))
|
||||
{
|
||||
DEBUG_ERROR("GL_EXT_buffer_storage is needed to use EGL backend");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (debugContext)
|
||||
{
|
||||
|
||||
@@ -268,6 +268,19 @@ void core_updatePositionInfo(void)
|
||||
{
|
||||
g_state.posInfoValid = true;
|
||||
g_state.ds->realignPointer();
|
||||
|
||||
// g_cursor.guest.valid could have become true in the meantime.
|
||||
if (g_cursor.guest.valid)
|
||||
{
|
||||
// Since posInfoValid was false, core_handleGuestMouseUpdate becomes a
|
||||
// noop when called on the cursor thread, which means we need to call it
|
||||
// again in order for the cursor to show up.
|
||||
core_handleGuestMouseUpdate();
|
||||
|
||||
// Similarly, the position needs to be valid before the initial mouse
|
||||
// move, otherwise we wouldn't know if the cursor is in the viewport.
|
||||
app_handleMouseRelative(0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
@@ -435,7 +448,8 @@ void core_handleMouseNormal(double ex, double ey)
|
||||
struct DoublePoint guest;
|
||||
util_localCurToGuest(&guest);
|
||||
|
||||
if (g_state.kvmfrFeatures & KVMFR_FEATURE_SETCURSORPOS)
|
||||
if (!g_state.stopVideo &&
|
||||
g_state.kvmfrFeatures & KVMFR_FEATURE_SETCURSORPOS)
|
||||
{
|
||||
const KVMFRSetCursorPos msg = {
|
||||
.msg.type = KVMFR_MESSAGE_SETCURSORPOS,
|
||||
|
||||
@@ -140,7 +140,7 @@ frames from the guest.
|
||||
|
||||
.. note::
|
||||
|
||||
If you are using GNOME on Wayland, you likely want to pass
|
||||
For users running GNOME on Wayland, you likely want to pass
|
||||
``-DENABLE_LIBDECOR=ON`` to ``cmake``, i.e. run ``cmake -DENABLE_LIBDECOR=ON ../``.
|
||||
|
||||
For details, see :ref:`the FAQ <gnome_wayland_decorations>`.
|
||||
|
||||
@@ -71,8 +71,8 @@ master_doc = 'index'
|
||||
html_theme = 'alabaster'
|
||||
|
||||
html_theme_options = {
|
||||
'logo': 'icon-128x128.png',
|
||||
'fixed_sidebar': 'true',
|
||||
'logo': 'icon-128x128.png',
|
||||
'fixed_sidebar': 'true',
|
||||
}
|
||||
|
||||
html_sidebars = {
|
||||
|
||||
29
doc/faq.rst
29
doc/faq.rst
@@ -79,26 +79,29 @@ well.
|
||||
|
||||
.. _gnome_wayland_decorations:
|
||||
|
||||
Why is there no title bar? / Why can't I resize the window?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Why is there no title bar on GNOME? / Why can't I resize the window on GNOME?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This happens on GNOME Wayland because GNOME doesn't support the `standard
|
||||
protocol`_ for server-side decorations. As a result, the window decorations
|
||||
do not appear.
|
||||
This happens because GNOME on Wayland doesn't support the `standard protocol`_
|
||||
for server-side decorations, and Looking Glass doesn't implement its own
|
||||
decorations.
|
||||
|
||||
The easy solution is to use `libdecor`_. This is currently not packaged in
|
||||
most distros, so you will need to build it from the linked git repository.
|
||||
The easiest solution is to build Looking Glass with `libdecor`_ support.
|
||||
If your distribution lacks a ``libdecor`` package, you must build it from
|
||||
`source code <libdecor_>`_.
|
||||
|
||||
Once you have built it, you can then build the the client with libdecor
|
||||
support by passing ``-DENABLE_LIBDECOR=ON`` to ``cmake``.
|
||||
|
||||
Please be aware that libdecor comes with overheads, which is why it is not
|
||||
used by default. You should avoid it if possible.
|
||||
You can then build the the client with libdecor support by passing
|
||||
``-DENABLE_LIBDECOR=ON`` to ``cmake``.
|
||||
|
||||
An alternative solution is to hold down the Super key (Windows key on most
|
||||
keyboards), and then right click on the window. This should bring up a menu,
|
||||
keyboards), then right click Looking Glass. This should bring up a menu,
|
||||
which will allow you to move the window and resize it.
|
||||
|
||||
.. warning::
|
||||
Libdecor support is provided for the convenience of our Wayland users on
|
||||
GNOME, however it is not a priority feature and may break, please seek
|
||||
alternatives if you require stable operation.
|
||||
|
||||
.. _standard protocol: https://wayland.app/protocols/xdg-decoration-unstable-v1
|
||||
.. _libdecor: https://gitlab.gnome.org/jadahl/libdecor
|
||||
|
||||
|
||||
167
doc/install.rst
167
doc/install.rst
@@ -289,21 +289,23 @@ Examples:
|
||||
Configuration Files
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
By default, the application will look for and load the config files in
|
||||
the following locations and order:
|
||||
By default, Looking Glass will load config files from
|
||||
the following locations:
|
||||
|
||||
- /etc/looking-glass-client.ini
|
||||
- ~/.looking-glass-client.ini
|
||||
- $XDG_CONFIG_HOME/looking-glass/client.ini (usually ~/.config/looking-glass/client.ini)
|
||||
|
||||
Config options are merged from all files. Same options appearing in more
|
||||
than one file will be overridden by the latest loaded one (E.g. an option
|
||||
appearing in ~/.config/looking-glass/client.ini will override the same
|
||||
option appearing in ~/.looking-glass-client.ini). When first launched,
|
||||
the Looking-Glass client will create the folder $XDG_CONFIG_HOME/looking-glass/
|
||||
if it does not yet exist.
|
||||
All config files are loaded in order. Duplicate entries override earlier ones.
|
||||
This means you can set a system-wide configuration in
|
||||
``/etc/looking-glass-client.ini``, and override specific options for just
|
||||
your user in ``~/.looking-glass-client.ini``, which is overlayed on top of
|
||||
the system-wide configuration.
|
||||
|
||||
The format of this file is the commonly known INI format, for example::
|
||||
When first launched, the Looking-Glass client will create the folder
|
||||
$XDG_CONFIG_HOME/looking-glass/ if it does not yet exist.
|
||||
|
||||
The format of config files is the commonly known INI format, for example::
|
||||
|
||||
[win]
|
||||
fullScreen=yes
|
||||
@@ -311,7 +313,7 @@ The format of this file is the commonly known INI format, for example::
|
||||
[egl]
|
||||
nvGain=1
|
||||
|
||||
Command line arguments will override any options loaded from the config
|
||||
Command line arguments will override any options loaded from config
|
||||
files.
|
||||
|
||||
.. _client_overlay_mode:
|
||||
@@ -319,82 +321,77 @@ files.
|
||||
Overlay Mode
|
||||
~~~~~~~~~~~~
|
||||
|
||||
Looking-Glass is utilizing an overlay layer to draw various widgets (such
|
||||
as the FPS display). An "Overlay Mode" can be toggled (see
|
||||
:ref:`client_key_bindings`) that allows editing and modifying widgets
|
||||
properties, such as their position and size. To use the Overlay Mode:
|
||||
The Overlay Mode lets you configure various runtime options for Looking Glass.
|
||||
These include:
|
||||
|
||||
- Enable one or more widgets (such as the FPS display)
|
||||
- Enter Overlay Mode by using its keybinding (the screen will turn
|
||||
darker to indicate Overlay Mode is active)
|
||||
- Drag the widgets you enabled to your preferred position
|
||||
- Change the widget size (if the widget allows you) by dragging the
|
||||
lower right edge
|
||||
- Change any other properties a widget has and are modifiable
|
||||
- Exit Overlay Mode by pressing :kbd:`ESC` or using the Overlay-Mode
|
||||
keybinding again
|
||||
- EGL filters
|
||||
- Performance metrics options
|
||||
- Debug frame damage display
|
||||
|
||||
Modifications done in Overlay Mode are persistent and are stored
|
||||
in a special config file $XDG_CONFIG_HOME/looking-glass/imgui.ini.
|
||||
Please refrain from editing this file manually as your changes might
|
||||
be overwritten by the client.
|
||||
(see :ref:`client_config_widget`)
|
||||
|
||||
You can also reposition and resize enabled widgets, like the FPS/UPS Display,
|
||||
and Performance Metrics.
|
||||
|
||||
Enter and exit Overlay Mode with :kbd:`ScrLk` + :kbd:`O`.
|
||||
:kbd:`ESC` can also be used to exit. (see :ref:`client_key_bindings`)
|
||||
|
||||
Modifications done to widgets in Overlay Mode are stored in
|
||||
``$XDG_CONFIG_HOME/looking-glass/imgui.ini``.
|
||||
Please do not manually edit this file while Looking Glass is running,
|
||||
as your changes may be discarded.
|
||||
|
||||
.. _client_config_widget:
|
||||
|
||||
Configuration Widget
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The Configuration Widget is accessible through the Overlay mode. The
|
||||
The Configuration Widget is accessible through the Overlay Mode. The
|
||||
widget has multiple tabs that allow setting a variety of modes and
|
||||
parameters for the application.
|
||||
parameters for Looking Glass at runtime.
|
||||
|
||||
Settings tab
|
||||
^^^^^^^^^^^^
|
||||
|
||||
- Performance Metrics: Enabling this will turn on the Metrics Graphs
|
||||
Widget. Multiple graphs can be enabled and they will stack vertically.
|
||||
- EGL: Modify EGL features such as the algorithm used for scaling and
|
||||
enabling night vision mode.
|
||||
- Performance Metrics: A toggle for the Performance Metrics Widget.
|
||||
Multiple graphs are available, and they will stack vertically.
|
||||
- EGL: Modify EGL features, such as the algorithm used for scaling, and
|
||||
night vision mode.
|
||||
|
||||
Changes in the Settings tab are not persistent and will change back to
|
||||
Changes in the Settings tab are not persistent, and will change back to
|
||||
their default values when the client is restarted.
|
||||
|
||||
EGL Filters tab
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
The EGL Filters tab is a GUI for enabling, configuring and ordering
|
||||
the post-processing filter stack. Each filter can be expanded to open
|
||||
its settings. Filters can also be re-ordered by dragging them up or down.
|
||||
Filters application is cumulative, and order is important (e.g. applying CAS
|
||||
before FSR might have different results than the reverse). Users are
|
||||
encouraged to experiment with the order and parameters to achieve optimal
|
||||
results. The currently available filters include:
|
||||
The EGL Filters tab contains options for toggling, configuring, and ordering
|
||||
post-processing filters. Each filter can be expanded to open its settings.
|
||||
Filters can also be re-ordered by dragging them up or down. Filters are applied
|
||||
from top to bottom, keep this in mind when ordering them, e.g applying CAS
|
||||
before FSR might have different results than the reverse. Users are encouraged
|
||||
to experiment with the order and parameters to achieve optimal results. The
|
||||
currently available filters include:
|
||||
|
||||
- Downscaler: Filter for downscaling resolution. Can be used to undo the
|
||||
poor upscaling that some games implement such that it can then
|
||||
be better upscaled using FSR (see below). The filter has a pixel-size setting
|
||||
that is used to set the effective downscaling ratio and can be set to use
|
||||
different downscaling algorithms.
|
||||
- AMD FidelityFX Super Resolution (FSR): Filter implementing a rendering
|
||||
technique for upscaling resolution. FSR works by accepting the original
|
||||
frames (on the guest) at lower resolution, then applying a spatial upscaling
|
||||
algorithm in the client to make the final result look as though it is
|
||||
rendered in high-resolution. The FSR filter interface allows for fine
|
||||
tuning the sharpness factor of the algorithm and shows the equivalent
|
||||
quality mode based on the ratio between the original frame resolution
|
||||
and the client resolution.
|
||||
- AMD FidelityFX Contrast Adaptive Sharpening (CAS): Filter that
|
||||
increases visual quality by applying a sharpening algorithm to the
|
||||
frame. CAS can sometimes restore detail lost in a typical upscaling
|
||||
application. The CAS filter interface has an adjustable sharpness
|
||||
control.
|
||||
- Downscaler: Filter for downscaling the host resolution. Can be used to undo
|
||||
poor upscaling on the VM to better utilize AMD FSR (see below). The filter
|
||||
has a pixel-size setting that is used to set the effective downscaling ratio,
|
||||
and a configurable interpolation algorithm.
|
||||
|
||||
The filter stack settings and order can be saved to presets so that it
|
||||
can be conveniently recalled at a later time. As filter settings are
|
||||
usually application specific, multiple presets can be defined for each
|
||||
case scenario. To save a preset, click on "Save preset as..." and enter
|
||||
a preset name. Presets are recalled by selecting them in the "Preset name"
|
||||
pull down. Presets are persistent and are stored on disk at
|
||||
- AMD FidelityFX Super Resolution (FSR): Spatial upscaling filter that works
|
||||
on low resolution frames from the guest VM and intelligently upscales to a
|
||||
higher resolution. The filter sharpness is tunable, and displays the
|
||||
equivalent AMD quality mode based on the resolution difference.
|
||||
|
||||
- AMD FidelityFX Contrast Adaptive Sharpening (CAS): Filter that
|
||||
increases visual quality by applying a sharpening algorithm to the
|
||||
video. CAS can sometimes restore detail lost in a typical upscaling
|
||||
application. Has adjustable sharpness setting.
|
||||
|
||||
The filter settings and order can be saved to presets so that it can be restored
|
||||
at a later time. As filter settings are usually application specific, multiple
|
||||
presets can be defined for each case scenario. To save a preset, click on "Save
|
||||
preset as..." and enter a preset name. Presets are loaded by selecting them in
|
||||
the "Preset name" pull down. Presets are persistent and are stored on disk at
|
||||
``$XDG_CONFIG_HOME/looking-glass/presets``.
|
||||
|
||||
.. warning::
|
||||
@@ -413,23 +410,23 @@ Full Command Line Options
|
||||
|
||||
The following is a complete list of options accepted by this application
|
||||
|
||||
+------------------------+-------+------------------------+------------------------------------------------------------------------------------------+
|
||||
| Long | Short | Value | Description |
|
||||
+========================+=======+========================+==========================================================================================+
|
||||
| app:configFile | -C | NULL | A file to read additional configuration from |
|
||||
+------------------------+-------+------------------------+------------------------------------------------------------------------------------------+
|
||||
| app:renderer | -g | auto | Specify the renderer to use |
|
||||
+------------------------+-------+------------------------+------------------------------------------------------------------------------------------+
|
||||
| app:license | -l | no | Show the license for this application and then terminate |
|
||||
+------------------------+-------+------------------------+------------------------------------------------------------------------------------------+
|
||||
| app:cursorPollInterval | | 1000 | How often to check for a cursor update in microseconds |
|
||||
+------------------------+-------+------------------------+------------------------------------------------------------------------------------------+
|
||||
| app:framePollInterval | | 1000 | How often to check for a frame update in microseconds |
|
||||
+------------------------+-------+------------------------+------------------------------------------------------------------------------------------+
|
||||
| app:allowDMA | | yes | Allow direct DMA transfers if supported (see `README.md` in the `module` dir) |
|
||||
+------------------------+-------+------------------------+------------------------------------------------------------------------------------------+
|
||||
| app:shmFile | -f | /dev/shm/looking-glass | The path to the shared memory file, or the name of the kvmfr device to use, e.g.: kvmfr0 |
|
||||
+------------------------+-------+------------------------+------------------------------------------------------------------------------------------+
|
||||
+------------------------+-------+------------------------+-----------------------------------------------------------------------------------------+
|
||||
| Long | Short | Value | Description |
|
||||
+========================+=======+========================+=========================================================================================+
|
||||
| app:configFile | -C | NULL | A file to read additional configuration from |
|
||||
+------------------------+-------+------------------------+-----------------------------------------------------------------------------------------+
|
||||
| app:renderer | -g | auto | Specify the renderer to use |
|
||||
+------------------------+-------+------------------------+-----------------------------------------------------------------------------------------+
|
||||
| app:license | -l | no | Show the license for this application and then terminate |
|
||||
+------------------------+-------+------------------------+-----------------------------------------------------------------------------------------+
|
||||
| app:cursorPollInterval | | 1000 | How often to check for a cursor update in microseconds |
|
||||
+------------------------+-------+------------------------+-----------------------------------------------------------------------------------------+
|
||||
| app:framePollInterval | | 1000 | How often to check for a frame update in microseconds |
|
||||
+------------------------+-------+------------------------+-----------------------------------------------------------------------------------------+
|
||||
| app:allowDMA | | yes | Allow direct DMA transfers if supported (see `README.md` in the `module` dir) |
|
||||
+------------------------+-------+------------------------+-----------------------------------------------------------------------------------------+
|
||||
| app:shmFile | -f | /dev/shm/looking-glass | The path to the shared memory file, or the name of the kvmfr device to use, e.g. kvmfr0 |
|
||||
+------------------------+-------+------------------------+-----------------------------------------------------------------------------------------+
|
||||
|
||||
+-------------------------+-------+------------------------+----------------------------------------------------------------------+
|
||||
| Long | Short | Value | Description |
|
||||
@@ -462,7 +459,7 @@ The following is a complete list of options accepted by this application
|
||||
+-------------------------+-------+------------------------+----------------------------------------------------------------------+
|
||||
| win:fpsMin | -K | -1 | Frame rate minimum (0 = disable - not recommended, -1 = auto detect) |
|
||||
+-------------------------+-------+------------------------+----------------------------------------------------------------------+
|
||||
| win:ignoreQuit | -Q | no | Ignore requests to quit (i.e.: Alt+F4) |
|
||||
| win:ignoreQuit | -Q | no | Ignore requests to quit (i.e. Alt+F4) |
|
||||
+-------------------------+-------+------------------------+----------------------------------------------------------------------+
|
||||
| win:noScreensaver | -S | no | Prevent the screensaver from starting |
|
||||
+-------------------------+-------+------------------------+----------------------------------------------------------------------+
|
||||
@@ -558,6 +555,10 @@ The following is a complete list of options accepted by this application
|
||||
+------------------+-------+-------+---------------------------------------------------------------------------+
|
||||
| egl:debug | | no | Enable debug output |
|
||||
+------------------+-------+-------+---------------------------------------------------------------------------+
|
||||
| egl:noBufferAge | | no | Disable partial rendering based on buffer age |
|
||||
+------------------+-------+-------+---------------------------------------------------------------------------+
|
||||
| egl:noSwapDamage | | no | Disable swapping with damage |
|
||||
+------------------+-------+-------+---------------------------------------------------------------------------+
|
||||
|
||||
+----------------------+-------+-------+---------------------------------------------+
|
||||
| Long | Short | Value | Description |
|
||||
|
||||
@@ -166,7 +166,30 @@ Add the following arguments to your ``qemu`` command line::
|
||||
libvirt
|
||||
^^^^^^^
|
||||
|
||||
Create the following XML block in your domain:
|
||||
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":33554432,"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 <client_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
|
||||
|
||||
@@ -179,8 +202,12 @@ Create the following XML block in your domain:
|
||||
|
||||
.. note::
|
||||
|
||||
Remember to add ``xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'``
|
||||
to the ``<domain>`` tag.
|
||||
- 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``"
|
||||
|
||||
- Remember to add ``xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'``
|
||||
to the ``<domain>`` tag.
|
||||
|
||||
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
|
||||
|
||||
10
doc/obs.rst
10
doc/obs.rst
@@ -47,7 +47,7 @@ These instructions are similar to building the
|
||||
cmake -DUSER_INSTALL=1 ../
|
||||
make
|
||||
|
||||
Alternatively if you would like to install the plugin for all users.
|
||||
Alternatively, if you would like to install the plugin for all users:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
@@ -59,15 +59,19 @@ Alternatively if you would like to install the plugin for all users.
|
||||
Installation
|
||||
~~~~~~~~~~~~
|
||||
|
||||
You can install the plugin for by running ``make install``.
|
||||
You can install the plugin by running ``make install``.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
make install
|
||||
|
||||
If you opted to install the plugin for all users you will need to run
|
||||
If you've opted to install the plugin for all users, you will need to run
|
||||
this command as ``root``.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
sudo make install
|
||||
|
||||
Setup
|
||||
~~~~~
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ modprobe
|
||||
msys
|
||||
multisampling
|
||||
Nvidia
|
||||
overlayed
|
||||
pacman
|
||||
passthrough
|
||||
pre
|
||||
@@ -38,11 +39,13 @@ radeon
|
||||
realtime
|
||||
renderer
|
||||
repo
|
||||
runtime
|
||||
submodule
|
||||
submodules
|
||||
systemd
|
||||
toolchain
|
||||
tritanope
|
||||
tunable
|
||||
udev
|
||||
UEFI
|
||||
uncheck
|
||||
@@ -51,6 +54,7 @@ Unigine
|
||||
unix
|
||||
upscaled
|
||||
upscaler
|
||||
upscales
|
||||
upscaling
|
||||
VM
|
||||
vsync
|
||||
|
||||
@@ -1,12 +1,23 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
project(looking-glass-host C)
|
||||
|
||||
get_filename_component(PROJECT_TOP "${PROJECT_SOURCE_DIR}/.." ABSOLUTE)
|
||||
|
||||
if(PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR)
|
||||
message(FATAL_ERROR
|
||||
"\n"
|
||||
"In-source builds are not supported\n"
|
||||
"See build instructions provided in: "
|
||||
"${PROJECT_TOP}/doc/build.rst\n"
|
||||
"Refusing to continue"
|
||||
)
|
||||
endif()
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${PROJECT_TOP}/cmake/" "${PROJECT_SOURCE_DIR}/cmake/")
|
||||
|
||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O3 -g -DNDEBUG" CACHE STRING "compiler flags" FORCE)
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -g -DNDEBUG" CACHE STRING "compiler flags" FORCE)
|
||||
|
||||
get_filename_component(PROJECT_TOP "${PROJECT_SOURCE_DIR}/.." ABSOLUTE)
|
||||
list(APPEND CMAKE_MODULE_PATH "${PROJECT_TOP}/cmake/" "${PROJECT_SOURCE_DIR}/cmake/")
|
||||
|
||||
include(CheckSubmodule)
|
||||
include(GNUInstallDirs)
|
||||
include(CheckCCompilerFlag)
|
||||
|
||||
@@ -319,13 +319,13 @@ static bool dxgi_init(void)
|
||||
|
||||
DXGI_ADAPTER_DESC1 adapterDesc;
|
||||
IDXGIAdapter1_GetDesc1(this->adapter, &adapterDesc);
|
||||
DEBUG_INFO("Device Name : %ls" , outputDesc.DeviceName);
|
||||
DEBUG_INFO("Device Descripion: %ls" , adapterDesc.Description);
|
||||
DEBUG_INFO("Device Vendor ID : 0x%x" , adapterDesc.VendorId);
|
||||
DEBUG_INFO("Device Device ID : 0x%x" , adapterDesc.DeviceId);
|
||||
DEBUG_INFO("Device Video Mem : %u MiB" , (unsigned)(adapterDesc.DedicatedVideoMemory / 1048576));
|
||||
DEBUG_INFO("Device Sys Mem : %u MiB" , (unsigned)(adapterDesc.DedicatedSystemMemory / 1048576));
|
||||
DEBUG_INFO("Shared Sys Mem : %u MiB" , (unsigned)(adapterDesc.SharedSystemMemory / 1048576));
|
||||
DEBUG_INFO("Device Name : %ls" , outputDesc.DeviceName);
|
||||
DEBUG_INFO("Device Description: %ls" , adapterDesc.Description);
|
||||
DEBUG_INFO("Device Vendor ID : 0x%x" , adapterDesc.VendorId);
|
||||
DEBUG_INFO("Device Device ID : 0x%x" , adapterDesc.DeviceId);
|
||||
DEBUG_INFO("Device Video Mem : %u MiB" , (unsigned)(adapterDesc.DedicatedVideoMemory / 1048576));
|
||||
DEBUG_INFO("Device Sys Mem : %u MiB" , (unsigned)(adapterDesc.DedicatedSystemMemory / 1048576));
|
||||
DEBUG_INFO("Shared Sys Mem : %u MiB" , (unsigned)(adapterDesc.SharedSystemMemory / 1048576));
|
||||
|
||||
static const D3D_FEATURE_LEVEL win8[] =
|
||||
{
|
||||
@@ -432,9 +432,9 @@ static bool dxgi_init(void)
|
||||
|
||||
++this->formatVer;
|
||||
|
||||
DEBUG_INFO("Feature Level : 0x%x" , this->featureLevel);
|
||||
DEBUG_INFO("Capture Size : %u x %u", this->width, this->height);
|
||||
DEBUG_INFO("AcquireLock : %s" , this->useAcquireLock ? "enabled" : "disabled");
|
||||
DEBUG_INFO("Feature Level : 0x%x" , this->featureLevel);
|
||||
DEBUG_INFO("Capture Size : %u x %u", this->width, this->height);
|
||||
DEBUG_INFO("AcquireLock : %s" , this->useAcquireLock ? "enabled" : "disabled");
|
||||
|
||||
// try to reduce the latency
|
||||
{
|
||||
@@ -524,7 +524,7 @@ static bool dxgi_init(void)
|
||||
|
||||
DXGI_OUTDUPL_DESC dupDesc;
|
||||
IDXGIOutputDuplication_GetDesc(this->dup, &dupDesc);
|
||||
DEBUG_INFO("Source Format : %s", GetDXGIFormatStr(dupDesc.ModeDesc.Format));
|
||||
DEBUG_INFO("Source Format : %s", GetDXGIFormatStr(dupDesc.ModeDesc.Format));
|
||||
|
||||
uint8_t bpp = 4;
|
||||
switch(dupDesc.ModeDesc.Format)
|
||||
|
||||
@@ -394,8 +394,8 @@ static void updateDamageRects(CaptureFrame * frame)
|
||||
for(unsigned int i = 0; i < ARRAY_LENGTH(ds); ++i)
|
||||
ds[i].use = (bool)this->diffMap[i];
|
||||
|
||||
// reduce the number of reusuting rectangles by filling in holes and merging
|
||||
// iiregular shapes into contiguous rectangles
|
||||
// reduce the number of resulting rectangles by filling in holes and merging
|
||||
// irregular shapes into contiguous rectangles
|
||||
bool resolve;
|
||||
do
|
||||
{
|
||||
@@ -447,8 +447,8 @@ static void updateDamageRects(CaptureFrame * frame)
|
||||
bool ok = true;
|
||||
if (x > 0 && ds[l].id != ds[u].id)
|
||||
{
|
||||
// no need to use dsFind as the search order ensures that the id has
|
||||
// been fully resolved of the block above
|
||||
// no need to use dsFind as the search order ensures that the id of
|
||||
// the block above has been fully resolved
|
||||
for(unsigned int j = ds[ds[u].id].x1; j <= ds[ds[u].id].x2; ++j)
|
||||
if (!ds[y * w + j].use)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user