diff --git a/c-host/app.c b/c-host/app.c index 206c148d..38194fcc 100644 --- a/c-host/app.c +++ b/c-host/app.c @@ -49,31 +49,31 @@ struct app bool running; bool reinit; - osEventHandle * updateEvent; osThreadHandle * pointerThread; - osEventHandle * pointerEvent; osThreadHandle * frameThread; - osEventHandle * frameEvent; }; static struct app app; static int pointerThread(void * opaque) { - DEBUG_INFO("Cursor thread started"); + DEBUG_INFO("Pointer thread started"); - while(os_waitEvent(app.pointerEvent) && app.running) - { #if 0 + while(app.running) + { CapturePointer pointer; pointer->data = app.pointerData; if (!app.iface->getPointer(&pointer)) + { DEBUG_ERROR("Failed to get the pointer"); -#endif - os_signalEvent(app.updateEvent); + app.reinit = true; + break; + } } +#endif - DEBUG_INFO("Cursor thread stopped"); + DEBUG_INFO("Pointer thread stopped"); return 0; } @@ -84,7 +84,7 @@ static int frameThread(void * opaque) int frameIndex = 0; volatile KVMFRFrame * fi = &(app.shmHeader->frame); - while(os_waitEvent(app.frameEvent) && app.running) + while(app.running) { CaptureFrame frame; frame.data = app.frame[frameIndex]; @@ -92,12 +92,9 @@ static int frameThread(void * opaque) { DEBUG_ERROR("Failed to get the frame"); app.reinit = true; - os_signalEvent(app.updateEvent); break; } - os_signalEvent(app.updateEvent); - // wait for the client to finish with the previous frame while(fi->flags & KVMFR_FRAME_FLAG_UPDATE && app.running) { @@ -155,8 +152,6 @@ bool stopThreads() bool ok = true; app.running = false; - os_signalEvent(app.frameEvent ); - os_signalEvent(app.pointerEvent); if (app.frameThread && !os_joinThread(app.frameThread, NULL)) { @@ -187,9 +182,6 @@ static bool captureStart() } DEBUG_INFO("Capture Size : %u MiB (%u)", maxFrameSize / 1048576, maxFrameSize); - // start signalled - os_signalEvent(app.updateEvent); - DEBUG_INFO("==== [ Capture Start ] ===="); return startThreads(); } @@ -270,30 +262,7 @@ int app_main() goto fail; } - app.iface = iface; - app.frameEvent = os_createEvent(true); - if (!app.frameEvent) - { - DEBUG_ERROR("Failed to create the frame event"); - exitcode = -1; - goto exit; - } - - app.updateEvent = os_createEvent(false); - if (!app.updateEvent) - { - DEBUG_ERROR("Failed to create the update event"); - exitcode = -1; - goto exit; - } - - app.pointerEvent = os_createEvent(true); - if (!app.pointerEvent) - { - DEBUG_ERROR("Failed to create the pointer event"); - exitcode = -1; - goto exit; - } + app.iface = iface; // initialize the shared memory headers memcpy(app.shmHeader->magic, KVMFR_HEADER_MAGIC, sizeof(KVMFR_HEADER_MAGIC)); @@ -310,19 +279,12 @@ int app_main() goto exit; } - // start signalled - os_signalEvent(app.updateEvent); - volatile char * flags = (volatile char *)&(app.shmHeader->flags); while(app.running) { INTERLOCKED_AND8(flags, ~(KVMFR_HEADER_FLAG_RESTART)); - // wait for one of the threads to flag an update - if (!os_waitEvent(app.updateEvent) || !app.running) - break; - if (app.reinit && !captureRestart()) { exitcode = -1; @@ -333,7 +295,6 @@ int app_main() bool frameUpdate = false; bool pointerUpdate = false; -retry_capture: switch(iface->capture(&frameUpdate, &pointerUpdate)) { case CAPTURE_RESULT_OK: @@ -355,39 +316,12 @@ retry_capture: exitcode = -1; goto finish; } - - if (!frameUpdate && !pointerUpdate) - goto retry_capture; - - os_resetEvent(app.updateEvent); - if (frameUpdate && !os_signalEvent(app.frameEvent)) - { - DEBUG_ERROR("Failed to signal the frame thread"); - exitcode = -1; - goto finish; - } - - if (pointerUpdate && !os_signalEvent(app.pointerEvent)) - { - DEBUG_ERROR("Failed to signal the pointer thread"); - exitcode = -1; - goto finish; - } } finish: stopThreads(); exit: - if (app.pointerEvent) - os_freeEvent(app.pointerEvent); - - if (app.frameEvent) - os_freeEvent(app.frameEvent); - - if (app.updateEvent) - os_freeEvent(app.updateEvent); - iface->deinit(); iface->free(); fail: @@ -398,5 +332,4 @@ fail: void app_quit() { app.running = false; - os_signalEvent(app.updateEvent); } \ No newline at end of file diff --git a/c-host/windows/capture/dxgi.c b/c-host/windows/capture/dxgi.c index f4d49b3b..a03a4b58 100644 --- a/c-host/windows/capture/dxgi.c +++ b/c-host/windows/capture/dxgi.c @@ -32,17 +32,21 @@ Place, Suite 330, Boston, MA 02111-1307 USA // locals struct iface { - bool initialized; - IDXGIFactory1 * factory; - IDXGIAdapter1 * adapter; - IDXGIOutput * output; - ID3D11Device * device; - ID3D11DeviceContext * deviceContext; - D3D_FEATURE_LEVEL featureLevel; - IDXGIOutputDuplication * dup; - ID3D11Texture2D * texture; - bool needsRelease; - osEventHandle * copyEvent; + bool initialized; + IDXGIFactory1 * factory; + IDXGIAdapter1 * adapter; + IDXGIOutput * output; + ID3D11Device * device; + ID3D11DeviceContext * deviceContext; + D3D_FEATURE_LEVEL featureLevel; + IDXGIOutputDuplication * dup; + ID3D11Texture2D * texture; + D3D11_MAPPED_SUBRESOURCE mapping; + bool needsRelease; + bool needsUnmap; + osEventHandle * copyEvent; + osEventHandle * frameEvent; + osEventHandle * pointerEvent; unsigned int width; unsigned int height; @@ -84,6 +88,25 @@ static bool dxgi_create() return false; } + this->frameEvent = os_createEvent(true); + if (!this->frameEvent) + { + DEBUG_ERROR("failed to create the frame event"); + os_freeEvent(this->copyEvent); + free(this); + return false; + } + + this->pointerEvent = os_createEvent(true); + if (!this->pointerEvent) + { + DEBUG_ERROR("failed to create the pointer event"); + os_freeEvent(this->copyEvent ); + os_freeEvent(this->frameEvent); + free(this); + return false; + } + return true; } @@ -364,6 +387,12 @@ static bool dxgi_deinit() { assert(this); + if (this->needsUnmap) + { + ID3D11DeviceContext_Unmap(this->deviceContext, (ID3D11Resource*)this->texture, 0); + this->needsUnmap = false; + } + if (this->texture) { ID3D11Texture2D_Release(this->texture); @@ -424,7 +453,9 @@ static void dxgi_free() if (this->initialized) dxgi_deinit(); - os_freeEvent(this->copyEvent); + os_freeEvent(this->copyEvent ); + os_freeEvent(this->frameEvent ); + os_freeEvent(this->pointerEvent); free(this); this = NULL; @@ -482,18 +513,40 @@ static CaptureResult dxgi_capture(bool * hasFrameUpdate, bool * hasPointerUpdate return CAPTURE_RESULT_ERROR; } - // wait for the prior copy to finish in getFrame + // wait for the prior copy to finish in getFrame and unmap os_waitEvent(this->copyEvent); + if (this->needsUnmap) + { + ID3D11DeviceContext_Unmap(this->deviceContext, (ID3D11Resource*)this->texture, 0); + this->needsUnmap = false; + } + // issue the copy from GPU to CPU RAM ID3D11DeviceContext_CopyResource(this->deviceContext, (ID3D11Resource *)this->texture, (ID3D11Resource *)src); + // map the resource (this must be done here as ID3D11DeviceContext is not thread safe) + status = ID3D11DeviceContext_Map(this->deviceContext, (ID3D11Resource*)this->texture, 0, D3D11_MAP_READ, 0, &this->mapping); + if (FAILED(status)) + { + DEBUG_WINERROR("Failed to map the texture", status); + IDXGIResource_Release(res); + return CAPTURE_RESULT_ERROR; + } + this->needsUnmap = true; + + // signal that a frame is available + os_signalEvent(this->frameEvent); + ID3D11Texture2D_Release(src); *hasFrameUpdate = true; } if (frameInfo.PointerShapeBufferSize > 0) + { + os_signalEvent(this->pointerEvent); *hasPointerUpdate = true; + } IDXGIResource_Release(res); return CAPTURE_RESULT_OK; @@ -504,24 +557,21 @@ static bool dxgi_getFrame(CaptureFrame * frame) assert(this); assert(this->initialized); + if (!os_waitEvent(this->frameEvent)) + { + DEBUG_ERROR("Failed to wait on the frame event"); + return false; + } + frame->width = this->width; frame->height = this->height; frame->pitch = this->pitch; frame->stride = this->stride; frame->format = this->format; - HRESULT status; - 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); - return false; - } - memcpy(frame->data, mapping.pData, this->pitch * this->height); + memcpy(frame->data, this->mapping.pData, this->pitch * this->height); - ID3D11DeviceContext_Unmap(this->deviceContext, (ID3D11Resource*)this->texture, 0); os_signalEvent(this->copyEvent); return true; }