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

View File

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