[c-host] general windows fixes

This commit is contained in:
Geoffrey McRae 2019-03-01 15:45:46 +11:00
parent 9170b24fee
commit fc178b40bc
5 changed files with 217 additions and 52 deletions

View file

@ -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();

View file

@ -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

View file

@ -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);
}; };

View file

@ -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);

View file

@ -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;
} }