Compare commits

...

33 Commits

Author SHA1 Message Date
Geoffrey McRae
3df7d30cd5 [client] core: don't try to send LGMP messages if the video is stopped
If the video stream is stopped the LGMP session is not valid, so we
can't send messages to the client.
2021-12-27 09:56:53 +11:00
Jonathan Rubenstein
74444f8eed [docs] Minor semantic spit and polish
Co-authored-by: Guanzhong Chen <quantum2048@gmail.com>
Co-authored-by: Netboy3 <1472804+netboy3@users.noreply.github.com>
2021-12-26 10:02:07 +11:00
Jonathan Rubenstein
6c43650cd3 [doc] spelling fixes 2021-12-26 10:02:07 +11:00
Jonathan Rubenstein
181ee2b4f5 [doc] module: Kernel Module polish 2021-12-26 10:02:07 +11:00
Jonathan Rubenstein
5bef733647 [doc] install: Update command line options 2021-12-26 10:02:07 +11:00
Jonathan Rubenstein
22cef47bc4 [doc] install: Overlay Filter config polish 2021-12-26 10:02:07 +11:00
Jonathan Rubenstein
5b25e20a2e [doc] install: Overlay Mode polish 2021-12-26 10:02:07 +11:00
Jonathan Rubenstein
bb5c7a222c [doc] conf: Whitespace 2021-12-26 10:02:07 +11:00
Jonathan Rubenstein
39ea6b0587 [doc] install: Config file loading polish 2021-12-26 10:02:07 +11:00
Jonathan Rubenstein
ddc6cb5277 [doc] obs: Install polish 2021-12-26 10:02:07 +11:00
Jonathan Rubenstein
b13a79880b [doc] faq: GNOME on Wayland polish 2021-12-26 10:02:07 +11:00
Jonathan Rubenstein
53fdc2e148 [docs] build: Better flow for Wayland tip 2021-12-26 10:02:07 +11:00
Tudor Brindus
9872d2e407 [host] dxgi: fix typo in debug log message 2021-12-26 09:49:03 +11:00
Quantum
3ccf6de868 [all] gitignore: ignore __pycache__ and *.py[co]
This prevents accidental commits of the compiled spellchecker.
2021-12-26 09:46:31 +11:00
Quantum
12461196c3 [host] nvfbc: fix comments in updateDamageRects 2021-12-24 15:30:04 +11:00
Quantum
15ec80e80d [client] input: fix race between window size and guest cursor
g_state.posInfoValid could become valid after the guest reports the
cursor position, in which case we did not show the cursor until another
update occurs.

This commit eliminates the race by performing the update when
g_state.posInfoValid becomes true.
2021-12-24 13:16:52 +11:00
Netboy3
d6eb72331c [doc] module: Bring back older style XML
Older libvirt and QEMU require older style config
so put it back with version instructions.
2021-12-24 10:24:57 +11:00
Quantum
eea0ced627 [client] wayland: handle NULL wl_keyboard on destruction 2021-12-24 10:22:23 +11:00
Quantum
94684324f4 [client] wayland: don't create confines on uncapture without wl_pointer 2021-12-24 10:17:16 +11:00
Quantum
194afa2d75 [client] wayland: create wl_relative_pointer when creating wl_pointer 2021-12-24 10:17:16 +11:00
Quantum
d96b2ef1fb [client] wayland: clean up objects when wl_pointer disappears 2021-12-24 10:17:16 +11:00
Geoffrey McRae
ad40ea4195 [client] x11: don't override the focus state if no EWMH focus support 2021-12-22 11:25:54 +11:00
Geoffrey McRae
65948034dd [client] x11: be more agressive grabbing the pointer 2021-12-21 21:51:43 +11:00
Netboy3
9d47ca4f12 [doc] module: Modify libvirt commandline block to use JSON
Latest versions of QEMU are running out of PCIe mapping
through libvirt as the commandline device is mapping
ivshmem before other root devices.
Use JSON style configuration in the commandline block.
JSON arguments are loaded after all regular ones
and will guarantee to get loaded after all other libvirt mapped
PCIe devices.
2021-12-21 15:38:28 +11:00
Geoffrey McRae
27c7054505 [client] x11: protect against msc overflow with jitRender 2021-12-21 10:47:55 +11:00
Geoffrey McRae
02b59ba8f7 [client] x11: don't use the atomic msc value when we already have it 2021-12-21 10:47:11 +11:00
Quantum
a5727262cd [client] wayland: make cursor change work without wl_pointer 2021-12-16 11:36:39 +11:00
Geoffrey McRae
43545a4e17 [all] cmake: refuse to perform in-source builds 2021-12-15 10:56:27 +11:00
Geoffrey McRae
adbe333414 [client] egl: dmabuf can be used without GL_EXT_buffer_storage support 2021-12-15 06:10:30 +11:00
Geoffrey McRae
5f80ce91e8 [client] x11: fix broken grab retry logic 2021-12-15 01:43:09 +11:00
Geoffrey McRae
b6fa296d5a [client] x11: work around issue with desktop switch on i3
For an unknwon reason when LG is on another desktop (hidden) and the
user switches to that desktop, the first attempt to grab the pointer
results in a GrabFrozen result. This adds some simple retry logic to
attempt again after a short (100ms) delay which seems to resolve the
issue.
2021-12-15 00:23:44 +11:00
Geoffrey McRae
2e170ad06f [client] x11: properly detect WMEH support for focus events 2021-12-15 00:17:33 +11:00
jonpas
a6720db749 [docs] obs: fix installation instructions grammar
regression in bc022c77f4
2021-12-14 21:19:25 +11:00
21 changed files with 395 additions and 159 deletions

2
.gitignore vendored
View File

@@ -8,3 +8,5 @@ module/modules.order
*.o *.o
*.exe *.exe
*/build */build
__pycache__
*.py[co]

View File

@@ -2,6 +2,17 @@ cmake_minimum_required(VERSION 3.0)
project(looking-glass-client C CXX) project(looking-glass-client C CXX)
get_filename_component(PROJECT_TOP "${PROJECT_SOURCE_DIR}/.." ABSOLUTE) 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/") list(APPEND CMAKE_MODULE_PATH "${PROJECT_TOP}/cmake/" "${PROJECT_SOURCE_DIR}/cmake/")
include(CheckSubmodule) include(CheckSubmodule)

View File

@@ -217,5 +217,6 @@ void waylandSetPointer(LG_DSPointer pointer)
wlWm.cursor = wlWm.cursors[pointer]; wlWm.cursor = wlWm.cursors[pointer];
wlWm.cursorHotX = wlWm.cursorHot[pointer].x; wlWm.cursorHotX = wlWm.cursorHot[pointer].x;
wlWm.cursorHotY = wlWm.cursorHot[pointer].y; 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);
} }

View File

@@ -290,20 +290,53 @@ static const struct wl_keyboard_listener keyboardListener = {
.modifiers = keyboardModifiersHandler, .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. // Seat-handling listeners.
static void handlePointerCapability(uint32_t capabilities) static void handlePointerCapability(uint32_t capabilities)
{ {
bool hasPointer = capabilities & WL_SEAT_CAPABILITY_POINTER; bool hasPointer = capabilities & WL_SEAT_CAPABILITY_POINTER;
if (!hasPointer && wlWm.pointer) if (!hasPointer && wlWm.pointer)
{ waylandCleanUpPointer();
wl_pointer_destroy(wlWm.pointer);
wlWm.pointer = NULL;
}
else if (hasPointer && !wlWm.pointer) else if (hasPointer && !wlWm.pointer)
{ {
wlWm.pointer = wl_seat_get_pointer(wlWm.seat); wlWm.pointer = wl_seat_get_pointer(wlWm.seat);
wl_pointer_add_listener(wlWm.pointer, &pointerListener, NULL); 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_seat_add_listener(wlWm.seat, &seatListener, NULL);
wl_display_roundtrip(wlWm.display); 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); LG_LOCK_INIT(wlWm.confineLock);
return true; return true;
@@ -393,8 +417,15 @@ void waylandInputFree(void)
{ {
waylandUngrabPointer(); waylandUngrabPointer();
LG_LOCK_FREE(wlWm.confineLock); 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); wl_seat_destroy(wlWm.seat);
if (wlWm.xkbState) if (wlWm.xkbState)
@@ -508,7 +539,7 @@ void waylandUncapturePointer(void)
*/ */
if (!wlWm.warpSupport || !app_isFormatValid() || app_isCaptureOnlyMode()) if (!wlWm.warpSupport || !app_isFormatValid() || app_isCaptureOnlyMode())
internalUngrabPointer(false); internalUngrabPointer(false);
else else if (wlWm.pointer)
{ {
wlWm.confinedPointer = zwp_pointer_constraints_v1_confine_pointer( wlWm.confinedPointer = zwp_pointer_constraints_v1_confine_pointer(
wlWm.pointerConstraints, wlWm.surface, wlWm.pointer, NULL, wlWm.pointerConstraints, wlWm.surface, wlWm.pointer, NULL,

View File

@@ -95,6 +95,9 @@ static bool waylandInit(const LG_DSInitParams params)
if (!waylandPresentationInit()) if (!waylandPresentationInit())
return false; return false;
if (!waylandCursorInit())
return false;
if (!waylandInputInit()) if (!waylandInputInit())
return false; return false;
@@ -104,9 +107,6 @@ static bool waylandInit(const LG_DSInitParams params)
if (!waylandEGLInit(params.w, params.h)) if (!waylandEGLInit(params.w, params.h))
return false; return false;
if (!waylandCursorInit())
return false;
#ifdef ENABLE_OPENGL #ifdef ENABLE_OPENGL
if (params.opengl && !waylandOpenGLInit()) if (params.opengl && !waylandOpenGLInit())
return false; return false;

View File

@@ -22,11 +22,15 @@
#define _H_X11DS_ATOMS_ #define _H_X11DS_ATOMS_
#define DEF_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_REQUEST_FRAME_EXTENTS, True) \
DEF_ATOM(_NET_FRAME_EXTENTS, True) \ DEF_ATOM(_NET_FRAME_EXTENTS, True) \
DEF_ATOM(_NET_WM_BYPASS_COMPOSITOR, False) \ DEF_ATOM(_NET_WM_BYPASS_COMPOSITOR, False) \
DEF_ATOM(_NET_WM_STATE, True) \ DEF_ATOM(_NET_WM_STATE, True) \
DEF_ATOM(_NET_WM_STATE_FULLSCREEN, 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_HORZ, True) \
DEF_ATOM(_NET_WM_STATE_MAXIMIZED_VERT, True) \ DEF_ATOM(_NET_WM_STATE_MAXIMIZED_VERT, True) \
DEF_ATOM(_NET_WM_WINDOW_TYPE, True) \ DEF_ATOM(_NET_WM_WINDOW_TYPE, True) \

View File

@@ -82,8 +82,9 @@ static void x11SetFullscreen(bool fs);
static int x11EventThread(void * unused); static int x11EventThread(void * unused);
static void x11XInputEvent(XGenericEventCookie *cookie); static void x11XInputEvent(XGenericEventCookie *cookie);
static void x11XPresentEvent(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; static bool startup = true;
if (startup) if (startup)
@@ -113,11 +114,19 @@ static void x11DoPresent(void)
static bool first = true; static bool first = true;
static uint64_t lastMsc = 0; static uint64_t lastMsc = 0;
uint64_t msc = atomic_load(&x11.presentMsc);
uint64_t refill; uint64_t refill;
if (!first) 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 else
{ {
refill = 50; refill = 50;
@@ -167,6 +176,69 @@ static bool x11EarlyInit(void)
return true; 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) static bool x11Init(const LG_DSInitParams params)
{ {
XIDeviceInfo *devinfo; XIDeviceInfo *devinfo;
@@ -272,6 +344,9 @@ static bool x11Init(const LG_DSInitParams params)
X11AtomsInit(); X11AtomsInit();
XSetWMProtocols(x11.display, x11.window, &x11atoms.WM_DELETE_WINDOW, 1); XSetWMProtocols(x11.display, x11.window, &x11atoms.WM_DELETE_WINDOW, 1);
// check for Extended Window Manager Hints support
x11CheckEWMHSupport();
if (params.borderless) if (params.borderless)
{ {
if (x11atoms._MOTIF_WM_HINTS) if (x11atoms._MOTIF_WM_HINTS)
@@ -457,8 +532,12 @@ static bool x11Init(const LG_DSInitParams params)
eventmask.mask_len = sizeof(mask); eventmask.mask_len = sizeof(mask);
eventmask.mask = mask; eventmask.mask = mask;
XISetMask(mask, XI_FocusIn ); if (!x11.ewmhHasFocusEvent)
XISetMask(mask, XI_FocusOut ); {
XISetMask(mask, XI_FocusIn );
XISetMask(mask, XI_FocusOut);
}
XISetMask(mask, XI_Enter ); XISetMask(mask, XI_Enter );
XISetMask(mask, XI_Leave ); XISetMask(mask, XI_Leave );
XISetMask(mask, XI_Motion ); XISetMask(mask, XI_Motion );
@@ -615,7 +694,7 @@ static bool x11Init(const LG_DSInitParams params)
} }
if (x11.jitRender) if (x11.jitRender)
x11DoPresent(); x11DoPresent(0);
return true; return true;
@@ -839,6 +918,7 @@ static int x11EventThread(void * unused)
} }
case PropertyNotify: case PropertyNotify:
// ignore property events that are not for us // ignore property events that are not for us
if (xe.xproperty.display != x11.display || if (xe.xproperty.display != x11.display ||
xe.xproperty.window != x11.window || xe.xproperty.window != x11.window ||
@@ -860,11 +940,20 @@ static int x11EventThread(void * unused)
break; break;
bool fullscreen = false; 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]; Atom prop = ((Atom *)data)[i];
if (prop == x11atoms._NET_WM_STATE_FULLSCREEN) if (prop == x11atoms._NET_WM_STATE_FULLSCREEN)
fullscreen = true; 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; x11.fullscreen = fullscreen;
@@ -941,6 +1030,9 @@ static void x11XInputEvent(XGenericEventCookie *cookie)
{ {
case XI_FocusIn: case XI_FocusIn:
{ {
if (x11.ewmhHasFocusEvent)
return;
atomic_store(&x11.lastWMEvent, microtime()); atomic_store(&x11.lastWMEvent, microtime());
if (x11.focused) if (x11.focused)
return; return;
@@ -959,6 +1051,9 @@ static void x11XInputEvent(XGenericEventCookie *cookie)
case XI_FocusOut: case XI_FocusOut:
{ {
if (x11.ewmhHasFocusEvent)
return;
atomic_store(&x11.lastWMEvent, microtime()); atomic_store(&x11.lastWMEvent, microtime());
if (!x11.focused) if (!x11.focused)
return; return;
@@ -1251,10 +1346,10 @@ static void x11XPresentEvent(XGenericEventCookie *cookie)
case PresentCompleteNotify: case PresentCompleteNotify:
{ {
XPresentCompleteNotifyEvent * e = cookie->data; XPresentCompleteNotifyEvent * e = cookie->data;
x11DoPresent(e->msc);
atomic_store(&x11.presentMsc, e->msc); atomic_store(&x11.presentMsc, e->msc);
atomic_store(&x11.presentUst, e->ust); atomic_store(&x11.presentUst, e->ust);
lgSignalEvent(x11.frameEvent); lgSignalEvent(x11.frameEvent);
x11DoPresent();
break; break;
} }
} }
@@ -1556,7 +1651,10 @@ static void x11GrabPointer(void)
XISetMask(mask.mask, XI_Enter ); XISetMask(mask.mask, XI_Enter );
XISetMask(mask.mask, XI_Leave ); XISetMask(mask.mask, XI_Leave );
Status ret = XIGrabDevice( Status ret;
for(int retry = 0; retry < 10; ++retry)
{
ret = XIGrabDevice(
x11.display, x11.display,
x11.pointerDev, x11.pointerDev,
x11.window, x11.window,
@@ -1567,6 +1665,18 @@ static void x11GrabPointer(void)
XINoOwnerEvents, XINoOwnerEvents,
&mask); &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) if (ret != Success)
{ {
x11PrintGrabError("pointer", x11.pointerDev, ret); x11PrintGrabError("pointer", x11.pointerDev, ret);

View File

@@ -54,6 +54,11 @@ struct X11DSState
Window window; Window window;
XVisualInfo * visual; XVisualInfo * visual;
//Extended Window Manager Hints
//ref: https://specifications.freedesktop.org/wm-spec/latest/
bool ewmhSupport;
bool ewmhHasFocusEvent;
_Atomic(uint64_t) lastWMEvent; _Atomic(uint64_t) lastWMEvent;
bool invalidateAll; bool invalidateAll;

View File

@@ -326,6 +326,13 @@ bool egl_desktopUpdate(EGL_Desktop * desktop, const FrameBuffer * frame, int dma
desktop->useDMA = false; 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); egl_textureFree(&desktop->texture);
if (!egl_textureInit(&desktop->texture, desktop->display, if (!egl_textureInit(&desktop->texture, desktop->display,
EGL_TEXTYPE_FRAMEBUFFER, true)) EGL_TEXTYPE_FRAMEBUFFER, true))

View File

@@ -798,12 +798,6 @@ static bool egl_renderStartup(LG_Renderer * renderer, bool useDMA)
glGetIntegerv(GL_MAJOR_VERSION, &esMaj); glGetIntegerv(GL_MAJOR_VERSION, &esMaj);
glGetIntegerv(GL_MINOR_VERSION, &esMin); 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")) if (!util_hasGLExt(gl_exts, "GL_EXT_texture_format_BGRA8888"))
{ {
DEBUG_ERROR("GL_EXT_texture_format_BGRA8888 is needed to use EGL backend"); 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; this->dmaSupport = true;
if (!this->dmaSupport) if (!this->dmaSupport)
{
useDMA = false; 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) if (debugContext)
{ {

View File

@@ -268,6 +268,19 @@ void core_updatePositionInfo(void)
{ {
g_state.posInfoValid = true; g_state.posInfoValid = true;
g_state.ds->realignPointer(); 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: done:
@@ -435,7 +448,8 @@ void core_handleMouseNormal(double ex, double ey)
struct DoublePoint guest; struct DoublePoint guest;
util_localCurToGuest(&guest); util_localCurToGuest(&guest);
if (g_state.kvmfrFeatures & KVMFR_FEATURE_SETCURSORPOS) if (!g_state.stopVideo &&
g_state.kvmfrFeatures & KVMFR_FEATURE_SETCURSORPOS)
{ {
const KVMFRSetCursorPos msg = { const KVMFRSetCursorPos msg = {
.msg.type = KVMFR_MESSAGE_SETCURSORPOS, .msg.type = KVMFR_MESSAGE_SETCURSORPOS,

View File

@@ -140,7 +140,7 @@ frames from the guest.
.. note:: .. 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 ../``. ``-DENABLE_LIBDECOR=ON`` to ``cmake``, i.e. run ``cmake -DENABLE_LIBDECOR=ON ../``.
For details, see :ref:`the FAQ <gnome_wayland_decorations>`. For details, see :ref:`the FAQ <gnome_wayland_decorations>`.

View File

@@ -71,8 +71,8 @@ master_doc = 'index'
html_theme = 'alabaster' html_theme = 'alabaster'
html_theme_options = { html_theme_options = {
'logo': 'icon-128x128.png', 'logo': 'icon-128x128.png',
'fixed_sidebar': 'true', 'fixed_sidebar': 'true',
} }
html_sidebars = { html_sidebars = {

View File

@@ -79,26 +79,29 @@ well.
.. _gnome_wayland_decorations: .. _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 This happens because GNOME on Wayland doesn't support the `standard protocol`_
protocol`_ for server-side decorations. As a result, the window decorations for server-side decorations, and Looking Glass doesn't implement its own
do not appear. decorations.
The easy solution is to use `libdecor`_. This is currently not packaged in The easiest solution is to build Looking Glass with `libdecor`_ support.
most distros, so you will need to build it from the linked git repository. 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 You can then build the the client with libdecor support by passing
support by passing ``-DENABLE_LIBDECOR=ON`` to ``cmake``. ``-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.
An alternative solution is to hold down the Super key (Windows key on most 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. 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 .. _standard protocol: https://wayland.app/protocols/xdg-decoration-unstable-v1
.. _libdecor: https://gitlab.gnome.org/jadahl/libdecor .. _libdecor: https://gitlab.gnome.org/jadahl/libdecor

View File

@@ -289,21 +289,23 @@ Examples:
Configuration Files Configuration Files
~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~
By default, the application will look for and load the config files in By default, Looking Glass will load config files from
the following locations and order: the following locations:
- /etc/looking-glass-client.ini - /etc/looking-glass-client.ini
- ~/.looking-glass-client.ini - ~/.looking-glass-client.ini
- $XDG_CONFIG_HOME/looking-glass/client.ini (usually ~/.config/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 All config files are loaded in order. Duplicate entries override earlier ones.
than one file will be overridden by the latest loaded one (E.g. an option This means you can set a system-wide configuration in
appearing in ~/.config/looking-glass/client.ini will override the same ``/etc/looking-glass-client.ini``, and override specific options for just
option appearing in ~/.looking-glass-client.ini). When first launched, your user in ``~/.looking-glass-client.ini``, which is overlayed on top of
the Looking-Glass client will create the folder $XDG_CONFIG_HOME/looking-glass/ the system-wide configuration.
if it does not yet exist.
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] [win]
fullScreen=yes fullScreen=yes
@@ -311,7 +313,7 @@ The format of this file is the commonly known INI format, for example::
[egl] [egl]
nvGain=1 nvGain=1
Command line arguments will override any options loaded from the config Command line arguments will override any options loaded from config
files. files.
.. _client_overlay_mode: .. _client_overlay_mode:
@@ -319,82 +321,77 @@ files.
Overlay Mode Overlay Mode
~~~~~~~~~~~~ ~~~~~~~~~~~~
Looking-Glass is utilizing an overlay layer to draw various widgets (such The Overlay Mode lets you configure various runtime options for Looking Glass.
as the FPS display). An "Overlay Mode" can be toggled (see These include:
:ref:`client_key_bindings`) that allows editing and modifying widgets
properties, such as their position and size. To use the Overlay Mode:
- Enable one or more widgets (such as the FPS display) - EGL filters
- Enter Overlay Mode by using its keybinding (the screen will turn - Performance metrics options
darker to indicate Overlay Mode is active) - Debug frame damage display
- 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
Modifications done in Overlay Mode are persistent and are stored (see :ref:`client_config_widget`)
in a special config file $XDG_CONFIG_HOME/looking-glass/imgui.ini.
Please refrain from editing this file manually as your changes might You can also reposition and resize enabled widgets, like the FPS/UPS Display,
be overwritten by the client. 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: .. _client_config_widget:
Configuration 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 widget has multiple tabs that allow setting a variety of modes and
parameters for the application. parameters for Looking Glass at runtime.
Settings tab Settings tab
^^^^^^^^^^^^ ^^^^^^^^^^^^
- Performance Metrics: Enabling this will turn on the Metrics Graphs - Performance Metrics: A toggle for the Performance Metrics Widget.
Widget. Multiple graphs can be enabled and they will stack vertically. Multiple graphs are available, and they will stack vertically.
- EGL: Modify EGL features such as the algorithm used for scaling and - EGL: Modify EGL features, such as the algorithm used for scaling, and
enabling night vision mode. 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. their default values when the client is restarted.
EGL Filters tab EGL Filters tab
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
The EGL Filters tab is a GUI for enabling, configuring and ordering The EGL Filters tab contains options for toggling, configuring, and ordering
the post-processing filter stack. Each filter can be expanded to open post-processing filters. Each filter can be expanded to open its settings.
its settings. Filters can also be re-ordered by dragging them up or down. Filters can also be re-ordered by dragging them up or down. Filters are applied
Filters application is cumulative, and order is important (e.g. applying CAS 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 before FSR might have different results than the reverse. Users are encouraged
encouraged to experiment with the order and parameters to achieve optimal to experiment with the order and parameters to achieve optimal results. The
results. The currently available filters include: currently available filters include:
- Downscaler: Filter for downscaling resolution. Can be used to undo the - Downscaler: Filter for downscaling the host resolution. Can be used to undo
poor upscaling that some games implement such that it can then poor upscaling on the VM to better utilize AMD FSR (see below). The filter
be better upscaled using FSR (see below). The filter has a pixel-size setting has a pixel-size setting that is used to set the effective downscaling ratio,
that is used to set the effective downscaling ratio and can be set to use and a configurable interpolation algorithm.
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.
The filter stack settings and order can be saved to presets so that it - AMD FidelityFX Super Resolution (FSR): Spatial upscaling filter that works
can be conveniently recalled at a later time. As filter settings are on low resolution frames from the guest VM and intelligently upscales to a
usually application specific, multiple presets can be defined for each higher resolution. The filter sharpness is tunable, and displays the
case scenario. To save a preset, click on "Save preset as..." and enter equivalent AMD quality mode based on the resolution difference.
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 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``. ``$XDG_CONFIG_HOME/looking-glass/presets``.
.. warning:: .. warning::
@@ -413,23 +410,23 @@ Full Command Line Options
The following is a complete list of options accepted by this application The following is a complete list of options accepted by this application
+------------------------+-------+------------------------+------------------------------------------------------------------------------------------+ +------------------------+-------+------------------------+-----------------------------------------------------------------------------------------+
| Long | Short | Value | Description | | Long | Short | Value | Description |
+========================+=======+========================+==========================================================================================+ +========================+=======+========================+=========================================================================================+
| app:configFile | -C | NULL | A file to read additional configuration from | | app:configFile | -C | NULL | A file to read additional configuration from |
+------------------------+-------+------------------------+------------------------------------------------------------------------------------------+ +------------------------+-------+------------------------+-----------------------------------------------------------------------------------------+
| app:renderer | -g | auto | Specify the renderer to use | | app:renderer | -g | auto | Specify the renderer to use |
+------------------------+-------+------------------------+------------------------------------------------------------------------------------------+ +------------------------+-------+------------------------+-----------------------------------------------------------------------------------------+
| app:license | -l | no | Show the license for this application and then terminate | | 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: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: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: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 | | 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 | | 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: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 | | 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: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 | | Long | Short | Value | Description |

View File

@@ -166,7 +166,30 @@ Add the following arguments to your ``qemu`` command line::
libvirt 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 .. code:: xml
@@ -179,8 +202,12 @@ Create the following XML block in your domain:
.. note:: .. note::
Remember to add ``xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'`` - Using the legacy syntax on QEMU 6.2/libvirt 7.9 may cause QEMU to
to the ``<domain>`` tag. 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 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 block the VM from running. These policies must be amended to allow the VM

View File

@@ -47,7 +47,7 @@ These instructions are similar to building the
cmake -DUSER_INSTALL=1 ../ cmake -DUSER_INSTALL=1 ../
make 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 .. code:: bash
@@ -59,15 +59,19 @@ Alternatively if you would like to install the plugin for all users.
Installation Installation
~~~~~~~~~~~~ ~~~~~~~~~~~~
You can install the plugin for by running ``make install``. You can install the plugin by running ``make install``.
.. code:: bash .. code:: bash
make install 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``. this command as ``root``.
.. code:: bash
sudo make install
Setup Setup
~~~~~ ~~~~~

View File

@@ -29,6 +29,7 @@ modprobe
msys msys
multisampling multisampling
Nvidia Nvidia
overlayed
pacman pacman
passthrough passthrough
pre pre
@@ -38,11 +39,13 @@ radeon
realtime realtime
renderer renderer
repo repo
runtime
submodule submodule
submodules submodules
systemd systemd
toolchain toolchain
tritanope tritanope
tunable
udev udev
UEFI UEFI
uncheck uncheck
@@ -51,6 +54,7 @@ Unigine
unix unix
upscaled upscaled
upscaler upscaler
upscales
upscaling upscaling
VM VM
vsync vsync

View File

@@ -1,12 +1,23 @@
cmake_minimum_required(VERSION 3.0) cmake_minimum_required(VERSION 3.0)
project(looking-glass-host C) 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_C_FLAGS_RELWITHDEBINFO "-O3 -g -DNDEBUG" CACHE STRING "compiler flags" FORCE)
set(CMAKE_CXX_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(CheckSubmodule)
include(GNUInstallDirs) include(GNUInstallDirs)
include(CheckCCompilerFlag) include(CheckCCompilerFlag)

View File

@@ -319,13 +319,13 @@ static bool dxgi_init(void)
DXGI_ADAPTER_DESC1 adapterDesc; DXGI_ADAPTER_DESC1 adapterDesc;
IDXGIAdapter1_GetDesc1(this->adapter, &adapterDesc); IDXGIAdapter1_GetDesc1(this->adapter, &adapterDesc);
DEBUG_INFO("Device Name : %ls" , outputDesc.DeviceName); DEBUG_INFO("Device Name : %ls" , outputDesc.DeviceName);
DEBUG_INFO("Device Descripion: %ls" , adapterDesc.Description); DEBUG_INFO("Device Description: %ls" , adapterDesc.Description);
DEBUG_INFO("Device Vendor ID : 0x%x" , adapterDesc.VendorId); DEBUG_INFO("Device Vendor ID : 0x%x" , adapterDesc.VendorId);
DEBUG_INFO("Device Device ID : 0x%x" , adapterDesc.DeviceId); DEBUG_INFO("Device Device ID : 0x%x" , adapterDesc.DeviceId);
DEBUG_INFO("Device Video Mem : %u MiB" , (unsigned)(adapterDesc.DedicatedVideoMemory / 1048576)); DEBUG_INFO("Device Video Mem : %u MiB" , (unsigned)(adapterDesc.DedicatedVideoMemory / 1048576));
DEBUG_INFO("Device Sys Mem : %u MiB" , (unsigned)(adapterDesc.DedicatedSystemMemory / 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("Shared Sys Mem : %u MiB" , (unsigned)(adapterDesc.SharedSystemMemory / 1048576));
static const D3D_FEATURE_LEVEL win8[] = static const D3D_FEATURE_LEVEL win8[] =
{ {
@@ -432,9 +432,9 @@ static bool dxgi_init(void)
++this->formatVer; ++this->formatVer;
DEBUG_INFO("Feature Level : 0x%x" , this->featureLevel); DEBUG_INFO("Feature Level : 0x%x" , this->featureLevel);
DEBUG_INFO("Capture Size : %u x %u", this->width, this->height); DEBUG_INFO("Capture Size : %u x %u", this->width, this->height);
DEBUG_INFO("AcquireLock : %s" , this->useAcquireLock ? "enabled" : "disabled"); DEBUG_INFO("AcquireLock : %s" , this->useAcquireLock ? "enabled" : "disabled");
// try to reduce the latency // try to reduce the latency
{ {
@@ -524,7 +524,7 @@ static bool dxgi_init(void)
DXGI_OUTDUPL_DESC dupDesc; DXGI_OUTDUPL_DESC dupDesc;
IDXGIOutputDuplication_GetDesc(this->dup, &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; uint8_t bpp = 4;
switch(dupDesc.ModeDesc.Format) switch(dupDesc.ModeDesc.Format)

View File

@@ -394,8 +394,8 @@ static void updateDamageRects(CaptureFrame * frame)
for(unsigned int i = 0; i < ARRAY_LENGTH(ds); ++i) for(unsigned int i = 0; i < ARRAY_LENGTH(ds); ++i)
ds[i].use = (bool)this->diffMap[i]; ds[i].use = (bool)this->diffMap[i];
// reduce the number of reusuting rectangles by filling in holes and merging // reduce the number of resulting rectangles by filling in holes and merging
// iiregular shapes into contiguous rectangles // irregular shapes into contiguous rectangles
bool resolve; bool resolve;
do do
{ {
@@ -447,8 +447,8 @@ static void updateDamageRects(CaptureFrame * frame)
bool ok = true; bool ok = true;
if (x > 0 && ds[l].id != ds[u].id) if (x > 0 && ds[l].id != ds[u].id)
{ {
// no need to use dsFind as the search order ensures that the id has // no need to use dsFind as the search order ensures that the id of
// been fully resolved of the block above // the block above has been fully resolved
for(unsigned int j = ds[ds[u].id].x1; j <= ds[ds[u].id].x2; ++j) for(unsigned int j = ds[ds[u].id].x1; j <= ds[ds[u].id].x2; ++j)
if (!ds[y * w + j].use) if (!ds[y * w + j].use)
{ {