diff --git a/c-host/Makefile b/c-host/Makefile index 0799f5bf..d780c2e3 100644 --- a/c-host/Makefile +++ b/c-host/Makefile @@ -13,7 +13,7 @@ OBJS = app.o # if windows ifdef OS CC = gcc.exe - LDFLAGS = -L./windows/dll + LDFLAGS = -L./windows/dll -mwindows LIBS += -lsetupapi OBJS += windows/platform.o OBJS += windows/windebug.o diff --git a/c-host/app.c b/c-host/app.c index 27c7b786..909f0a34 100644 --- a/c-host/app.c +++ b/c-host/app.c @@ -20,20 +20,61 @@ Place, Suite 330, Boston, MA 02111-1307 USA #include "app.h" #include +#include #include "debug.h" #include "capture/interfaces.h" +#include "KVMFR.h" + +#define ALIGN_DN(x) ((uintptr_t)(x) & ~0x7F) +#define ALIGN_UP(x) ALIGN_DN(x + 0x7F) +#define MAX_FRAMES 2 + +struct app +{ + KVMFRHeader * shmHeader; + uint8_t * cursorData; + unsigned int cursorDataSize; + unsigned int cursorOffset; + + uint8_t * frames; + unsigned int frameSize; + uint8_t * frame[MAX_FRAMES]; + unsigned int frameOffset[MAX_FRAMES]; +}; + +static struct app app; int app_main() { unsigned int shmemSize = os_shmemSize(); - void * shmemMap = NULL; + uint8_t * shmemMap = NULL; + int exitcode = 0; DEBUG_INFO("IVSHMEM Size : %u MiB", shmemSize / 1048576); - if (!os_shmemMmap(&shmemMap) || !shmemMap) + if (!os_shmemMmap((void **)&shmemMap) || !shmemMap) { DEBUG_ERROR("Failed to map the shared memory"); return -1; } + DEBUG_INFO("IVSHMEM Address : 0x%" PRIXPTR, (uintptr_t)shmemMap); + + app.shmHeader = (KVMFRHeader *)shmemMap; + app.cursorData = (uint8_t *)ALIGN_UP(shmemMap + sizeof(KVMFRHeader)); + app.cursorDataSize = 1048576; // 1MB fixed for cursor size, should be more then enough + app.cursorOffset = app.cursorData - shmemMap; + app.frames = (uint8_t *)ALIGN_UP(app.cursorData + app.cursorDataSize); + app.frameSize = ALIGN_DN((shmemSize - (app.frames - shmemMap)) / MAX_FRAMES); + + DEBUG_INFO("Max Cursor Size : %u MiB" , app.cursorDataSize / 1048576); + DEBUG_INFO("Max Frame Size : %u MiB" , app.frameSize / 1048576); + DEBUG_INFO("Cursor : 0x%" PRIXPTR " (0x%08x)", (uintptr_t)app.cursorData, app.cursorOffset); + + for (int i = 0; i < MAX_FRAMES; ++i) + { + app.frame [i] = app.frames + i * app.frameSize; + app.frameOffset[i] = app.frame[i] - shmemMap; + DEBUG_INFO("Frame %d : 0x%" PRIXPTR " (0x%08x)", i, (uintptr_t)app.frame[i], app.frameOffset[i]); + } struct CaptureInterface * iface = NULL; for(int i = 0; CaptureInterfaces[i]; ++i) @@ -53,18 +94,29 @@ int app_main() if (!iface) { DEBUG_ERROR("Failed to find a supported capture interface"); - return -1; + exitcode = -1; + goto fail; } DEBUG_INFO("Using : %s", iface->getName()); + const unsigned int maxFrameSize = iface->getMaxFrameSize(); + if (maxFrameSize > app.frameSize) + { + DEBUG_ERROR("Maximum frame size of %d bytes excceds maximum space available", maxFrameSize); + exitcode = -1; + goto exit; + } + DEBUG_INFO("Capture Size : %u MiB (%u)", maxFrameSize / 1048576, maxFrameSize); + iface->capture(); iface->capture(); iface->capture(); +exit: iface->deinit(); iface->free(); - +fail: os_shmemUnmap(); - return 0; + return exitcode; } \ No newline at end of file diff --git a/c-host/capture/interface.h b/c-host/capture/interface.h index 9dc6b11e..64e39ea6 100644 --- a/c-host/capture/interface.h +++ b/c-host/capture/interface.h @@ -33,10 +33,11 @@ CaptureResult; struct CaptureInterface { - const char * (*getName)(); - bool (*create )(); - bool (*init )(); - bool (*deinit )(); - void (*free )(); - CaptureResult (*capture)(); + const char * (*getName )(); + bool (*create )(); + bool (*init )(); + bool (*deinit )(); + void (*free )(); + unsigned int (*getMaxFrameSize)(); + CaptureResult (*capture )(); }; \ No newline at end of file diff --git a/c-host/windows/capture/dxgi.c b/c-host/windows/capture/dxgi.c index d887db06..99076083 100644 --- a/c-host/windows/capture/dxgi.c +++ b/c-host/windows/capture/dxgi.c @@ -45,6 +45,8 @@ struct iface unsigned int width; unsigned int height; + unsigned int pitch; + unsigned int stride; }; static bool dpiDone = false; @@ -184,9 +186,9 @@ static bool dxgi_init() DEBUG_INFO("Device Descripion: %ls" , adapterDesc.Description); DEBUG_INFO("Device Vendor ID : 0x%x" , adapterDesc.VendorId); DEBUG_INFO("Device Device ID : 0x%x" , adapterDesc.DeviceId); - DEBUG_INFO("Device Video Mem : %u MB", (unsigned)(adapterDesc.DedicatedVideoMemory / 1048576)); - DEBUG_INFO("Device Sys Mem : %u MB", (unsigned)(adapterDesc.DedicatedSystemMemory / 1048576)); - DEBUG_INFO("Shared Sys Mem : %u MB", (unsigned)(adapterDesc.SharedSystemMemory / 1048576)); + DEBUG_INFO("Device Video Mem : %u MiB", (unsigned)(adapterDesc.DedicatedVideoMemory / 1048576)); + DEBUG_INFO("Device Sys Mem : %u MiB", (unsigned)(adapterDesc.DedicatedSystemMemory / 1048576)); + DEBUG_INFO("Shared Sys Mem : %u MiB", (unsigned)(adapterDesc.SharedSystemMemory / 1048576)); DEBUG_INFO("Feature Level : 0x%x", this->featureLevel); DEBUG_INFO("Capture Size : %u x %u", this->width, this->height); @@ -294,6 +296,18 @@ static bool dxgi_init() goto fail_release_output; } + // map the texture simply to get the pitch and stride + D3D11_MAPPED_SUBRESOURCE mapping; + status = ID3D11DeviceContext_Map(this->deviceContext, (ID3D11Resource *)this->texture, 0, D3D11_MAP_READ, 0, &mapping); + if (FAILED(status)) + { + DEBUG_WINERROR("Failed to map the texture", status); + goto fail_release_output; + } + this->pitch = mapping.RowPitch; + this->stride = mapping.RowPitch / 4; + ID3D11DeviceContext_Unmap(this->deviceContext, (ID3D11Resource *)this->texture, 0); + this->factory = factory; this->adapter = adapter; this->output = output; @@ -370,6 +384,14 @@ static void dxgi_free() this = NULL; } +static unsigned int dxgi_getMaxFrameSize() +{ + assert(this); + assert(this->initialized); + + return this->height * this->pitch; +} + static CaptureResult dxgi_capture() { assert(this); @@ -456,10 +478,11 @@ static CaptureResult dxgi_releaseFrame() struct CaptureInterface Capture_DXGI = { - .getName = dxgi_getName, - .create = dxgi_create, - .init = dxgi_init, - .deinit = dxgi_deinit, - .free = dxgi_free, - .capture = dxgi_capture + .getName = dxgi_getName, + .create = dxgi_create, + .init = dxgi_init, + .deinit = dxgi_deinit, + .free = dxgi_free, + .getMaxFrameSize = dxgi_getMaxFrameSize, + .capture = dxgi_capture }; \ No newline at end of file diff --git a/c-host/windows/platform.c b/c-host/windows/platform.c index a9ac6dd6..a94393e1 100644 --- a/c-host/windows/platform.c +++ b/c-host/windows/platform.c @@ -85,6 +85,18 @@ int WINAPI WinMain(HINSTANCE hInstnace, HINSTANCE hPrevInstance, LPSTR lpCmdLine os_shmemUnmap(); CloseHandle(shmemHandle); + + if (result != 0) + { + MessageBoxA( + NULL, + "The Looking Glass host has terminated due to an error.\r\n" + "\r\n" + "For more information run the application in a command prompt.", + "Looking Glass Host", + MB_ICONERROR); + } + return result; }