mirror of
https://github.com/gnif/LookingGlass.git
synced 2025-01-11 14:43:57 +00:00
[c-host] general windows fixes
This commit is contained in:
parent
9170b24fee
commit
fc178b40bc
5 changed files with 217 additions and 52 deletions
109
c-host/app.c
109
c-host/app.c
|
@ -51,19 +51,67 @@ static struct app app;
|
||||||
|
|
||||||
static int cursorThread(void * opaque)
|
static int cursorThread(void * opaque)
|
||||||
{
|
{
|
||||||
|
DEBUG_INFO("Cursor thread started");
|
||||||
|
|
||||||
while(app.running)
|
while(app.running)
|
||||||
usleep(10000);
|
usleep(10000);
|
||||||
|
|
||||||
|
DEBUG_INFO("Cursor thread stopped");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int frameThread(void * opaque)
|
static int frameThread(void * opaque)
|
||||||
{
|
{
|
||||||
|
DEBUG_INFO("Frame thread started");
|
||||||
|
|
||||||
while(app.running)
|
while(app.running)
|
||||||
usleep(10000);
|
usleep(10000);
|
||||||
|
|
||||||
|
DEBUG_INFO("Frame thread stopped");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int app_main()
|
bool startThreads()
|
||||||
|
{
|
||||||
|
app.running = true;
|
||||||
|
if (!os_createThread("CursorThread", cursorThread, NULL, &app.cursorThread))
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Failed to create the cursor thread");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!os_createThread("FrameThread", frameThread, NULL, &app.frameThread))
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Failed to create the frame thread");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool stopThreads()
|
||||||
|
{
|
||||||
|
bool ok = true;
|
||||||
|
|
||||||
|
app.running = false;
|
||||||
|
if (app.frameThread && !os_joinThread(app.frameThread, NULL))
|
||||||
|
{
|
||||||
|
DEBUG_WARN("Failed to join the frame thread");
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
app.frameThread = NULL;
|
||||||
|
|
||||||
|
if (app.cursorThread && !os_joinThread(app.cursorThread, NULL))
|
||||||
|
{
|
||||||
|
DEBUG_WARN("Failed to join the cursor thread");
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
app.cursorThread = NULL;
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
int app_main(bool * termSignal)
|
||||||
{
|
{
|
||||||
unsigned int shmemSize = os_shmemSize();
|
unsigned int shmemSize = os_shmemSize();
|
||||||
uint8_t * shmemMap = NULL;
|
uint8_t * shmemMap = NULL;
|
||||||
|
@ -128,32 +176,57 @@ int app_main()
|
||||||
}
|
}
|
||||||
DEBUG_INFO("Capture Size : %u MiB (%u)", maxFrameSize / 1048576, maxFrameSize);
|
DEBUG_INFO("Capture Size : %u MiB (%u)", maxFrameSize / 1048576, maxFrameSize);
|
||||||
|
|
||||||
if (!os_createThread("CursorThread", cursorThread, NULL, &app.cursorThread))
|
DEBUG_INFO("==== [ Capture Start ] ====");
|
||||||
|
|
||||||
|
if (!startThreads())
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to create the cursor thread");
|
|
||||||
exitcode = -1;
|
exitcode = -1;
|
||||||
goto exit;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!os_createThread("FrameThread", frameThread, NULL, &app.frameThread))
|
while(!*termSignal)
|
||||||
|
{
|
||||||
|
bool hasFrameUpdate = false;
|
||||||
|
bool hasPointerUpdate = false;
|
||||||
|
switch(iface->capture(&hasFrameUpdate, &hasPointerUpdate))
|
||||||
|
{
|
||||||
|
case CAPTURE_RESULT_OK:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CAPTURE_RESULT_TIMEOUT:
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case CAPTURE_RESULT_REINIT:
|
||||||
|
DEBUG_INFO("==== [ Capture Reinit ] ====");
|
||||||
|
if (!stopThreads())
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to create the frame thread");
|
|
||||||
exitcode = -1;
|
exitcode = -1;
|
||||||
goto exit_cursor_thread;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
iface->capture();
|
if (true || !iface->deinit() || !iface->init())
|
||||||
iface->capture();
|
{
|
||||||
iface->capture();
|
DEBUG_ERROR("Failed to reinitialize the capture device");
|
||||||
|
exitcode = -1;
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
//finish:
|
if (!startThreads())
|
||||||
app.running = false;
|
{
|
||||||
if (!os_joinThread(app.frameThread, NULL))
|
exitcode = -1;
|
||||||
DEBUG_WARN("Failed to join the cursor thread");
|
goto finish;
|
||||||
exit_cursor_thread:
|
}
|
||||||
app.running = false;
|
break;
|
||||||
if (!os_joinThread(app.cursorThread, NULL))
|
|
||||||
DEBUG_WARN("Failed to join the cursor thread");
|
case CAPTURE_RESULT_ERROR:
|
||||||
|
DEBUG_ERROR("Capture interface reported a fatal error");
|
||||||
|
exitcode = -1;
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
finish:
|
||||||
|
stopThreads();
|
||||||
exit:
|
exit:
|
||||||
iface->deinit();
|
iface->deinit();
|
||||||
iface->free();
|
iface->free();
|
||||||
|
|
|
@ -21,7 +21,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
int app_main();
|
int app_main(bool * termSignal);
|
||||||
|
|
||||||
// these must be implemented for each OS
|
// these must be implemented for each OS
|
||||||
|
|
||||||
|
|
|
@ -39,5 +39,8 @@ struct CaptureInterface
|
||||||
bool (*deinit )();
|
bool (*deinit )();
|
||||||
void (*free )();
|
void (*free )();
|
||||||
unsigned int (*getMaxFrameSize)();
|
unsigned int (*getMaxFrameSize)();
|
||||||
CaptureResult (*capture )();
|
|
||||||
|
CaptureResult (*capture)(
|
||||||
|
bool * hasFrameUpdate,
|
||||||
|
bool * hasPointerUpdate);
|
||||||
};
|
};
|
|
@ -41,7 +41,6 @@ struct iface
|
||||||
IDXGIOutputDuplication * dup;
|
IDXGIOutputDuplication * dup;
|
||||||
ID3D11Texture2D * texture;
|
ID3D11Texture2D * texture;
|
||||||
bool hasFrame;
|
bool hasFrame;
|
||||||
bool retryAcquire;
|
|
||||||
|
|
||||||
unsigned int width;
|
unsigned int width;
|
||||||
unsigned int height;
|
unsigned int height;
|
||||||
|
@ -93,7 +92,7 @@ static bool dxgi_init()
|
||||||
fn = (User32_SetProcessDpiAwarenessContext)GetProcAddress(user32, "SetProcessDpiAwarenessContext");
|
fn = (User32_SetProcessDpiAwarenessContext)GetProcAddress(user32, "SetProcessDpiAwarenessContext");
|
||||||
if (fn)
|
if (fn)
|
||||||
fn(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
|
fn(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
|
||||||
CloseHandle(user32);
|
FreeLibrary(user32);
|
||||||
dpiDone = true;
|
dpiDone = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,6 +259,10 @@ static bool dxgi_init()
|
||||||
if (SUCCEEDED(status))
|
if (SUCCEEDED(status))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// if access is denied we just keep trying until it isn't
|
||||||
|
if (status == E_ACCESSDENIED)
|
||||||
|
--i;
|
||||||
|
|
||||||
Sleep(200);
|
Sleep(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,7 +395,7 @@ static unsigned int dxgi_getMaxFrameSize()
|
||||||
return this->height * this->pitch;
|
return this->height * this->pitch;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CaptureResult dxgi_capture()
|
static CaptureResult dxgi_capture(bool * hasFrameUpdate, bool * hasPointerUpdate)
|
||||||
{
|
{
|
||||||
assert(this);
|
assert(this);
|
||||||
assert(this->initialized);
|
assert(this->initialized);
|
||||||
|
@ -418,14 +421,6 @@ static CaptureResult dxgi_capture()
|
||||||
|
|
||||||
case WAIT_ABANDONED:
|
case WAIT_ABANDONED:
|
||||||
case DXGI_ERROR_ACCESS_LOST:
|
case DXGI_ERROR_ACCESS_LOST:
|
||||||
if (this->retryAcquire)
|
|
||||||
{
|
|
||||||
DEBUG_WINERROR("Unable to acquire next frame, giving up", status);
|
|
||||||
this->retryAcquire = false;
|
|
||||||
return CAPTURE_RESULT_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->retryAcquire = true;
|
|
||||||
return CAPTURE_RESULT_REINIT;
|
return CAPTURE_RESULT_REINIT;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -444,6 +439,11 @@ static CaptureResult dxgi_capture()
|
||||||
ID3D11DeviceContext_CopyResource(this->deviceContext,
|
ID3D11DeviceContext_CopyResource(this->deviceContext,
|
||||||
(ID3D11Resource *)this->texture, (ID3D11Resource *)src);
|
(ID3D11Resource *)this->texture, (ID3D11Resource *)src);
|
||||||
|
|
||||||
|
*hasFrameUpdate = true;
|
||||||
|
|
||||||
|
if (frameInfo.PointerShapeBufferSize > 0)
|
||||||
|
*hasPointerUpdate = true;
|
||||||
|
|
||||||
return CAPTURE_RESULT_OK;
|
return CAPTURE_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -465,7 +465,10 @@ static CaptureResult dxgi_releaseFrame()
|
||||||
|
|
||||||
case WAIT_ABANDONED:
|
case WAIT_ABANDONED:
|
||||||
case DXGI_ERROR_ACCESS_LOST:
|
case DXGI_ERROR_ACCESS_LOST:
|
||||||
|
{
|
||||||
|
this->hasFrame = false;
|
||||||
return CAPTURE_RESULT_REINIT;
|
return CAPTURE_RESULT_REINIT;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DEBUG_WINERROR("ReleaseFrame failed", status);
|
DEBUG_WINERROR("ReleaseFrame failed", status);
|
||||||
|
|
|
@ -28,6 +28,8 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
static HANDLE shmemHandle = INVALID_HANDLE_VALUE;
|
static HANDLE shmemHandle = INVALID_HANDLE_VALUE;
|
||||||
static bool shmemOwned = false;
|
static bool shmemOwned = false;
|
||||||
static IVSHMEM_MMAP shmemMap = {0};
|
static IVSHMEM_MMAP shmemMap = {0};
|
||||||
|
static bool termSignal = false;
|
||||||
|
static HWND messageWnd;
|
||||||
|
|
||||||
struct osThreadHandle
|
struct osThreadHandle
|
||||||
{
|
{
|
||||||
|
@ -39,12 +41,54 @@ struct osThreadHandle
|
||||||
int resultCode;
|
int resultCode;
|
||||||
};
|
};
|
||||||
|
|
||||||
int WINAPI WinMain(HINSTANCE hInstnace, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
|
LRESULT CALLBACK DummyWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
|
switch(msg)
|
||||||
|
{
|
||||||
|
case WM_CLOSE:
|
||||||
|
DestroyWindow(hwnd);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_DESTROY:
|
||||||
|
PostQuitMessage(0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return DefWindowProc(hwnd, msg, wParam, lParam);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int appThread(void * opaque)
|
||||||
|
{
|
||||||
|
int result = app_main(&termSignal);
|
||||||
|
SendMessage(messageWnd, WM_CLOSE, 0, 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
HDEVINFO deviceInfoSet;
|
HDEVINFO deviceInfoSet;
|
||||||
PSP_DEVICE_INTERFACE_DETAIL_DATA infData = NULL;
|
PSP_DEVICE_INTERFACE_DETAIL_DATA infData = NULL;
|
||||||
SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
|
SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// redirect stderr to a file
|
||||||
|
{
|
||||||
|
char tempPath[MAX_PATH+1];
|
||||||
|
GetTempPathA(sizeof(tempPath), tempPath);
|
||||||
|
int len = snprintf(NULL, 0, "%slooking-glass-host.txt", tempPath);
|
||||||
|
char * path = malloc(len + 1);
|
||||||
|
sprintf(path, "%slooking-glass-host.txt", tempPath);
|
||||||
|
freopen(path, "a", stderr);
|
||||||
|
free(path);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// always flush stderr
|
||||||
|
setbuf(stderr, NULL);
|
||||||
|
|
||||||
deviceInfoSet = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT | DIGCF_ALLCLASSES | DIGCF_DEVICEINTERFACE);
|
deviceInfoSet = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT | DIGCF_ALLCLASSES | DIGCF_DEVICEINTERFACE);
|
||||||
memset(&deviceInterfaceData, 0, sizeof(SP_DEVICE_INTERFACE_DATA));
|
memset(&deviceInterfaceData, 0, sizeof(SP_DEVICE_INTERFACE_DATA));
|
||||||
deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
|
deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
|
||||||
|
@ -55,11 +99,13 @@ int WINAPI WinMain(HINSTANCE hInstnace, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||||
if (error == ERROR_NO_MORE_ITEMS)
|
if (error == ERROR_NO_MORE_ITEMS)
|
||||||
{
|
{
|
||||||
DEBUG_WINERROR("Unable to enumerate the device, is it attached?", error);
|
DEBUG_WINERROR("Unable to enumerate the device, is it attached?", error);
|
||||||
return -1;
|
result = -1;
|
||||||
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_WINERROR("SetupDiEnumDeviceInterfaces failed", error);
|
DEBUG_WINERROR("SetupDiEnumDeviceInterfaces failed", error);
|
||||||
return -1;
|
result = -1;
|
||||||
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD reqSize = 0;
|
DWORD reqSize = 0;
|
||||||
|
@ -67,7 +113,8 @@ int WINAPI WinMain(HINSTANCE hInstnace, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||||
if (!reqSize)
|
if (!reqSize)
|
||||||
{
|
{
|
||||||
DEBUG_WINERROR("SetupDiGetDeviceInterfaceDetail", GetLastError());
|
DEBUG_WINERROR("SetupDiGetDeviceInterfaceDetail", GetLastError());
|
||||||
return -1;
|
result = -1;
|
||||||
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
infData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)calloc(reqSize, 1);
|
infData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)calloc(reqSize, 1);
|
||||||
|
@ -76,7 +123,8 @@ int WINAPI WinMain(HINSTANCE hInstnace, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||||
{
|
{
|
||||||
free(infData);
|
free(infData);
|
||||||
DEBUG_WINERROR("SetupDiGetDeviceInterfaceDetail", GetLastError());
|
DEBUG_WINERROR("SetupDiGetDeviceInterfaceDetail", GetLastError());
|
||||||
return -1;
|
result = -1;
|
||||||
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
shmemHandle = CreateFile(infData->DevicePath, 0, 0, NULL, OPEN_EXISTING, 0, 0);
|
shmemHandle = CreateFile(infData->DevicePath, 0, 0, NULL, OPEN_EXISTING, 0, 0);
|
||||||
|
@ -85,28 +133,66 @@ int WINAPI WinMain(HINSTANCE hInstnace, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||||
SetupDiDestroyDeviceInfoList(deviceInfoSet);
|
SetupDiDestroyDeviceInfoList(deviceInfoSet);
|
||||||
free(infData);
|
free(infData);
|
||||||
DEBUG_WINERROR("CreateFile returned INVALID_HANDLE_VALUE", GetLastError());
|
DEBUG_WINERROR("CreateFile returned INVALID_HANDLE_VALUE", GetLastError());
|
||||||
return -1;
|
result = -1;
|
||||||
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(infData);
|
free(infData);
|
||||||
SetupDiDestroyDeviceInfoList(deviceInfoSet);
|
SetupDiDestroyDeviceInfoList(deviceInfoSet);
|
||||||
|
|
||||||
int result = app_main();
|
// create a message window so that our message pump works
|
||||||
|
WNDCLASSEX wx = {};
|
||||||
os_shmemUnmap();
|
wx.cbSize = sizeof(WNDCLASSEX);
|
||||||
CloseHandle(shmemHandle);
|
wx.lpfnWndProc = DummyWndProc;
|
||||||
|
wx.hInstance = hInstance;
|
||||||
if (result != 0)
|
wx.lpszClassName = "DUMMY_CLASS";
|
||||||
|
if (!RegisterClassEx(&wx))
|
||||||
{
|
{
|
||||||
MessageBoxA(
|
DEBUG_ERROR("Failed to register message window class");
|
||||||
NULL,
|
result = -1;
|
||||||
"The Looking Glass host has terminated due to an error.\r\n"
|
goto finish_shmem;
|
||||||
"\r\n"
|
}
|
||||||
"For more information run the application in a command prompt.",
|
messageWnd = CreateWindowEx(0, "DUMMY_CLASS", "DUMMY_NAME", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
|
||||||
"Looking Glass Host",
|
|
||||||
MB_ICONERROR);
|
osThreadHandle * thread;
|
||||||
|
if (!os_createThread("appThread", appThread, NULL, &thread))
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Failed to create the main application thread");
|
||||||
|
result = -1;
|
||||||
|
goto finish_shmem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while(!termSignal)
|
||||||
|
{
|
||||||
|
MSG msg;
|
||||||
|
BOOL bRet = GetMessage(&msg, NULL, 0, 0);
|
||||||
|
if (bRet > 0)
|
||||||
|
{
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
}
|
||||||
|
else if (bRet < 0)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Unknown error from GetMessage");
|
||||||
|
result = -1;
|
||||||
|
goto shutdown;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_INFO("Platform shutdown");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
shutdown:
|
||||||
|
termSignal = true;
|
||||||
|
if (!os_joinThread(thread, &result))
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Failed to join the main application thread");
|
||||||
|
result = -1;
|
||||||
|
}
|
||||||
|
finish_shmem:
|
||||||
|
os_shmemUnmap();
|
||||||
|
CloseHandle(shmemHandle);
|
||||||
|
finish:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue