mirror of
https://github.com/gnif/LookingGlass.git
synced 2025-12-20 03:30:22 +00:00
Compare commits
43 Commits
B3-rc1
...
Release/B3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2973319bff | ||
|
|
ec921d7f39 | ||
|
|
637a7625d2 | ||
|
|
32d8a47cd9 | ||
|
|
b4787fcfd1 | ||
|
|
e6ebcec689 | ||
|
|
ff0a859ceb | ||
|
|
1b48ac842a | ||
|
|
a702c912ae | ||
|
|
acc3298344 | ||
|
|
25e74301be | ||
|
|
327d472d64 | ||
|
|
e951aaad2d | ||
|
|
bbfe5aea37 | ||
|
|
0d28ea160e | ||
|
|
4fbaf18c89 | ||
|
|
c91b7f647d | ||
|
|
1761ea2b9b | ||
|
|
fb916cbac1 | ||
|
|
b97130cf20 | ||
|
|
05f2305fa0 | ||
|
|
b76fedeb67 | ||
|
|
6b5842d2ff | ||
|
|
7e15ec5e66 | ||
|
|
1808adc2de | ||
|
|
e2e49bce13 | ||
|
|
0d7be70b56 | ||
|
|
6b0699e664 | ||
|
|
9e96156912 | ||
|
|
837858c214 | ||
|
|
3783a25211 | ||
|
|
941c651fad | ||
|
|
f9ec32b255 | ||
|
|
8caf951c41 | ||
|
|
ef54e1be7f | ||
|
|
4c1893fe20 | ||
|
|
086f73721d | ||
|
|
202739c5be | ||
|
|
88b15cb3fe | ||
|
|
6990d7f7e3 | ||
|
|
9941a4bb83 | ||
|
|
d610aaf2cf | ||
|
|
908aa84599 |
13
.github/issue_template.md
vendored
13
.github/issue_template.md
vendored
@@ -5,8 +5,8 @@ If you are looking for help or support please use one of the following methods
|
|||||||
Create a New Topic on the Level1Tech's forum under the Looking Glass category:
|
Create a New Topic on the Level1Tech's forum under the Looking Glass category:
|
||||||
* https://forum.level1techs.com/c/software/lookingGlass/142
|
* https://forum.level1techs.com/c/software/lookingGlass/142
|
||||||
|
|
||||||
Ask for help in #looking-glass in the VFIO discord server
|
Ask for help in the Looking Glass discord server
|
||||||
* https://discord.gg/4ahCn4c
|
* https://discord.gg/52SMupxkvt
|
||||||
|
|
||||||
*Issues that are not bug reports or feature requests will be closed & ignored*
|
*Issues that are not bug reports or feature requests will be closed & ignored*
|
||||||
|
|
||||||
@@ -40,12 +40,9 @@ PASTE CLIENT OUTPUT HERE
|
|||||||
```
|
```
|
||||||
|
|
||||||
The entire (not truncated) log file from the host application (if applicable).
|
The entire (not truncated) log file from the host application (if applicable).
|
||||||
To obtain this locate the log file on your system, it will be in one of the
|
Normally, this is found on the guest system at:
|
||||||
following two locations depending on how you are launching the Looking Glass Host
|
|
||||||
application:
|
|
||||||
|
|
||||||
* C:\Windows\Temp\looking-glass.txt
|
%ProgramData%\Looking Glass (host)\looking-glass-host.txt
|
||||||
* C:\Users\YOUR_USER\AppData\Local\Temp\looking-glass.txt
|
|
||||||
|
|
||||||
This log may be quite long, please delete the file first and then proceed to
|
This log may be quite long, please delete the file first and then proceed to
|
||||||
launch the host and reproduce the issue so that the log only contains the
|
launch the host and reproduce the issue so that the log only contains the
|
||||||
@@ -56,7 +53,7 @@ pertinent information.
|
|||||||
PASTE HOST LOG FILE CONTENTS HERE
|
PASTE HOST LOG FILE CONTENTS HERE
|
||||||
```
|
```
|
||||||
|
|
||||||
If the client is unexpetedly exiting without a backtrace, please provide one via
|
If the client is unexpectedly exiting without a backtrace, please provide one via
|
||||||
gdb with the command `thread apply all bt`. If you are unsure how to do this
|
gdb with the command `thread apply all bt`. If you are unsure how to do this
|
||||||
please watch the video below on how to perform a Debug build and generate this
|
please watch the video below on how to perform a Debug build and generate this
|
||||||
backtrace.
|
backtrace.
|
||||||
|
|||||||
@@ -51,11 +51,12 @@ https://looking-glass.io/downloads
|
|||||||
|
|
||||||
## Web
|
## Web
|
||||||
|
|
||||||
https://forum.level1techs.com/t/looking-glass-triage/130952
|
https://forum.level1techs.com/c/software/lookingglass/142
|
||||||
|
|
||||||
## Discord
|
## Discord
|
||||||
|
|
||||||
https://discord.gg/4ahCn4c
|
* Looking Glass: https://discord.gg/52SMupxkvt
|
||||||
|
* VFIO: https://discord.gg/4ahCn4c
|
||||||
|
|
||||||
## IRC
|
## IRC
|
||||||
|
|
||||||
|
|||||||
@@ -391,9 +391,18 @@ static void relativePointerMotionHandler(void * data,
|
|||||||
wl_fixed_t dxW, wl_fixed_t dyW, wl_fixed_t dxUnaccelW,
|
wl_fixed_t dxW, wl_fixed_t dyW, wl_fixed_t dxUnaccelW,
|
||||||
wl_fixed_t dyUnaccelW)
|
wl_fixed_t dyUnaccelW)
|
||||||
{
|
{
|
||||||
double dxUnaccel = wl_fixed_to_double(dxUnaccelW);
|
double dx, dy;
|
||||||
double dyUnaccel = wl_fixed_to_double(dyUnaccelW);
|
if (app_cursorWantsRaw())
|
||||||
app_handleMouseGrabbed(dxUnaccel, dyUnaccel);
|
{
|
||||||
|
dx = wl_fixed_to_double(dxUnaccelW);
|
||||||
|
dy = wl_fixed_to_double(dyUnaccelW);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dx = wl_fixed_to_double(dxW);
|
||||||
|
dy = wl_fixed_to_double(dyW);
|
||||||
|
}
|
||||||
|
app_handleMouseGrabbed(dx, dy);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct zwp_relative_pointer_v1_listener relativePointerListener = {
|
static const struct zwp_relative_pointer_v1_listener relativePointerListener = {
|
||||||
@@ -635,11 +644,12 @@ static void dataOfferHandleOffer(void * data, struct wl_data_offer * offer,
|
|||||||
const char * mimetype)
|
const char * mimetype)
|
||||||
{
|
{
|
||||||
enum LG_ClipboardData type = mimetypeToCbType(mimetype);
|
enum LG_ClipboardData type = mimetypeToCbType(mimetype);
|
||||||
// Oftentimes we'll get text/html alongside text/png, but would prefer to send
|
// We almost never prefer text/html, as that's used to represent rich text.
|
||||||
// image/png. In general, prefer images over text content.
|
// Since we can't copy or paste rich text, we should instead prefer actual
|
||||||
|
// images or plain text.
|
||||||
if (type != LG_CLIPBOARD_DATA_NONE &&
|
if (type != LG_CLIPBOARD_DATA_NONE &&
|
||||||
(wcb.stashedType == LG_CLIPBOARD_DATA_NONE ||
|
(wcb.stashedType == LG_CLIPBOARD_DATA_NONE ||
|
||||||
wcb.stashedType == LG_CLIPBOARD_DATA_TEXT))
|
strstr(wcb.stashedMimetype, "html")))
|
||||||
{
|
{
|
||||||
wcb.stashedType = type;
|
wcb.stashedType = type;
|
||||||
if (wcb.stashedMimetype)
|
if (wcb.stashedMimetype)
|
||||||
|
|||||||
@@ -261,6 +261,7 @@ static bool x11GetProp(LG_DSProperty prop, void *ret)
|
|||||||
maxSamples = samples;
|
maxSamples = samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XFree(visuals);
|
||||||
XCloseDisplay(dpy);
|
XCloseDisplay(dpy);
|
||||||
|
|
||||||
*(int*)ret = maxSamples;
|
*(int*)ret = maxSamples;
|
||||||
@@ -336,12 +337,14 @@ static bool x11EventFilter(SDL_Event * event)
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
XIFocusOutEvent *xie = cookie->data;
|
XIFocusOutEvent *xie = cookie->data;
|
||||||
if (xie->mode != NotifyNormal && xie->mode != XINotifyWhileGrabbed)
|
if (xie->mode != XINotifyNormal &&
|
||||||
|
xie->mode != XINotifyWhileGrabbed &&
|
||||||
|
xie->mode != XINotifyUngrab)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
x11.focused = true;
|
||||||
app_updateCursorPos(xie->event_x, xie->event_y);
|
app_updateCursorPos(xie->event_x, xie->event_y);
|
||||||
app_handleFocusEvent(true);
|
app_handleFocusEvent(true);
|
||||||
x11.focused = true;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -351,7 +354,9 @@ static bool x11EventFilter(SDL_Event * event)
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
XIFocusOutEvent *xie = cookie->data;
|
XIFocusOutEvent *xie = cookie->data;
|
||||||
if (xie->mode != NotifyNormal && xie->mode != XINotifyWhileGrabbed)
|
if (xie->mode != XINotifyNormal &&
|
||||||
|
xie->mode != XINotifyWhileGrabbed &&
|
||||||
|
xie->mode != XINotifyGrab)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
app_updateCursorPos(xie->event_x, xie->event_y);
|
app_updateCursorPos(xie->event_x, xie->event_y);
|
||||||
@@ -470,6 +475,9 @@ static bool x11EventFilter(SDL_Event * event)
|
|||||||
{
|
{
|
||||||
XIDeviceEvent *device = cookie->data;
|
XIDeviceEvent *device = cookie->data;
|
||||||
app_updateCursorPos(device->event_x, device->event_y);
|
app_updateCursorPos(device->event_x, device->event_y);
|
||||||
|
|
||||||
|
if (!x11.pointerGrabbed)
|
||||||
|
app_handleMouseNormal(0.0, 0.0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -571,6 +579,25 @@ static bool x11EventFilter(SDL_Event * event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void x11PrintGrabError(const char * type, int dev, Status ret)
|
||||||
|
{
|
||||||
|
const char * errStr;
|
||||||
|
switch(ret)
|
||||||
|
{
|
||||||
|
case AlreadyGrabbed : errStr = "AlreadyGrabbed" ; break;
|
||||||
|
case GrabNotViewable: errStr = "GrabNotViewable"; break;
|
||||||
|
case GrabFrozen : errStr = "GrabFrozen" ; break;
|
||||||
|
case GrabInvalidTime: errStr = "GrabInvalidTime"; break;
|
||||||
|
default:
|
||||||
|
errStr = "Unknown";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_ERROR("XIGrabDevice failed for %s dev %d with 0x%x (%s)",
|
||||||
|
type, dev, ret, errStr);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static void x11GrabPointer(void)
|
static void x11GrabPointer(void)
|
||||||
{
|
{
|
||||||
if (x11.pointerGrabbed)
|
if (x11.pointerGrabbed)
|
||||||
@@ -588,18 +615,22 @@ static void x11GrabPointer(void)
|
|||||||
XISetMask(mask.mask, XI_RawMotion );
|
XISetMask(mask.mask, XI_RawMotion );
|
||||||
XISetMask(mask.mask, XI_Motion );
|
XISetMask(mask.mask, XI_Motion );
|
||||||
|
|
||||||
XIGrabDevice(
|
Status ret = XIGrabDevice(
|
||||||
x11.display,
|
x11.display,
|
||||||
x11.pointerDev,
|
x11.pointerDev,
|
||||||
x11.window,
|
x11.window,
|
||||||
CurrentTime,
|
CurrentTime,
|
||||||
None,
|
None,
|
||||||
GrabModeAsync,
|
XIGrabModeAsync,
|
||||||
GrabModeAsync,
|
XIGrabModeAsync,
|
||||||
false,
|
XINoOwnerEvents,
|
||||||
&mask);
|
&mask);
|
||||||
|
|
||||||
XSync(x11.display, False);
|
if (ret != Success)
|
||||||
|
{
|
||||||
|
x11PrintGrabError("pointer", x11.pointerDev, ret);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
x11.pointerGrabbed = true;
|
x11.pointerGrabbed = true;
|
||||||
}
|
}
|
||||||
@@ -630,18 +661,22 @@ static void x11GrabKeyboard(void)
|
|||||||
XISetMask(mask.mask, XI_RawKeyPress );
|
XISetMask(mask.mask, XI_RawKeyPress );
|
||||||
XISetMask(mask.mask, XI_RawKeyRelease);
|
XISetMask(mask.mask, XI_RawKeyRelease);
|
||||||
|
|
||||||
XIGrabDevice(
|
Status ret = XIGrabDevice(
|
||||||
x11.display,
|
x11.display,
|
||||||
x11.keyboardDev,
|
x11.keyboardDev,
|
||||||
x11.window,
|
x11.window,
|
||||||
CurrentTime,
|
CurrentTime,
|
||||||
None,
|
None,
|
||||||
GrabModeAsync,
|
XIGrabModeAsync,
|
||||||
GrabModeAsync,
|
XIGrabModeAsync,
|
||||||
false,
|
XINoOwnerEvents,
|
||||||
&mask);
|
&mask);
|
||||||
|
|
||||||
XSync(x11.display, False);
|
if (ret != Success)
|
||||||
|
{
|
||||||
|
x11PrintGrabError("keyboard", x11.keyboardDev, ret);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
x11.keyboardGrabbed = true;
|
x11.keyboardGrabbed = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,19 +36,21 @@ struct Inst
|
|||||||
|
|
||||||
static bool lgf_sdl_create(LG_FontObj * opaque, const char * font_name, unsigned int size)
|
static bool lgf_sdl_create(LG_FontObj * opaque, const char * font_name, unsigned int size)
|
||||||
{
|
{
|
||||||
if (g_initCount++ == 0)
|
bool ret = false;
|
||||||
|
|
||||||
|
if (g_initCount == 0)
|
||||||
{
|
{
|
||||||
if (TTF_Init() < 0)
|
if (TTF_Init() < 0)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("TTF_Init Failed");
|
DEBUG_ERROR("TTF_Init Failed");
|
||||||
return false;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_fontConfig = FcInitLoadConfigAndFonts();
|
g_fontConfig = FcInitLoadConfigAndFonts();
|
||||||
if (!g_fontConfig)
|
if (!g_fontConfig)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("FcInitLoadConfigAndFonts Failed");
|
DEBUG_ERROR("FcInitLoadConfigAndFonts Failed");
|
||||||
return false;
|
goto fail_init;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,50 +58,95 @@ static bool lgf_sdl_create(LG_FontObj * opaque, const char * font_name, unsigned
|
|||||||
if (!*opaque)
|
if (!*opaque)
|
||||||
{
|
{
|
||||||
DEBUG_INFO("Failed to allocate %lu bytes", sizeof(struct Inst));
|
DEBUG_INFO("Failed to allocate %lu bytes", sizeof(struct Inst));
|
||||||
return false;
|
goto fail_config;
|
||||||
}
|
}
|
||||||
memset(*opaque, 0, sizeof(struct Inst));
|
|
||||||
|
|
||||||
|
memset(*opaque, 0, sizeof(struct Inst));
|
||||||
struct Inst * this = (struct Inst *)*opaque;
|
struct Inst * this = (struct Inst *)*opaque;
|
||||||
|
|
||||||
if (!font_name)
|
if (!font_name)
|
||||||
font_name = "FreeMono";
|
font_name = "FreeMono";
|
||||||
|
|
||||||
FcPattern * pat = FcNameParse((const FcChar8*)font_name);
|
FcPattern * pat = FcNameParse((const FcChar8*)font_name);
|
||||||
FcConfigSubstitute (g_fontConfig, pat, FcMatchPattern);
|
if (!pat)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("FCNameParse failed");
|
||||||
|
goto fail_opaque;
|
||||||
|
}
|
||||||
|
|
||||||
|
FcConfigSubstitute(g_fontConfig, pat, FcMatchPattern);
|
||||||
FcDefaultSubstitute(pat);
|
FcDefaultSubstitute(pat);
|
||||||
FcResult result;
|
FcResult result;
|
||||||
FcChar8 * file = NULL;
|
FcChar8 * file = NULL;
|
||||||
FcPattern * font = FcFontMatch(g_fontConfig, pat, &result);
|
FcPattern * match = FcFontMatch(g_fontConfig, pat, &result);
|
||||||
|
|
||||||
if (font && (FcPatternGetString(font, FC_FILE, 0, &file) == FcResultMatch))
|
if (!match)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("FcFontMatch Failed");
|
||||||
|
goto fail_parse;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FcPatternGetString(match, FC_FILE, 0, &file) == FcResultMatch)
|
||||||
{
|
{
|
||||||
this->font = TTF_OpenFont((char *)file, size);
|
this->font = TTF_OpenFont((char *)file, size);
|
||||||
if (!this->font)
|
if (!this->font)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("TTL_OpenFont Failed");
|
DEBUG_ERROR("TTL_OpenFont Failed");
|
||||||
return false;
|
goto fail_match;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to locate the requested font: %s", font_name);
|
DEBUG_ERROR("Failed to locate the requested font: %s", font_name);
|
||||||
return false;
|
goto fail_match;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
++g_initCount;
|
||||||
|
ret = true;
|
||||||
|
|
||||||
|
fail_match:
|
||||||
|
FcPatternDestroy(match);
|
||||||
|
|
||||||
|
fail_parse:
|
||||||
FcPatternDestroy(pat);
|
FcPatternDestroy(pat);
|
||||||
|
|
||||||
return true;
|
if (ret)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
fail_opaque:
|
||||||
|
free(this);
|
||||||
|
*opaque = NULL;
|
||||||
|
|
||||||
|
fail_config:
|
||||||
|
if (g_initCount == 0)
|
||||||
|
{
|
||||||
|
FcConfigDestroy(g_fontConfig);
|
||||||
|
g_fontConfig = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fail_init:
|
||||||
|
if (g_initCount == 0)
|
||||||
|
TTF_Quit();
|
||||||
|
|
||||||
|
fail:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lgf_sdl_destroy(LG_FontObj opaque)
|
static void lgf_sdl_destroy(LG_FontObj opaque)
|
||||||
{
|
{
|
||||||
struct Inst * this = (struct Inst *)opaque;
|
struct Inst * this = (struct Inst *)opaque;
|
||||||
|
|
||||||
if (this->font)
|
if (this->font)
|
||||||
TTF_CloseFont(this->font);
|
TTF_CloseFont(this->font);
|
||||||
free(this);
|
free(this);
|
||||||
|
|
||||||
if (--g_initCount == 0)
|
if (--g_initCount == 0)
|
||||||
|
{
|
||||||
|
FcConfigDestroy(g_fontConfig);
|
||||||
|
g_fontConfig = NULL;
|
||||||
|
|
||||||
TTF_Quit();
|
TTF_Quit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static LG_FontBitmap * lgf_sdl_render(LG_FontObj opaque, unsigned int fg_color, const char * text)
|
static LG_FontBitmap * lgf_sdl_render(LG_FontObj opaque, unsigned int fg_color, const char * text)
|
||||||
|
|||||||
@@ -33,7 +33,8 @@ make_object(
|
|||||||
|
|
||||||
add_library(renderer_EGL STATIC
|
add_library(renderer_EGL STATIC
|
||||||
egl.c
|
egl.c
|
||||||
debug.c
|
dynprocs.c
|
||||||
|
egldebug.c
|
||||||
shader.c
|
shader.c
|
||||||
texture.c
|
texture.c
|
||||||
model.c
|
model.c
|
||||||
|
|||||||
@@ -1,58 +0,0 @@
|
|||||||
/*
|
|
||||||
Looking Glass - KVM FrameRelay (KVMFR) Client
|
|
||||||
Copyright (C) 2017-2019 Geoffrey McRae <geoff@hostfission.com>
|
|
||||||
https://looking-glass.hostfission.com
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
|
||||||
the terms of the GNU General Public License as published by the Free Software
|
|
||||||
Foundation; either version 2 of the License, or (at your option) any later
|
|
||||||
version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
|
||||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|
||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <GL/gl.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
void egl_debug_printf(char * format, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
va_start(args, format);
|
|
||||||
vfprintf(stderr, format, args);
|
|
||||||
va_end(args);
|
|
||||||
|
|
||||||
GLenum error = glGetError();
|
|
||||||
switch(error)
|
|
||||||
{
|
|
||||||
case GL_NO_ERROR:
|
|
||||||
fprintf(stderr, " (GL_NO_ERROR)\n");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GL_INVALID_ENUM:
|
|
||||||
fprintf(stderr, " (GL_INVALID_ENUM)\n");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GL_INVALID_VALUE:
|
|
||||||
fprintf(stderr, " (GL_INVALID_VALUE)\n");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GL_INVALID_OPERATION:
|
|
||||||
fprintf(stderr, " (GL_INVALID_OPERATION)\n");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GL_INVALID_FRAMEBUFFER_OPERATION:
|
|
||||||
fprintf(stderr, " (GL_INVALID_FRAMEBUFFER_OPERATION)\n");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GL_OUT_OF_MEMORY:
|
|
||||||
fprintf(stderr, " (GL_OUT_OF_MEMORY)\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
32
client/renderers/EGL/dynprocs.c
Normal file
32
client/renderers/EGL/dynprocs.c
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||||
|
Copyright (C) 2017-2021 Geoffrey McRae <geoff@hostfission.com>
|
||||||
|
https://looking-glass.hostfission.com
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation; either version 2 of the License, or (at your option) any later
|
||||||
|
version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along with
|
||||||
|
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||||
|
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dynprocs.h"
|
||||||
|
|
||||||
|
struct EGLDynProcs g_dynprocs = {0};
|
||||||
|
|
||||||
|
void egl_dynProcsInit(void)
|
||||||
|
{
|
||||||
|
g_dynprocs.eglGetPlatformDisplay = (eglGetPlatformDisplayEXT_t)
|
||||||
|
eglGetProcAddress("eglGetPlatformDisplay");
|
||||||
|
g_dynprocs.eglGetPlatformDisplayEXT = (eglGetPlatformDisplayEXT_t)
|
||||||
|
eglGetProcAddress("eglGetPlatformDisplayEXT");
|
||||||
|
g_dynprocs.glEGLImageTargetTexture2DOES = (glEGLImageTargetTexture2DOES_t)
|
||||||
|
eglGetProcAddress("glEGLImageTargetTexture2DOES");
|
||||||
|
};
|
||||||
37
client/renderers/EGL/dynprocs.h
Normal file
37
client/renderers/EGL/dynprocs.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||||
|
Copyright (C) 2017-2021 Geoffrey McRae <geoff@hostfission.com>
|
||||||
|
https://looking-glass.hostfission.com
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation; either version 2 of the License, or (at your option) any later
|
||||||
|
version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along with
|
||||||
|
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||||
|
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <SDL2/SDL_egl.h>
|
||||||
|
#include <GL/gl.h>
|
||||||
|
|
||||||
|
typedef EGLDisplay (*eglGetPlatformDisplayEXT_t)(EGLenum platform,
|
||||||
|
void *native_display, const EGLint *attrib_list);
|
||||||
|
typedef void (*glEGLImageTargetTexture2DOES_t)(GLenum target,
|
||||||
|
GLeglImageOES image);
|
||||||
|
|
||||||
|
struct EGLDynProcs
|
||||||
|
{
|
||||||
|
eglGetPlatformDisplayEXT_t eglGetPlatformDisplay;
|
||||||
|
eglGetPlatformDisplayEXT_t eglGetPlatformDisplayEXT;
|
||||||
|
glEGLImageTargetTexture2DOES_t glEGLImageTargetTexture2DOES;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct EGLDynProcs g_dynprocs;
|
||||||
|
|
||||||
|
void egl_dynProcsInit(void);
|
||||||
@@ -37,6 +37,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include "app.h"
|
#include "app.h"
|
||||||
|
#include "dynprocs.h"
|
||||||
#include "model.h"
|
#include "model.h"
|
||||||
#include "shader.h"
|
#include "shader.h"
|
||||||
#include "desktop.h"
|
#include "desktop.h"
|
||||||
@@ -102,17 +103,6 @@ struct Inst
|
|||||||
LG_FontObj fontObj;
|
LG_FontObj fontObj;
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool egl_vsync_option_validator(struct Option * opt, const char ** error)
|
|
||||||
{
|
|
||||||
if (opt->value.x_bool && getenv("WAYLAND_DISPLAY"))
|
|
||||||
{
|
|
||||||
DEBUG_WARN("Cannot disable vsync on Wayland, forcing egl:vsync=off");
|
|
||||||
opt->value.x_bool = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct Option egl_options[] =
|
static struct Option egl_options[] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@@ -121,7 +111,6 @@ static struct Option egl_options[] =
|
|||||||
.description = "Enable vsync",
|
.description = "Enable vsync",
|
||||||
.type = OPTION_TYPE_BOOL,
|
.type = OPTION_TYPE_BOOL,
|
||||||
.value.x_bool = false,
|
.value.x_bool = false,
|
||||||
.validator = &egl_vsync_option_validator
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.module = "egl",
|
.module = "egl",
|
||||||
@@ -241,6 +230,16 @@ void egl_deinitialize(void * opaque)
|
|||||||
|
|
||||||
LG_LOCK_FREE(this->lock);
|
LG_LOCK_FREE(this->lock);
|
||||||
|
|
||||||
|
eglMakeCurrent(this->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||||
|
|
||||||
|
if (this->frameContext)
|
||||||
|
eglDestroyContext(this->display, this->frameContext);
|
||||||
|
|
||||||
|
if (this->context)
|
||||||
|
eglDestroyContext(this->display, this->context);
|
||||||
|
|
||||||
|
eglTerminate(this->display);
|
||||||
|
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -495,43 +494,28 @@ bool egl_render_startup(void * opaque, SDL_Window * window)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool useNative = false;
|
egl_dynProcsInit();
|
||||||
{
|
|
||||||
const char *client_exts = eglQueryString(NULL, EGL_EXTENSIONS);
|
|
||||||
if (strstr(client_exts, "EGL_KHR_platform_base") != NULL)
|
|
||||||
useNative = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_INFO("use native: %s", useNative ? "true" : "false");
|
EGLNativeDisplayType native;
|
||||||
|
EGLenum platform;
|
||||||
|
|
||||||
switch(wminfo.subsystem)
|
switch(wminfo.subsystem)
|
||||||
{
|
{
|
||||||
case SDL_SYSWM_X11:
|
case SDL_SYSWM_X11:
|
||||||
{
|
native = (EGLNativeDisplayType)wminfo.info.x11.display;
|
||||||
if (!useNative)
|
platform = EGL_PLATFORM_X11_KHR;
|
||||||
this->display = eglGetPlatformDisplay(EGL_PLATFORM_X11_KHR, wminfo.info.x11.display, NULL);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
EGLNativeDisplayType native = (EGLNativeDisplayType)wminfo.info.x11.display;
|
|
||||||
this->display = eglGetDisplay(native);
|
|
||||||
}
|
|
||||||
this->nativeWind = (EGLNativeWindowType)wminfo.info.x11.window;
|
this->nativeWind = (EGLNativeWindowType)wminfo.info.x11.window;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(SDL_VIDEO_DRIVER_WAYLAND)
|
#if defined(SDL_VIDEO_DRIVER_WAYLAND)
|
||||||
case SDL_SYSWM_WAYLAND:
|
case SDL_SYSWM_WAYLAND:
|
||||||
{
|
{
|
||||||
int width, height;
|
int width, height;
|
||||||
SDL_GetWindowSize(window, &width, &height);
|
SDL_GetWindowSize(window, &width, &height);
|
||||||
if (!useNative)
|
native = (EGLNativeDisplayType)wminfo.info.wl.display;
|
||||||
this->display = eglGetPlatformDisplay(EGL_PLATFORM_WAYLAND_KHR, wminfo.info.wl.display, NULL);
|
platform = EGL_PLATFORM_WAYLAND_KHR;
|
||||||
else
|
this->nativeWind = (EGLNativeWindowType)wl_egl_window_create(
|
||||||
{
|
wminfo.info.wl.surface, width, height);
|
||||||
EGLNativeDisplayType native = (EGLNativeDisplayType)wminfo.info.wl.display;
|
|
||||||
this->display = eglGetDisplay(native);
|
|
||||||
}
|
|
||||||
this->nativeWind = (EGLNativeWindowType)wl_egl_window_create(wminfo.info.wl.surface, width, height);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -541,6 +525,25 @@ bool egl_render_startup(void * opaque, SDL_Window * window)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *early_exts = eglQueryString(NULL, EGL_EXTENSIONS);
|
||||||
|
if (strstr(early_exts, "EGL_KHR_platform_base") != NULL &&
|
||||||
|
g_dynprocs.eglGetPlatformDisplay)
|
||||||
|
{
|
||||||
|
DEBUG_INFO("Using eglGetPlatformDisplay");
|
||||||
|
this->display = g_dynprocs.eglGetPlatformDisplay(platform, native, NULL);
|
||||||
|
}
|
||||||
|
else if (strstr(early_exts, "EGL_EXT_platform_base") != NULL &&
|
||||||
|
g_dynprocs.eglGetPlatformDisplayEXT)
|
||||||
|
{
|
||||||
|
DEBUG_INFO("Using eglGetPlatformDisplayEXT");
|
||||||
|
this->display = g_dynprocs.eglGetPlatformDisplayEXT(platform, native, NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DEBUG_INFO("Using eglGetDisplay");
|
||||||
|
this->display = eglGetDisplay(native);
|
||||||
|
}
|
||||||
|
|
||||||
if (this->display == EGL_NO_DISPLAY)
|
if (this->display == EGL_NO_DISPLAY)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("eglGetDisplay failed");
|
DEBUG_ERROR("eglGetDisplay failed");
|
||||||
@@ -636,20 +639,27 @@ bool egl_render_startup(void * opaque, SDL_Window * window)
|
|||||||
DEBUG_INFO("EGL APIs : %s", eglQueryString(this->display, EGL_CLIENT_APIS));
|
DEBUG_INFO("EGL APIs : %s", eglQueryString(this->display, EGL_CLIENT_APIS));
|
||||||
DEBUG_INFO("Extensions: %s", client_exts);
|
DEBUG_INFO("Extensions: %s", client_exts);
|
||||||
|
|
||||||
if (strstr(client_exts, "EGL_EXT_image_dma_buf_import") != NULL)
|
if (g_dynprocs.glEGLImageTargetTexture2DOES)
|
||||||
{
|
{
|
||||||
/*
|
if (strstr(client_exts, "EGL_EXT_image_dma_buf_import") != NULL)
|
||||||
* As of version 455.45.01 NVidia started advertising support for this
|
{
|
||||||
* feature, however even on the latest version 460.27.04 this is still
|
/*
|
||||||
* broken and does not work, until this is fixed and we have way to detect
|
* As of version 455.45.01 NVidia started advertising support for this
|
||||||
* this early just disable dma for all NVIDIA devices.
|
* feature, however even on the latest version 460.27.04 this is still
|
||||||
*
|
* broken and does not work, until this is fixed and we have way to detect
|
||||||
* ref: https://forums.developer.nvidia.com/t/egl-ext-image-dma-buf-import-broken-egl-bad-alloc-with-tons-of-free-ram/165552
|
* this early just disable dma for all NVIDIA devices.
|
||||||
*/
|
*
|
||||||
if (strstr(vendor, "NVIDIA") != NULL)
|
* ref: https://forums.developer.nvidia.com/t/egl-ext-image-dma-buf-import-broken-egl-bad-alloc-with-tons-of-free-ram/165552
|
||||||
DEBUG_WARN("NVIDIA driver detected, ignoring broken DMA support");
|
*/
|
||||||
else
|
if (strstr(vendor, "NVIDIA") != NULL)
|
||||||
this->dmaSupport = true;
|
DEBUG_WARN("NVIDIA driver detected, ignoring broken DMA support");
|
||||||
|
else
|
||||||
|
this->dmaSupport = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DEBUG_INFO("glEGLImageTargetTexture2DOES unavilable, DMA support disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
eglSwapInterval(this->display, this->opt.vsync ? 1 : 0);
|
eglSwapInterval(this->display, this->opt.vsync ? 1 : 0);
|
||||||
|
|||||||
45
client/renderers/EGL/egldebug.c
Normal file
45
client/renderers/EGL/egldebug.c
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||||
|
Copyright (C) 2017-2021 Geoffrey McRae <geoff@hostfission.com>
|
||||||
|
https://looking-glass.hostfission.com
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation; either version 2 of the License, or (at your option) any later
|
||||||
|
version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along with
|
||||||
|
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||||
|
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "egldebug.h"
|
||||||
|
#include <SDL2/SDL_egl.h>
|
||||||
|
#include <GL/gl.h>
|
||||||
|
|
||||||
|
const char * egl_getErrorStr(void)
|
||||||
|
{
|
||||||
|
switch (eglGetError())
|
||||||
|
{
|
||||||
|
case EGL_SUCCESS : return "EGL_SUCCESS";
|
||||||
|
case EGL_NOT_INITIALIZED : return "EGL_NOT_INITIALIZED";
|
||||||
|
case EGL_BAD_ACCESS : return "EGL_BAD_ACCESS";
|
||||||
|
case EGL_BAD_ALLOC : return "EGL_BAD_ALLOC";
|
||||||
|
case EGL_BAD_ATTRIBUTE : return "EGL_BAD_ATTRIBUTE";
|
||||||
|
case EGL_BAD_CONTEXT : return "EGL_BAD_CONTEXT";
|
||||||
|
case EGL_BAD_CONFIG : return "EGL_BAD_CONFIG";
|
||||||
|
case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
|
||||||
|
case EGL_BAD_DISPLAY : return "EGL_BAD_DISPLAY";
|
||||||
|
case EGL_BAD_SURFACE : return "EGL_BAD_SURFACE";
|
||||||
|
case EGL_BAD_MATCH : return "EGL_BAD_MATCH";
|
||||||
|
case EGL_BAD_PARAMETER : return "EGL_BAD_PARAMETER";
|
||||||
|
case EGL_BAD_NATIVE_PIXMAP : return "EGL_BAD_NATIVE_PIXMAP";
|
||||||
|
case EGL_BAD_NATIVE_WINDOW : return "EGL_BAD_NATIVE_WINDOW";
|
||||||
|
case EGL_CONTEXT_LOST : return "EGL_CONTEXT_LOST";
|
||||||
|
default : return "UNKNOWN";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Looking Glass - KVM FrameRelay (KVMFR) Client
|
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||||
Copyright (C) 2017-2019 Geoffrey McRae <geoff@hostfission.com>
|
Copyright (C) 2017-2021 Geoffrey McRae <geoff@hostfission.com>
|
||||||
https://looking-glass.hostfission.com
|
https://looking-glass.hostfission.com
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -17,11 +17,13 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <common/debug.h>
|
#include "common/debug.h"
|
||||||
|
|
||||||
#define EGL_DEBUG_PRINT(type, fmt, ...) do {egl_debug_printf(type " %20s:%-4u | %-30s | " fmt, STRIPPATH(__FILE__), __LINE__, __FUNCTION__, ##__VA_ARGS__);} while (0)
|
const char * egl_getErrorStr(void);
|
||||||
#define EGL_ERROR(fmt, ...) EGL_DEBUG_PRINT("[E]", fmt, ##__VA_ARGS__)
|
|
||||||
|
|
||||||
void egl_debug_printf(char * format, ...);
|
#define DEBUG_EGL_WARN(fmt, ...) \
|
||||||
|
DEBUG_WARN(fmt " (%s)", ##__VA_ARGS__, egl_getErrorStr())
|
||||||
|
|
||||||
|
#define DEBUG_EGL_ERROR(fmt, ...) \
|
||||||
|
DEBUG_ERROR(fmt " (%s)", ##__VA_ARGS__, egl_getErrorStr())
|
||||||
@@ -154,8 +154,12 @@ void egl_splash_free(EGL_Splash ** splash)
|
|||||||
if (!*splash)
|
if (!*splash)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
egl_model_free(&(*splash)->bg );
|
||||||
egl_model_free(&(*splash)->logo);
|
egl_model_free(&(*splash)->logo);
|
||||||
|
|
||||||
|
egl_shader_free(&(*splash)->bgShader );
|
||||||
|
egl_shader_free(&(*splash)->logoShader);
|
||||||
|
|
||||||
free(*splash);
|
free(*splash);
|
||||||
*splash = NULL;
|
*splash = NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,8 +20,9 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
#include "texture.h"
|
#include "texture.h"
|
||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
#include "common/framebuffer.h"
|
#include "common/framebuffer.h"
|
||||||
#include "debug.h"
|
#include "dynprocs.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "egldebug.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -141,7 +142,8 @@ static bool egl_texture_map(EGL_Texture * texture, uint8_t i)
|
|||||||
|
|
||||||
if (!texture->buf[i].map)
|
if (!texture->buf[i].map)
|
||||||
{
|
{
|
||||||
EGL_ERROR("glMapBufferRange failed for %d of %lu bytes", i, texture->pboBufferSize);
|
DEBUG_EGL_ERROR("glMapBufferRange failed for %d of %lu bytes", i,
|
||||||
|
texture->pboBufferSize);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -386,13 +388,13 @@ bool egl_texture_update_from_dma(EGL_Texture * texture, const FrameBuffer * fram
|
|||||||
|
|
||||||
if (image == EGL_NO_IMAGE)
|
if (image == EGL_NO_IMAGE)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("failed to create ELGImage for DMA transfer");
|
DEBUG_EGL_ERROR("Failed to create ELGImage for DMA transfer");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* bind the texture and initiate the transfer */
|
/* bind the texture and initiate the transfer */
|
||||||
glBindTexture(GL_TEXTURE_2D, texture->tex);
|
glBindTexture(GL_TEXTURE_2D, texture->tex);
|
||||||
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
|
g_dynprocs.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
|
||||||
|
|
||||||
/* wait for completion */
|
/* wait for completion */
|
||||||
framebuffer_wait(frame, texture->height * texture->stride);
|
framebuffer_wait(frame, texture->height * texture->stride);
|
||||||
@@ -480,7 +482,7 @@ enum EGL_TexStatus egl_texture_bind(EGL_Texture * texture)
|
|||||||
case GL_INVALID_VALUE:
|
case GL_INVALID_VALUE:
|
||||||
glDeleteSync(texture->buf[b].sync);
|
glDeleteSync(texture->buf[b].sync);
|
||||||
texture->buf[b].sync = 0;
|
texture->buf[b].sync = 0;
|
||||||
EGL_ERROR("glClientWaitSync failed");
|
DEBUG_EGL_ERROR("glClientWaitSync failed");
|
||||||
return EGL_TEX_STATUS_ERROR;
|
return EGL_TEX_STATUS_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ project(renderer_Opengl LANGUAGES C)
|
|||||||
find_package(PkgConfig)
|
find_package(PkgConfig)
|
||||||
pkg_check_modules(RENDERER_OPENGL_PKGCONFIG REQUIRED
|
pkg_check_modules(RENDERER_OPENGL_PKGCONFIG REQUIRED
|
||||||
gl
|
gl
|
||||||
glu
|
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(renderer_OpenGL STATIC
|
add_library(renderer_OpenGL STATIC
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
#include <SDL2/SDL_ttf.h>
|
#include <SDL2/SDL_ttf.h>
|
||||||
|
|
||||||
#include <GL/gl.h>
|
#include <GL/gl.h>
|
||||||
#include <GL/glu.h>
|
|
||||||
#include <GL/glx.h>
|
#include <GL/glx.h>
|
||||||
|
|
||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
@@ -48,17 +47,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
|
|
||||||
#define FADE_TIME 1000000
|
#define FADE_TIME 1000000
|
||||||
|
|
||||||
static bool opengl_vsync_option_validator(struct Option * opt, const char ** error)
|
|
||||||
{
|
|
||||||
if (opt->value.x_bool && getenv("WAYLAND_DISPLAY"))
|
|
||||||
{
|
|
||||||
DEBUG_WARN("Cannot disable vsync on Wayland, forcing opengl:vsync=off");
|
|
||||||
opt->value.x_bool = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct Option opengl_options[] =
|
static struct Option opengl_options[] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@@ -74,7 +62,6 @@ static struct Option opengl_options[] =
|
|||||||
.description = "Enable vsync",
|
.description = "Enable vsync",
|
||||||
.type = OPTION_TYPE_BOOL,
|
.type = OPTION_TYPE_BOOL,
|
||||||
.value.x_bool = false,
|
.value.x_bool = false,
|
||||||
.validator = &opengl_vsync_option_validator
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.module = "opengl",
|
.module = "opengl",
|
||||||
@@ -331,7 +318,7 @@ void opengl_on_resize(void * opaque, const int width, const int height,
|
|||||||
glViewport(0, 0, this->window.x, this->window.y);
|
glViewport(0, 0, this->window.x, this->window.y);
|
||||||
glMatrixMode(GL_PROJECTION);
|
glMatrixMode(GL_PROJECTION);
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
gluOrtho2D(0, this->window.x, this->window.y, 0);
|
glOrtho(0, this->window.x, this->window.y, 0, -1, 1);
|
||||||
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
@@ -854,7 +841,40 @@ static bool _check_gl_error(unsigned int line, const char * name)
|
|||||||
if (error == GL_NO_ERROR)
|
if (error == GL_NO_ERROR)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const GLubyte * errStr = gluErrorString(error);
|
const char * errStr;
|
||||||
|
switch (error)
|
||||||
|
{
|
||||||
|
case GL_INVALID_ENUM:
|
||||||
|
errStr = "GL_INVALID_ENUM";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GL_INVALID_VALUE:
|
||||||
|
errStr = "GL_INVALID_VALUE";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GL_INVALID_OPERATION:
|
||||||
|
errStr = "GL_INVALID_OPERATION";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GL_STACK_OVERFLOW:
|
||||||
|
errStr = "GL_STACK_OVERFLOW";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GL_STACK_UNDERFLOW:
|
||||||
|
errStr = "GL_STACK_UNDERFLOW";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GL_OUT_OF_MEMORY:
|
||||||
|
errStr = "GL_OUT_OF_MEMORY";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GL_TABLE_TOO_LARGE:
|
||||||
|
errStr = "GL_TABLE_TOO_LARGE";
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
errStr = "unknown error";
|
||||||
|
}
|
||||||
DEBUG_ERROR("%d: %s = %d (%s)", line, name, error, errStr);
|
DEBUG_ERROR("%d: %s = %d (%s)", line, name, error, errStr);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1282,7 +1302,7 @@ static bool draw_frame(struct Inst * this)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case GL_WAIT_FAILED:
|
case GL_WAIT_FAILED:
|
||||||
DEBUG_ERROR("Wait failed %s", gluErrorString(glGetError()));
|
DEBUG_ERROR("Wait failed %d", glGetError());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -152,16 +152,11 @@ void app_handleFocusEvent(bool focused)
|
|||||||
if (!app_inputEnabled())
|
if (!app_inputEnabled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (params.grabKeyboardOnFocus)
|
|
||||||
{
|
|
||||||
if (focused)
|
|
||||||
g_state.ds->grabKeyboard();
|
|
||||||
else
|
|
||||||
g_state.ds->ungrabKeyboard();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!focused)
|
if (!focused)
|
||||||
|
{
|
||||||
|
setGrabQuiet(false);
|
||||||
setCursorInView(false);
|
setCursorInView(false);
|
||||||
|
}
|
||||||
|
|
||||||
g_cursor.realign = true;
|
g_cursor.realign = true;
|
||||||
g_state.ds->realignPointer();
|
g_state.ds->realignPointer();
|
||||||
@@ -506,7 +501,7 @@ static int cursorThread(void * unused)
|
|||||||
g_cursor.guest.y
|
g_cursor.guest.y
|
||||||
);
|
);
|
||||||
|
|
||||||
if (params.mouseRedraw)
|
if (params.mouseRedraw && g_cursor.guest.visible)
|
||||||
lgSignalEvent(e_frame);
|
lgSignalEvent(e_frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1013,6 +1008,9 @@ static void setCursorInView(bool enable)
|
|||||||
|
|
||||||
if (warpSupport && !params.captureInputOnly)
|
if (warpSupport && !params.captureInputOnly)
|
||||||
g_state.ds->grabPointer();
|
g_state.ds->grabPointer();
|
||||||
|
|
||||||
|
if (params.grabKeyboardOnFocus)
|
||||||
|
g_state.ds->grabKeyboard();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1022,7 +1020,7 @@ static void setCursorInView(bool enable)
|
|||||||
if (warpSupport)
|
if (warpSupport)
|
||||||
g_state.ds->ungrabPointer();
|
g_state.ds->ungrabPointer();
|
||||||
|
|
||||||
setGrabQuiet(false);
|
g_state.ds->ungrabKeyboard();
|
||||||
}
|
}
|
||||||
|
|
||||||
g_cursor.warpState = WARP_STATE_ON;
|
g_cursor.warpState = WARP_STATE_ON;
|
||||||
@@ -1452,6 +1450,9 @@ void app_handleMouseBasic()
|
|||||||
int x = (int) round((px - local.x) / g_cursor.dpiScale);
|
int x = (int) round((px - local.x) / g_cursor.dpiScale);
|
||||||
int y = (int) round((py - local.y) / g_cursor.dpiScale);
|
int y = (int) round((py - local.y) / g_cursor.dpiScale);
|
||||||
|
|
||||||
|
if (!x && !y)
|
||||||
|
return;
|
||||||
|
|
||||||
g_cursor.guest.x += x;
|
g_cursor.guest.x += x;
|
||||||
g_cursor.guest.y += y;
|
g_cursor.guest.y += y;
|
||||||
|
|
||||||
@@ -1562,8 +1563,7 @@ static void setGrabQuiet(bool enable)
|
|||||||
{
|
{
|
||||||
if (params.grabKeyboard)
|
if (params.grabKeyboard)
|
||||||
{
|
{
|
||||||
if (!g_state.focused || !params.grabKeyboardOnFocus ||
|
if (!params.grabKeyboardOnFocus || !g_state.focused || params.captureInputOnly)
|
||||||
params.captureInputOnly)
|
|
||||||
g_state.ds->ungrabKeyboard();
|
g_state.ds->ungrabKeyboard();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1609,14 +1609,23 @@ int eventFilter(void * userdata, SDL_Event * event)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void int_handler(int signal)
|
void int_handler(int sig)
|
||||||
{
|
{
|
||||||
switch(signal)
|
switch(sig)
|
||||||
{
|
{
|
||||||
case SIGINT:
|
case SIGINT:
|
||||||
case SIGTERM:
|
case SIGTERM:
|
||||||
DEBUG_INFO("Caught signal, shutting down...");
|
if (g_state.state != APP_STATE_SHUTDOWN)
|
||||||
g_state.state = APP_STATE_SHUTDOWN;
|
{
|
||||||
|
DEBUG_INFO("Caught signal, shutting down...");
|
||||||
|
g_state.state = APP_STATE_SHUTDOWN;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DEBUG_INFO("Caught second signal, force quitting...");
|
||||||
|
signal(sig, SIG_DFL);
|
||||||
|
raise(sig);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2037,6 +2046,8 @@ static int lg_run(void)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lgInit();
|
||||||
|
|
||||||
// start the renderThread so we don't just display junk
|
// start the renderThread so we don't just display junk
|
||||||
if (!lgCreateThread("renderThread", renderThread, NULL, &t_render))
|
if (!lgCreateThread("renderThread", renderThread, NULL, &t_render))
|
||||||
{
|
{
|
||||||
@@ -2079,8 +2090,6 @@ static int lg_run(void)
|
|||||||
KVMFR *udata;
|
KVMFR *udata;
|
||||||
int waitCount = 0;
|
int waitCount = 0;
|
||||||
|
|
||||||
lgInit();
|
|
||||||
|
|
||||||
restart:
|
restart:
|
||||||
while(g_state.state == APP_STATE_RUNNING)
|
while(g_state.state == APP_STATE_RUNNING)
|
||||||
{
|
{
|
||||||
@@ -2104,7 +2113,8 @@ restart:
|
|||||||
{
|
{
|
||||||
DEBUG_BREAK();
|
DEBUG_BREAK();
|
||||||
DEBUG_INFO("Please check the host application is running and is the correct version");
|
DEBUG_INFO("Please check the host application is running and is the correct version");
|
||||||
DEBUG_INFO("Check the host log in your guest at %%TEMP%%\\looking-glass-host.txt");
|
DEBUG_INFO("Check the host log in your guest at: "
|
||||||
|
"%%ProgramData%%\\Looking Glass (host)\\looking-glass-host.txt");
|
||||||
DEBUG_INFO("Continuing to wait...");
|
DEBUG_INFO("Continuing to wait...");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -223,6 +223,12 @@ void option_free(void)
|
|||||||
state.options = NULL;
|
state.options = NULL;
|
||||||
state.oCount = 0;
|
state.oCount = 0;
|
||||||
|
|
||||||
|
for(int g = 0; g < state.gCount; ++g)
|
||||||
|
{
|
||||||
|
struct OptionGroup * group = &state.groups[g];
|
||||||
|
if (group->options)
|
||||||
|
free(group->options);
|
||||||
|
}
|
||||||
free(state.groups);
|
free(state.groups);
|
||||||
state.groups = NULL;
|
state.groups = NULL;
|
||||||
state.gCount = 0;
|
state.gCount = 0;
|
||||||
|
|||||||
@@ -20,3 +20,7 @@ target_link_libraries(lg_common_platform_code
|
|||||||
lg_common
|
lg_common
|
||||||
setupapi
|
setupapi
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (ENABLE_BACKTRACE)
|
||||||
|
target_link_libraries(lg_common_platform_code dbghelp)
|
||||||
|
endif()
|
||||||
|
|||||||
@@ -18,9 +18,142 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "common/crash.h"
|
#include "common/crash.h"
|
||||||
|
#include "common/debug.h"
|
||||||
|
#include "common/version.h"
|
||||||
|
|
||||||
|
#ifdef ENABLE_BACKTRACE
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#include <dbghelp.h>
|
||||||
|
|
||||||
|
static const char * exception_name(DWORD code)
|
||||||
|
{
|
||||||
|
switch (code)
|
||||||
|
{
|
||||||
|
case EXCEPTION_ACCESS_VIOLATION:
|
||||||
|
return "ACCESS_VIOLATION";
|
||||||
|
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
|
||||||
|
return "ARRAY_BOUNDS_EXCEEDED";
|
||||||
|
case EXCEPTION_BREAKPOINT:
|
||||||
|
return "BREAKPOINT";
|
||||||
|
case EXCEPTION_DATATYPE_MISALIGNMENT:
|
||||||
|
return "DATATYPE_MISALIGNMENT";
|
||||||
|
case EXCEPTION_FLT_DENORMAL_OPERAND:
|
||||||
|
return "FLT_DENORMAL_OPERAND";
|
||||||
|
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
|
||||||
|
return "FLT_DIVIDE_BY_ZERO";
|
||||||
|
case EXCEPTION_FLT_INEXACT_RESULT:
|
||||||
|
return "FLT_INEXACT_RESULT";
|
||||||
|
case EXCEPTION_FLT_INVALID_OPERATION:
|
||||||
|
return "FLT_INVALID_OPERATION";
|
||||||
|
case EXCEPTION_FLT_OVERFLOW:
|
||||||
|
return "FLT_OVERFLOW";
|
||||||
|
case EXCEPTION_FLT_STACK_CHECK:
|
||||||
|
return "FLT_STACK_CHECK";
|
||||||
|
case EXCEPTION_FLT_UNDERFLOW:
|
||||||
|
return "FLT_UNDERFLOW";
|
||||||
|
case EXCEPTION_ILLEGAL_INSTRUCTION:
|
||||||
|
return "ILLEGAL_INSTRUCTION";
|
||||||
|
case EXCEPTION_IN_PAGE_ERROR:
|
||||||
|
return "IN_PAGE_ERROR";
|
||||||
|
case EXCEPTION_INT_DIVIDE_BY_ZERO:
|
||||||
|
return "INT_DIVIDE_BY_ZERO";
|
||||||
|
case EXCEPTION_INT_OVERFLOW:
|
||||||
|
return "INT_OVERFLOW";
|
||||||
|
case EXCEPTION_INVALID_DISPOSITION:
|
||||||
|
return "INVALID_DISPOSITION";
|
||||||
|
case EXCEPTION_NONCONTINUABLE_EXCEPTION:
|
||||||
|
return "NONCONTINUABLE_EXCEPTION";
|
||||||
|
case EXCEPTION_PRIV_INSTRUCTION:
|
||||||
|
return "PRIV_INSTRUCTION";
|
||||||
|
case EXCEPTION_SINGLE_STEP:
|
||||||
|
return "SINGLE_STEP";
|
||||||
|
case EXCEPTION_STACK_OVERFLOW:
|
||||||
|
return "STACK_OVERFLOW";
|
||||||
|
default:
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static LONG CALLBACK exception_filter(EXCEPTION_POINTERS * exc)
|
||||||
|
{
|
||||||
|
PEXCEPTION_RECORD excInfo = exc->ExceptionRecord;
|
||||||
|
CONTEXT context;
|
||||||
|
memcpy(&context, exc->ContextRecord, sizeof context);
|
||||||
|
|
||||||
|
DEBUG_ERROR("==== FATAL CRASH (%s) ====", BUILD_VERSION);
|
||||||
|
DEBUG_ERROR("exception 0x%08lx (%s), address is %p", excInfo->ExceptionCode,
|
||||||
|
exception_name(excInfo->ExceptionCode), excInfo->ExceptionAddress);
|
||||||
|
|
||||||
|
if (!SymInitialize(GetCurrentProcess(), NULL, TRUE))
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Failed to SymInitialize: 0x%08lx, could not generate stack trace", GetLastError());
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
SymSetOptions(SYMOPT_LOAD_LINES);
|
||||||
|
|
||||||
|
STACKFRAME64 frame = { 0 };
|
||||||
|
frame.AddrPC.Offset = context.Rip;
|
||||||
|
frame.AddrPC.Mode = AddrModeFlat;
|
||||||
|
frame.AddrFrame.Offset = context.Rbp;
|
||||||
|
frame.AddrFrame.Mode = AddrModeFlat;
|
||||||
|
frame.AddrStack.Offset = context.Rsp;
|
||||||
|
frame.AddrStack.Mode = AddrModeFlat;
|
||||||
|
|
||||||
|
HANDLE hProcess = GetCurrentProcess();
|
||||||
|
HANDLE hThread = GetCurrentThread();
|
||||||
|
|
||||||
|
for (int i = 1; StackWalk64(IMAGE_FILE_MACHINE_AMD64, hProcess, hThread, &frame, &context, NULL,
|
||||||
|
SymFunctionTableAccess64, SymGetModuleBase64, NULL); ++i)
|
||||||
|
{
|
||||||
|
DWORD64 moduleBase = SymGetModuleBase64(hProcess, frame.AddrPC.Offset);
|
||||||
|
char moduleName[MAX_PATH];
|
||||||
|
|
||||||
|
if (moduleBase && GetModuleFileNameA((HMODULE) moduleBase, moduleName, MAX_PATH))
|
||||||
|
{
|
||||||
|
DWORD64 disp;
|
||||||
|
|
||||||
|
char symbolBuf[sizeof(SYMBOL_INFO) + 255];
|
||||||
|
PSYMBOL_INFO symbol = (PSYMBOL_INFO) symbolBuf;
|
||||||
|
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||||
|
symbol->MaxNameLen = 256;
|
||||||
|
|
||||||
|
if (SymFromAddr(hProcess, frame.AddrPC.Offset, &disp, symbol))
|
||||||
|
{
|
||||||
|
IMAGEHLP_LINE line = { sizeof(IMAGEHLP_LINE), 0 };
|
||||||
|
DWORD lineDisp;
|
||||||
|
|
||||||
|
if (SymGetLineFromAddr64(hProcess, frame.AddrPC.Offset, &lineDisp, &line))
|
||||||
|
DEBUG_ERROR("[trace]: %2d: %s:%s+0x%" PRIx64 " (%s:%ld+0x%lx)", i, moduleName, symbol->Name, disp,
|
||||||
|
line.FileName, line.LineNumber, lineDisp);
|
||||||
|
else
|
||||||
|
DEBUG_ERROR("[trace]: %2d: %s:%s+0x%" PRIx64, i, moduleName, symbol->Name, disp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
DEBUG_ERROR("[trace]: %2d: %s+0x%08" PRIx64, i, moduleName, frame.AddrPC.Offset - moduleBase);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
DEBUG_ERROR("[trace]: %2d: 0x%016" PRIx64, i, frame.AddrPC.Offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
SymCleanup(hProcess);
|
||||||
|
|
||||||
|
fail:
|
||||||
|
fflush(stderr);
|
||||||
|
return EXCEPTION_CONTINUE_SEARCH;
|
||||||
|
}
|
||||||
|
|
||||||
bool installCrashHandler(const char * exe)
|
bool installCrashHandler(const char * exe)
|
||||||
{
|
{
|
||||||
//TODO
|
SetUnhandledExceptionFilter(exception_filter);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
bool installCrashHandler(const char * exe)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -6,12 +6,17 @@ set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/")
|
|||||||
include(CheckCCompilerFlag)
|
include(CheckCCompilerFlag)
|
||||||
include(FeatureSummary)
|
include(FeatureSummary)
|
||||||
|
|
||||||
option(OPTIMIZE_FOR_NATIVE "Build with -march=native" ON)
|
option(OPTIMIZE_FOR_NATIVE "Build with -march=native" OFF)
|
||||||
if(OPTIMIZE_FOR_NATIVE)
|
if(OPTIMIZE_FOR_NATIVE)
|
||||||
CHECK_C_COMPILER_FLAG("-march=native" COMPILER_SUPPORTS_MARCH_NATIVE)
|
CHECK_C_COMPILER_FLAG("-march=native" COMPILER_SUPPORTS_MARCH_NATIVE)
|
||||||
if(COMPILER_SUPPORTS_MARCH_NATIVE)
|
if(COMPILER_SUPPORTS_MARCH_NATIVE)
|
||||||
add_compile_options("-march=native")
|
add_compile_options("-march=native")
|
||||||
endif()
|
endif()
|
||||||
|
else()
|
||||||
|
CHECK_C_COMPILER_FLAG("-march=nehalem" COMPILER_SUPPORTS_MARCH_NEHALEM)
|
||||||
|
if(COMPILER_SUPPORTS_MARCH_NEHALEM)
|
||||||
|
add_compile_options("-march=nehalem")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
option(ENABLE_BACKTRACE "Enable backtrace support on crash" ON)
|
option(ENABLE_BACKTRACE "Enable backtrace support on crash" ON)
|
||||||
|
|||||||
@@ -54,16 +54,19 @@ The resulting installer will be at
|
|||||||
|
|
||||||
## Where is the log?
|
## Where is the log?
|
||||||
|
|
||||||
It is in your user's temp directory:
|
The log file for the host application is located at:
|
||||||
|
|
||||||
%TEMP%\looking-glass-host.txt
|
%ProgramData%\Looking Glass (host)\looking-glass-host.txt
|
||||||
|
|
||||||
Or if running as a system service it will be located in:
|
You can also find out where the file is by right clicking on the tray icon and
|
||||||
|
selecting "Log File Location".
|
||||||
|
|
||||||
C:\Windows\Temp\looking-glass-host.txt
|
The log file for the looking glass service is located at:
|
||||||
|
|
||||||
You can find out where the file is by right clicking on the tray icon and
|
%ProgramData%\Looking Glass (host)\looking-glass-host-service.txt
|
||||||
selecting "Log File Location"
|
|
||||||
|
This is useful for troubleshooting errors related to the host application not
|
||||||
|
starting.
|
||||||
|
|
||||||
### High priority capture using DXGI and Secure Desktop (UAC) capture support
|
### High priority capture using DXGI and Secure Desktop (UAC) capture support
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ target_link_libraries(platform_Windows
|
|||||||
userenv
|
userenv
|
||||||
wtsapi32
|
wtsapi32
|
||||||
psapi
|
psapi
|
||||||
|
shlwapi
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(platform_Windows
|
target_include_directories(platform_Windows
|
||||||
|
|||||||
@@ -743,7 +743,7 @@ static CaptureResult dxgi_capture(void)
|
|||||||
assert(this);
|
assert(this);
|
||||||
assert(this->initialized);
|
assert(this->initialized);
|
||||||
|
|
||||||
Texture * tex;
|
Texture * tex = NULL;
|
||||||
CaptureResult result;
|
CaptureResult result;
|
||||||
HRESULT status;
|
HRESULT status;
|
||||||
DXGI_OUTDUPL_FRAME_INFO frameInfo;
|
DXGI_OUTDUPL_FRAME_INFO frameInfo;
|
||||||
|
|||||||
@@ -60,12 +60,16 @@ struct iface
|
|||||||
LGEvent * cursorEvents[2];
|
LGEvent * cursorEvents[2];
|
||||||
|
|
||||||
int mouseX, mouseY, mouseHotX, mouseHotY;
|
int mouseX, mouseY, mouseHotX, mouseHotY;
|
||||||
bool mouseVisible;
|
bool mouseVisible, hasMousePosition;
|
||||||
|
|
||||||
|
bool mouseHookCreated;
|
||||||
|
bool forceCompositionCreated;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct iface * this = NULL;
|
static struct iface * this = NULL;
|
||||||
|
|
||||||
static void nvfbc_free();
|
static bool nvfbc_deinit(void);
|
||||||
|
static void nvfbc_free(void);
|
||||||
static int pointerThread(void * unused);
|
static int pointerThread(void * unused);
|
||||||
|
|
||||||
static void getDesktopSize(unsigned int * width, unsigned int * height, unsigned int * dpi)
|
static void getDesktopSize(unsigned int * width, unsigned int * height, unsigned int * dpi)
|
||||||
@@ -84,8 +88,9 @@ static void getDesktopSize(unsigned int * width, unsigned int * height, unsigned
|
|||||||
|
|
||||||
static void on_mouseMove(int x, int y)
|
static void on_mouseMove(int x, int y)
|
||||||
{
|
{
|
||||||
this->mouseX = x;
|
this->hasMousePosition = true;
|
||||||
this->mouseY = y;
|
this->mouseX = x;
|
||||||
|
this->mouseY = y;
|
||||||
lgSignalEvent(this->cursorEvents[0]);
|
lgSignalEvent(this->cursorEvents[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,36 +123,7 @@ static bool nvfbc_create(
|
|||||||
if (!NvFBCInit())
|
if (!NvFBCInit())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
int bufferLen = GetEnvironmentVariable("NVFBC_PRIV_DATA", NULL, 0);
|
|
||||||
uint8_t * privData = NULL;
|
|
||||||
int privDataLen = 0;
|
|
||||||
|
|
||||||
if(bufferLen)
|
|
||||||
{
|
|
||||||
char * buffer = malloc(bufferLen);
|
|
||||||
GetEnvironmentVariable("NVFBC_PRIV_DATA", buffer, bufferLen);
|
|
||||||
|
|
||||||
privDataLen = (bufferLen - 1) / 2;
|
|
||||||
privData = (uint8_t *)malloc(privDataLen);
|
|
||||||
char hex[3] = {0};
|
|
||||||
for(int i = 0; i < privDataLen; ++i)
|
|
||||||
{
|
|
||||||
memcpy(hex, &buffer[i*2], 2);
|
|
||||||
privData[i] = (uint8_t)strtoul(hex, NULL, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
this = (struct iface *)calloc(sizeof(struct iface), 1);
|
this = (struct iface *)calloc(sizeof(struct iface), 1);
|
||||||
if (!NvFBCToSysCreate(privData, privDataLen, &this->nvfbc, &this->maxWidth, &this->maxHeight))
|
|
||||||
{
|
|
||||||
free(privData);
|
|
||||||
nvfbc_free();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
free(privData);
|
|
||||||
|
|
||||||
this->frameEvent = lgCreateEvent(true, 17);
|
this->frameEvent = lgCreateEvent(true, 17);
|
||||||
if (!this->frameEvent)
|
if (!this->frameEvent)
|
||||||
{
|
{
|
||||||
@@ -166,6 +142,35 @@ static bool nvfbc_create(
|
|||||||
static bool nvfbc_init(void)
|
static bool nvfbc_init(void)
|
||||||
{
|
{
|
||||||
this->stop = false;
|
this->stop = false;
|
||||||
|
|
||||||
|
int bufferLen = GetEnvironmentVariable("NVFBC_PRIV_DATA", NULL, 0);
|
||||||
|
uint8_t * privData = NULL;
|
||||||
|
int privDataLen = 0;
|
||||||
|
|
||||||
|
if (bufferLen)
|
||||||
|
{
|
||||||
|
char * buffer = malloc(bufferLen);
|
||||||
|
GetEnvironmentVariable("NVFBC_PRIV_DATA", buffer, bufferLen);
|
||||||
|
|
||||||
|
privDataLen = (bufferLen - 1) / 2;
|
||||||
|
privData = (uint8_t *)malloc(privDataLen);
|
||||||
|
char hex[3] = {0};
|
||||||
|
for(int i = 0; i < privDataLen; ++i)
|
||||||
|
{
|
||||||
|
memcpy(hex, &buffer[i*2], 2);
|
||||||
|
privData[i] = (uint8_t)strtoul(hex, NULL, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!NvFBCToSysCreate(privData, privDataLen, &this->nvfbc, &this->maxWidth, &this->maxHeight))
|
||||||
|
{
|
||||||
|
free(privData);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
free(privData);
|
||||||
|
|
||||||
getDesktopSize(&this->width, &this->height, &this->dpi);
|
getDesktopSize(&this->width, &this->height, &this->dpi);
|
||||||
lgResetEvent(this->frameEvent);
|
lgResetEvent(this->frameEvent);
|
||||||
|
|
||||||
@@ -186,12 +191,21 @@ static bool nvfbc_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
this->cursorEvents[0] = lgCreateEvent(true, 10);
|
this->cursorEvents[0] = lgCreateEvent(true, 10);
|
||||||
mouseHook_install(on_mouseMove);
|
|
||||||
|
|
||||||
if (this->seperateCursor)
|
if (this->seperateCursor)
|
||||||
this->cursorEvents[1] = lgWrapEvent(event);
|
this->cursorEvents[1] = lgWrapEvent(event);
|
||||||
|
|
||||||
dwmForceComposition();
|
if (!this->mouseHookCreated)
|
||||||
|
{
|
||||||
|
mouseHook_install(on_mouseMove);
|
||||||
|
this->mouseHookCreated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this->forceCompositionCreated)
|
||||||
|
{
|
||||||
|
dwmForceComposition();
|
||||||
|
this->forceCompositionCreated = true;
|
||||||
|
}
|
||||||
|
|
||||||
DEBUG_INFO("Cursor mode : %s", this->seperateCursor ? "decoupled" : "integrated");
|
DEBUG_INFO("Cursor mode : %s", this->seperateCursor ? "decoupled" : "integrated");
|
||||||
|
|
||||||
@@ -200,6 +214,7 @@ static bool nvfbc_init(void)
|
|||||||
if (!lgCreateThread("NvFBCPointer", pointerThread, NULL, &this->pointerThread))
|
if (!lgCreateThread("NvFBCPointer", pointerThread, NULL, &this->pointerThread))
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to create the NvFBCPointer thread");
|
DEBUG_ERROR("Failed to create the NvFBCPointer thread");
|
||||||
|
nvfbc_deinit();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,25 +238,32 @@ static void nvfbc_stop(void)
|
|||||||
|
|
||||||
static bool nvfbc_deinit(void)
|
static bool nvfbc_deinit(void)
|
||||||
{
|
{
|
||||||
mouseHook_remove();
|
|
||||||
dwmUnforceComposition();
|
|
||||||
|
|
||||||
if (this->cursorEvents[0])
|
if (this->cursorEvents[0])
|
||||||
{
|
{
|
||||||
lgFreeEvent(this->cursorEvents[0]);
|
lgFreeEvent(this->cursorEvents[0]);
|
||||||
this->cursorEvents[0] = NULL;
|
this->cursorEvents[0] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this->nvfbc)
|
||||||
|
{
|
||||||
|
NvFBCToSysRelease(&this->nvfbc);
|
||||||
|
this->nvfbc = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nvfbc_free(void)
|
static void nvfbc_free(void)
|
||||||
{
|
{
|
||||||
NvFBCToSysRelease(&this->nvfbc);
|
|
||||||
|
|
||||||
if (this->frameEvent)
|
if (this->frameEvent)
|
||||||
lgFreeEvent(this->frameEvent);
|
lgFreeEvent(this->frameEvent);
|
||||||
|
|
||||||
|
if (this->mouseHookCreated)
|
||||||
|
mouseHook_remove();
|
||||||
|
|
||||||
|
if (this->forceCompositionCreated)
|
||||||
|
dwmUnforceComposition();
|
||||||
|
|
||||||
free(this);
|
free(this);
|
||||||
this = NULL;
|
this = NULL;
|
||||||
NvFBCFree();
|
NvFBCFree();
|
||||||
@@ -350,6 +372,8 @@ static CaptureResult nvfbc_getFrame(FrameBuffer * frame)
|
|||||||
|
|
||||||
static int pointerThread(void * unused)
|
static int pointerThread(void * unused)
|
||||||
{
|
{
|
||||||
|
lgSignalEvent(this->cursorEvents[1]);
|
||||||
|
|
||||||
while(!this->stop)
|
while(!this->stop)
|
||||||
{
|
{
|
||||||
LGEvent * events[2];
|
LGEvent * events[2];
|
||||||
@@ -362,6 +386,7 @@ static int pointerThread(void * unused)
|
|||||||
|
|
||||||
CaptureResult result;
|
CaptureResult result;
|
||||||
CapturePointer pointer = { 0 };
|
CapturePointer pointer = { 0 };
|
||||||
|
bool hotspotUpdated = false;
|
||||||
|
|
||||||
if (this->seperateCursor && events[1])
|
if (this->seperateCursor && events[1])
|
||||||
{
|
{
|
||||||
@@ -383,9 +408,10 @@ static int pointerThread(void * unused)
|
|||||||
this->mouseVisible = pointer.visible;
|
this->mouseVisible = pointer.visible;
|
||||||
this->mouseHotX = pointer.hx;
|
this->mouseHotX = pointer.hx;
|
||||||
this->mouseHotY = pointer.hy;
|
this->mouseHotY = pointer.hy;
|
||||||
|
hotspotUpdated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (events[0])
|
if (events[0] || (hotspotUpdated && this->hasMousePosition))
|
||||||
{
|
{
|
||||||
pointer.positionUpdate = true;
|
pointer.positionUpdate = true;
|
||||||
pointer.visible = this->mouseVisible;
|
pointer.visible = this->mouseVisible;
|
||||||
|
|||||||
@@ -129,6 +129,7 @@ Section "-Install" Section1
|
|||||||
|
|
||||||
SetOutPath $INSTDIR
|
SetOutPath $INSTDIR
|
||||||
File ..\..\looking-glass-host.exe
|
File ..\..\looking-glass-host.exe
|
||||||
|
File /nonfatal ..\..\looking-glass-host.pdb
|
||||||
File LICENSE.txt
|
File LICENSE.txt
|
||||||
WriteUninstaller $INSTDIR\uninstaller.exe
|
WriteUninstaller $INSTDIR\uninstaller.exe
|
||||||
|
|
||||||
@@ -171,7 +172,7 @@ Section /o "Desktop Shortcut" Section3
|
|||||||
StrCpy $option_desktop 1
|
StrCpy $option_desktop 1
|
||||||
SectionEnd
|
SectionEnd
|
||||||
|
|
||||||
Section /o "Start Menu Shortcut" Section4
|
Section "Start Menu Shortcut" Section4
|
||||||
StrCpy $option_startMenu 1
|
StrCpy $option_startMenu 1
|
||||||
SectionEnd
|
SectionEnd
|
||||||
|
|
||||||
@@ -179,7 +180,10 @@ Section "-Hidden Start Menu" Section5
|
|||||||
SetShellVarContext all
|
SetShellVarContext all
|
||||||
|
|
||||||
${If} $option_startMenu == 1
|
${If} $option_startMenu == 1
|
||||||
CreateShortCut "$SMPROGRAMS\Looking Glass (host).lnk" $INSTDIR\looking-glass-host.exe
|
CreateDirectory "$APPDATA\Looking Glass (host)"
|
||||||
|
CreateDirectory "$SMPROGRAMS\Looking Glass (host)"
|
||||||
|
CreateShortCut "$SMPROGRAMS\Looking Glass (host)\Looking Glass (host).lnk" $INSTDIR\looking-glass-host.exe
|
||||||
|
CreateShortCut "$SMPROGRAMS\Looking Glass (host)\Looking Glass Logs.lnk" "$APPDATA\Looking Glass (host)"
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
${If} $option_desktop == 1
|
${If} $option_desktop == 1
|
||||||
|
|||||||
@@ -56,6 +56,13 @@ static bool switchDesktopAndHook(void)
|
|||||||
}
|
}
|
||||||
CloseDesktop(desk);
|
CloseDesktop(desk);
|
||||||
|
|
||||||
|
POINT position;
|
||||||
|
GetCursorPos(&position);
|
||||||
|
|
||||||
|
mouseHook.x = position.x;
|
||||||
|
mouseHook.y = position.y;
|
||||||
|
mouseHook.callback(position.x, position.y);
|
||||||
|
|
||||||
mouseHook.hook = SetWindowsHookEx(WH_MOUSE_LL, mouseHook_hook, NULL, 0);
|
mouseHook.hook = SetWindowsHookEx(WH_MOUSE_LL, mouseHook_hook, NULL, 0);
|
||||||
if (!mouseHook.hook)
|
if (!mouseHook.hook)
|
||||||
{
|
{
|
||||||
@@ -84,11 +91,11 @@ static DWORD WINAPI threadProc(LPVOID lParam) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mouseHook.callback = (MouseHookFn)lParam;
|
||||||
if (!switchDesktopAndHook())
|
if (!switchDesktopAndHook())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
mouseHook.installed = true;
|
mouseHook.installed = true;
|
||||||
mouseHook.callback = (MouseHookFn)lParam;
|
|
||||||
|
|
||||||
HWINEVENTHOOK eventHook = SetWinEventHook(
|
HWINEVENTHOOK eventHook = SetWinEventHook(
|
||||||
EVENT_SYSTEM_DESKTOPSWITCH, EVENT_SYSTEM_DESKTOPSWITCH, NULL,
|
EVENT_SYSTEM_DESKTOPSWITCH, EVENT_SYSTEM_DESKTOPSWITCH, NULL,
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <shellapi.h>
|
#include <shellapi.h>
|
||||||
|
#include <shlwapi.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
#include "interface/platform.h"
|
#include "interface/platform.h"
|
||||||
@@ -34,6 +35,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
|
|
||||||
#define ID_MENU_SHOW_LOG 3000
|
#define ID_MENU_SHOW_LOG 3000
|
||||||
#define ID_MENU_EXIT 3001
|
#define ID_MENU_EXIT 3001
|
||||||
|
#define LOG_NAME "looking-glass-host.txt"
|
||||||
|
|
||||||
struct AppState
|
struct AppState
|
||||||
{
|
{
|
||||||
@@ -44,6 +46,7 @@ struct AppState
|
|||||||
char ** argv;
|
char ** argv;
|
||||||
|
|
||||||
char executable[MAX_PATH + 1];
|
char executable[MAX_PATH + 1];
|
||||||
|
char systemLogDir[MAX_PATH];
|
||||||
HWND messageWnd;
|
HWND messageWnd;
|
||||||
NOTIFYICONDATA iconData;
|
NOTIFYICONDATA iconData;
|
||||||
UINT trayRestartMsg;
|
UINT trayRestartMsg;
|
||||||
@@ -166,6 +169,29 @@ static BOOL WINAPI CtrlHandler(DWORD dwCtrlType)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *getSystemLogDirectory(void)
|
||||||
|
{
|
||||||
|
return app.systemLogDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void populateSystemLogDirectory()
|
||||||
|
{
|
||||||
|
char programData[MAX_PATH];
|
||||||
|
if (GetEnvironmentVariableA("ProgramData", programData, sizeof(programData)) &&
|
||||||
|
PathIsDirectoryA(programData))
|
||||||
|
{
|
||||||
|
if (!PathCombineA(app.systemLogDir, programData, "Looking Glass (host)"))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (!PathIsDirectoryA(app.systemLogDir) && !CreateDirectoryA(app.systemLogDir, NULL))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fail:
|
||||||
|
strcpy(app.systemLogDir, "");
|
||||||
|
}
|
||||||
|
|
||||||
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
|
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
|
||||||
{
|
{
|
||||||
// convert the command line to the standard argc and argv
|
// convert the command line to the standard argc and argv
|
||||||
@@ -180,6 +206,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||||||
LocalFree(wargv);
|
LocalFree(wargv);
|
||||||
|
|
||||||
GetModuleFileName(NULL, app.executable, sizeof(app.executable));
|
GetModuleFileName(NULL, app.executable, sizeof(app.executable));
|
||||||
|
populateSystemLogDirectory();
|
||||||
|
|
||||||
if (HandleService(app.argc, app.argv))
|
if (HandleService(app.argc, app.argv))
|
||||||
return LG_HOST_EXIT_FAILED;
|
return LG_HOST_EXIT_FAILED;
|
||||||
|
|
||||||
@@ -201,11 +229,9 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||||||
int result = 0;
|
int result = 0;
|
||||||
app.hInst = hInstance;
|
app.hInst = hInstance;
|
||||||
|
|
||||||
char tempPath[MAX_PATH+1];
|
char logFilePath[MAX_PATH];
|
||||||
GetTempPathA(sizeof(tempPath), tempPath);
|
if (!PathCombineA(logFilePath, app.systemLogDir, LOG_NAME))
|
||||||
int len = snprintf(NULL, 0, "%slooking-glass-host.txt", tempPath);
|
strcpy(logFilePath, LOG_NAME);
|
||||||
char * logFilePath = malloc(len + 1);
|
|
||||||
sprintf(logFilePath, "%slooking-glass-host.txt", tempPath);
|
|
||||||
|
|
||||||
struct Option options[] =
|
struct Option options[] =
|
||||||
{
|
{
|
||||||
@@ -220,7 +246,6 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||||||
};
|
};
|
||||||
|
|
||||||
option_register(options);
|
option_register(options);
|
||||||
free(logFilePath);
|
|
||||||
|
|
||||||
// setup a handler for ctrl+c
|
// setup a handler for ctrl+c
|
||||||
SetConsoleCtrlHandler(CtrlHandler, TRUE);
|
SetConsoleCtrlHandler(CtrlHandler, TRUE);
|
||||||
|
|||||||
@@ -30,4 +30,5 @@ struct MSG_CALL_FUNCTION
|
|||||||
LPARAM lParam;
|
LPARAM lParam;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const char *getSystemLogDirectory(void);
|
||||||
LRESULT sendAppMessage(UINT Msg, WPARAM wParam, LPARAM lParam);
|
LRESULT sendAppMessage(UINT Msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
#include "interface/platform.h"
|
#include "interface/platform.h"
|
||||||
#include "common/ivshmem.h"
|
#include "common/ivshmem.h"
|
||||||
#include "service.h"
|
#include "service.h"
|
||||||
|
#include "platform.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
@@ -29,6 +30,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include <shlwapi.h>
|
||||||
#include <winsvc.h>
|
#include <winsvc.h>
|
||||||
#include <psapi.h>
|
#include <psapi.h>
|
||||||
#include <sddl.h>
|
#include <sddl.h>
|
||||||
@@ -37,6 +39,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
|
|
||||||
#define SVCNAME "Looking Glass (host)"
|
#define SVCNAME "Looking Glass (host)"
|
||||||
#define SVC_ERROR ((DWORD)0xC0020001L)
|
#define SVC_ERROR ((DWORD)0xC0020001L)
|
||||||
|
#define LOG_NAME "looking-glass-host-service.txt"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Windows 10 provides this API via kernel32.dll as well as advapi32.dll and
|
* Windows 10 provides this API via kernel32.dll as well as advapi32.dll and
|
||||||
@@ -112,12 +115,11 @@ static bool setupAPI(void)
|
|||||||
|
|
||||||
static void setupLogging(void)
|
static void setupLogging(void)
|
||||||
{
|
{
|
||||||
char tempPath[MAX_PATH+1];
|
char logFilePath[MAX_PATH];
|
||||||
GetTempPathA(sizeof(tempPath), tempPath);
|
if (!PathCombineA(logFilePath, getSystemLogDirectory(), LOG_NAME))
|
||||||
int len = snprintf(NULL, 0, "%slooking-glass-host-service.txt", tempPath);
|
strcpy(logFilePath, LOG_NAME);
|
||||||
char * logFilePath = malloc(len + 1);
|
|
||||||
sprintf(logFilePath, "%slooking-glass-host-service.txt", tempPath);
|
|
||||||
service.logFile = fopen(logFilePath, "a+");
|
service.logFile = fopen(logFilePath, "a+");
|
||||||
|
setbuf(service.logFile, NULL);
|
||||||
doLog("Startup\n");
|
doLog("Startup\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -644,7 +646,7 @@ VOID WINAPI SvcMain(DWORD dwArgc, LPTSTR *lpszArgv)
|
|||||||
ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0);
|
ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0);
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
ULONGLONG launchTime;
|
ULONGLONG launchTime = 0ULL;
|
||||||
|
|
||||||
DWORD interactiveSession = WTSGetActiveConsoleSessionId();
|
DWORD interactiveSession = WTSGetActiveConsoleSessionId();
|
||||||
if (interactiveSession != 0 && interactiveSession != 0xFFFFFFFF)
|
if (interactiveSession != 0 && interactiveSession != 0xFFFFFFFF)
|
||||||
|
|||||||
@@ -467,7 +467,7 @@ int app_main(int argc, char * argv[])
|
|||||||
.magic = KVMFR_MAGIC,
|
.magic = KVMFR_MAGIC,
|
||||||
.version = KVMFR_VERSION,
|
.version = KVMFR_VERSION,
|
||||||
};
|
};
|
||||||
strncpy(udata.hostver, BUILD_VERSION, sizeof(udata.hostver));
|
strncpy(udata.hostver, BUILD_VERSION, sizeof(udata.hostver)-1);
|
||||||
|
|
||||||
LGMP_STATUS status;
|
LGMP_STATUS status;
|
||||||
if ((status = lgmpHostInit(shmDev.mem, shmDev.size, &app.lgmp,
|
if ((status = lgmpHostInit(shmDev.mem, shmDev.size, &app.lgmp,
|
||||||
|
|||||||
Submodule repos/PureSpice updated: cc4a17b330...00961e8f43
Reference in New Issue
Block a user