diff --git a/c-host/platform/Windows/capture/DXGI/src/dxgi.c b/c-host/platform/Windows/capture/DXGI/src/dxgi.c index eab080a0..61b86e13 100644 --- a/c-host/platform/Windows/capture/DXGI/src/dxgi.c +++ b/c-host/platform/Windows/capture/DXGI/src/dxgi.c @@ -46,7 +46,6 @@ typedef struct Texture enum TextureState state; ID3D11Texture2D * tex; D3D11_MAPPED_SUBRESOURCE map; - osEventHandle * readyEvent; } Texture; @@ -80,10 +79,12 @@ struct iface IDXGIOutputDuplication * dup; int maxTextures; Texture * texture; - volatile int texRIndex; + int texRIndex; int texWIndex; + volatile int texReady; bool needsRelease; osEventHandle * pointerEvent; + osEventHandle * frameEvent; unsigned int width; unsigned int height; @@ -172,27 +173,20 @@ static bool dxgi_create() return false; } + this->frameEvent = os_createEvent(true, 17); // 60Hz = 16.7ms + if (!this->frameEvent) + { + DEBUG_ERROR("failed to create the frame event"); + free(this); + return false; + } + this->maxTextures = option_get_int("dxgi", "maxTextures"); if (this->maxTextures <= 0) this->maxTextures = 1; - this->texture = calloc(sizeof(struct Texture), this->maxTextures); - for(int i = 0; i < this->maxTextures; ++i) - { - this->texture[i].readyEvent = os_createEvent(false, 30); - if (!this->texture[i].readyEvent) - { - DEBUG_ERROR("failed to create the texture event"); - - for(int x = 0; x < i; ++x) - os_freeEvent(this->texture[x].readyEvent); - - free(this->texture); - free(this); - } - } - this->useAcquireLock = option_get_bool("dxgi", "useAcquireLock"); + this->texture = calloc(sizeof(struct Texture), this->maxTextures); return true; } @@ -226,6 +220,7 @@ static bool dxgi_init(void * pointerShape, const unsigned int pointerSize) this->stop = false; this->texRIndex = 0; this->texWIndex = 0; + this->texReady = 0; status = CreateDXGIFactory1(&IID_IDXGIFactory1, (void **)&this->factory); if (FAILED(status)) @@ -682,11 +677,12 @@ static CaptureResult dxgi_capture() ID3D11Texture2D_Release(src); - // set the state and signal + // set the state, and signal tex->state = TEXTURE_STATE_PENDING_MAP; - os_signalEvent(tex->readyEvent); + INTERLOCKED_INC(&this->texReady); + os_signalEvent(this->frameEvent); - // advance our write pointer + // advance the write index if (++this->texWIndex == this->maxTextures) this->texWIndex = 0; @@ -760,9 +756,17 @@ static CaptureResult dxgi_waitFrame(CaptureFrame * frame) assert(this); assert(this->initialized); - Texture * tex = &this->texture[INTERLOCKED_GET(&this->texRIndex)]; - if (!os_waitEvent(tex->readyEvent, 1000)) - return CAPTURE_RESULT_TIMEOUT; + // NOTE: the event may be signaled when there are no frames available + if(this->texReady == 0) + { + if (!os_waitEvent(this->frameEvent, 1000)) + return CAPTURE_RESULT_TIMEOUT; + + if (this->texReady == 0) + return CAPTURE_RESULT_TIMEOUT; + } + + Texture * tex = &this->texture[this->texRIndex]; // try to map the resource, but don't wait for it HRESULT status; @@ -784,7 +788,7 @@ static CaptureResult dxgi_waitFrame(CaptureFrame * frame) frame->stride = this->stride; frame->format = this->format; - os_resetEvent(tex->readyEvent); + INTERLOCKED_DEC(&this->texReady); return CAPTURE_RESULT_OK; } @@ -793,14 +797,14 @@ static CaptureResult dxgi_getFrame(FrameBuffer frame) assert(this); assert(this->initialized); - Texture * tex = &this->texture[INTERLOCKED_GET(&this->texRIndex)]; + Texture * tex = &this->texture[this->texRIndex]; framebuffer_write(frame, tex->map.pData, this->pitch * this->height); LOCKED({ID3D11DeviceContext_Unmap(this->deviceContext, (ID3D11Resource*)tex->tex, 0);}); tex->state = TEXTURE_STATE_UNUSED; - INTERLOCKED_INC(&this->texRIndex); - INTERLOCKED_CE (&this->texRIndex, this->maxTextures, 0); + if (++this->texRIndex == this->maxTextures) + this->texRIndex = 0; return CAPTURE_RESULT_OK; } diff --git a/c-host/platform/Windows/src/platform.c b/c-host/platform/Windows/src/platform.c index bd05db38..e9241a72 100644 --- a/c-host/platform/Windows/src/platform.c +++ b/c-host/platform/Windows/src/platform.c @@ -30,6 +30,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA #include "interface/platform.h" #include "common/debug.h" #include "common/option.h" +#include "common/locking.h" #include "windows/debug.h" #include "ivshmem.h" @@ -72,6 +73,7 @@ struct osThreadHandle struct osEventHandle { + volatile int lock; bool reset; HANDLE handle; bool wrapped; @@ -510,10 +512,13 @@ osEventHandle * os_createEvent(bool autoReset, unsigned int msSpinTime) return NULL; } + event->lock = 0; event->reset = autoReset; + event->handle = CreateEvent(NULL, autoReset ? FALSE : TRUE, FALSE, NULL); event->wrapped = false; event->msSpinTime = msSpinTime; - event->handle = CreateEvent(NULL, autoReset ? FALSE : TRUE, FALSE, NULL); + event->signaled = false; + if (!event->handle) { DEBUG_WINERROR("Failed to create the event", GetLastError()); @@ -533,10 +538,12 @@ osEventHandle * os_wrapEvent(HANDLE handle) return NULL; } + event->lock = 0; event->reset = false; event->handle = event; event->wrapped = true; event->msSpinTime = 0; + event->signaled = false; return event; } @@ -551,10 +558,19 @@ bool os_waitEvent(osEventHandle * event, unsigned int timeout) if (!event->wrapped) { if (event->signaled) + { + if (event->reset) + event->signaled = false; return true; + } if (timeout == 0) - return event->signaled; + { + bool ret = event->signaled; + if (event->reset) + event->signaled = false; + return ret; + } if (event->msSpinTime) { @@ -581,7 +597,11 @@ bool os_waitEvent(osEventHandle * event, unsigned int timeout) } if (event->signaled) + { + if (event->reset) + event->signaled = false; return true; + } } }