[c-host] rework events

This commit is contained in:
Geoffrey McRae 2019-03-04 15:03:11 +11:00
parent a8b018d5da
commit 6f545483c9
2 changed files with 84 additions and 101 deletions

View file

@ -49,31 +49,31 @@ struct app
bool running; bool running;
bool reinit; bool reinit;
osEventHandle * updateEvent;
osThreadHandle * pointerThread; osThreadHandle * pointerThread;
osEventHandle * pointerEvent;
osThreadHandle * frameThread; osThreadHandle * frameThread;
osEventHandle * frameEvent;
}; };
static struct app app; static struct app app;
static int pointerThread(void * opaque) static int pointerThread(void * opaque)
{ {
DEBUG_INFO("Cursor thread started"); DEBUG_INFO("Pointer thread started");
while(os_waitEvent(app.pointerEvent) && app.running)
{
#if 0 #if 0
while(app.running)
{
CapturePointer pointer; CapturePointer pointer;
pointer->data = app.pointerData; pointer->data = app.pointerData;
if (!app.iface->getPointer(&pointer)) if (!app.iface->getPointer(&pointer))
{
DEBUG_ERROR("Failed to get the pointer"); DEBUG_ERROR("Failed to get the pointer");
#endif app.reinit = true;
os_signalEvent(app.updateEvent); break;
} }
}
#endif
DEBUG_INFO("Cursor thread stopped"); DEBUG_INFO("Pointer thread stopped");
return 0; return 0;
} }
@ -84,7 +84,7 @@ static int frameThread(void * opaque)
int frameIndex = 0; int frameIndex = 0;
volatile KVMFRFrame * fi = &(app.shmHeader->frame); volatile KVMFRFrame * fi = &(app.shmHeader->frame);
while(os_waitEvent(app.frameEvent) && app.running) while(app.running)
{ {
CaptureFrame frame; CaptureFrame frame;
frame.data = app.frame[frameIndex]; frame.data = app.frame[frameIndex];
@ -92,12 +92,9 @@ static int frameThread(void * opaque)
{ {
DEBUG_ERROR("Failed to get the frame"); DEBUG_ERROR("Failed to get the frame");
app.reinit = true; app.reinit = true;
os_signalEvent(app.updateEvent);
break; break;
} }
os_signalEvent(app.updateEvent);
// wait for the client to finish with the previous frame // wait for the client to finish with the previous frame
while(fi->flags & KVMFR_FRAME_FLAG_UPDATE && app.running) while(fi->flags & KVMFR_FRAME_FLAG_UPDATE && app.running)
{ {
@ -155,8 +152,6 @@ bool stopThreads()
bool ok = true; bool ok = true;
app.running = false; app.running = false;
os_signalEvent(app.frameEvent );
os_signalEvent(app.pointerEvent);
if (app.frameThread && !os_joinThread(app.frameThread, NULL)) 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); DEBUG_INFO("Capture Size : %u MiB (%u)", maxFrameSize / 1048576, maxFrameSize);
// start signalled
os_signalEvent(app.updateEvent);
DEBUG_INFO("==== [ Capture Start ] ===="); DEBUG_INFO("==== [ Capture Start ] ====");
return startThreads(); return startThreads();
} }
@ -271,29 +263,6 @@ int app_main()
} }
app.iface = iface; 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;
}
// initialize the shared memory headers // initialize the shared memory headers
memcpy(app.shmHeader->magic, KVMFR_HEADER_MAGIC, sizeof(KVMFR_HEADER_MAGIC)); memcpy(app.shmHeader->magic, KVMFR_HEADER_MAGIC, sizeof(KVMFR_HEADER_MAGIC));
@ -310,19 +279,12 @@ int app_main()
goto exit; goto exit;
} }
// start signalled
os_signalEvent(app.updateEvent);
volatile char * flags = (volatile char *)&(app.shmHeader->flags); volatile char * flags = (volatile char *)&(app.shmHeader->flags);
while(app.running) while(app.running)
{ {
INTERLOCKED_AND8(flags, ~(KVMFR_HEADER_FLAG_RESTART)); 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()) if (app.reinit && !captureRestart())
{ {
exitcode = -1; exitcode = -1;
@ -333,7 +295,6 @@ int app_main()
bool frameUpdate = false; bool frameUpdate = false;
bool pointerUpdate = false; bool pointerUpdate = false;
retry_capture:
switch(iface->capture(&frameUpdate, &pointerUpdate)) switch(iface->capture(&frameUpdate, &pointerUpdate))
{ {
case CAPTURE_RESULT_OK: case CAPTURE_RESULT_OK:
@ -355,39 +316,12 @@ retry_capture:
exitcode = -1; exitcode = -1;
goto finish; 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: finish:
stopThreads(); stopThreads();
exit: 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->deinit();
iface->free(); iface->free();
fail: fail:
@ -398,5 +332,4 @@ fail:
void app_quit() void app_quit()
{ {
app.running = false; app.running = false;
os_signalEvent(app.updateEvent);
} }

View file

@ -41,8 +41,12 @@ struct iface
D3D_FEATURE_LEVEL featureLevel; D3D_FEATURE_LEVEL featureLevel;
IDXGIOutputDuplication * dup; IDXGIOutputDuplication * dup;
ID3D11Texture2D * texture; ID3D11Texture2D * texture;
D3D11_MAPPED_SUBRESOURCE mapping;
bool needsRelease; bool needsRelease;
bool needsUnmap;
osEventHandle * copyEvent; osEventHandle * copyEvent;
osEventHandle * frameEvent;
osEventHandle * pointerEvent;
unsigned int width; unsigned int width;
unsigned int height; unsigned int height;
@ -84,6 +88,25 @@ static bool dxgi_create()
return false; 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; return true;
} }
@ -364,6 +387,12 @@ static bool dxgi_deinit()
{ {
assert(this); assert(this);
if (this->needsUnmap)
{
ID3D11DeviceContext_Unmap(this->deviceContext, (ID3D11Resource*)this->texture, 0);
this->needsUnmap = false;
}
if (this->texture) if (this->texture)
{ {
ID3D11Texture2D_Release(this->texture); ID3D11Texture2D_Release(this->texture);
@ -424,7 +453,9 @@ static void dxgi_free()
if (this->initialized) if (this->initialized)
dxgi_deinit(); dxgi_deinit();
os_freeEvent(this->copyEvent); os_freeEvent(this->copyEvent );
os_freeEvent(this->frameEvent );
os_freeEvent(this->pointerEvent);
free(this); free(this);
this = NULL; this = NULL;
@ -482,18 +513,40 @@ static CaptureResult dxgi_capture(bool * hasFrameUpdate, bool * hasPointerUpdate
return CAPTURE_RESULT_ERROR; 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); 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, ID3D11DeviceContext_CopyResource(this->deviceContext,
(ID3D11Resource *)this->texture, (ID3D11Resource *)src); (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); ID3D11Texture2D_Release(src);
*hasFrameUpdate = true; *hasFrameUpdate = true;
} }
if (frameInfo.PointerShapeBufferSize > 0) if (frameInfo.PointerShapeBufferSize > 0)
{
os_signalEvent(this->pointerEvent);
*hasPointerUpdate = true; *hasPointerUpdate = true;
}
IDXGIResource_Release(res); IDXGIResource_Release(res);
return CAPTURE_RESULT_OK; return CAPTURE_RESULT_OK;
@ -504,24 +557,21 @@ static bool dxgi_getFrame(CaptureFrame * frame)
assert(this); assert(this);
assert(this->initialized); assert(this->initialized);
if (!os_waitEvent(this->frameEvent))
{
DEBUG_ERROR("Failed to wait on the frame event");
return false;
}
frame->width = this->width; frame->width = this->width;
frame->height = this->height; frame->height = this->height;
frame->pitch = this->pitch; frame->pitch = this->pitch;
frame->stride = this->stride; frame->stride = this->stride;
frame->format = this->format; 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); os_signalEvent(this->copyEvent);
return true; return true;
} }