From c07b72883a17f4d364c8fa6eb6fbb670bb0c680b Mon Sep 17 00:00:00 2001 From: Geoffrey McRae Date: Wed, 31 Jan 2024 09:43:01 +1100 Subject: [PATCH] [host] d12: adjust backend API to allow multiple instances --- host/platform/Windows/capture/D12/backend.h | 34 +++++-- .../platform/Windows/capture/D12/backend/dd.c | 89 ++++++++++++------- host/platform/Windows/capture/D12/d12.c | 18 ++-- 3 files changed, 90 insertions(+), 51 deletions(-) diff --git a/host/platform/Windows/capture/D12/backend.h b/host/platform/Windows/capture/D12/backend.h index 28ed804b..23df0cd2 100644 --- a/host/platform/Windows/capture/D12/backend.h +++ b/host/platform/Windows/capture/D12/backend.h @@ -25,7 +25,9 @@ #include #include "interface/capture.h" -typedef struct D12Backend +typedef struct D12Backend D12Backend; + +struct D12Backend { // friendly name const char * name; @@ -34,21 +36,37 @@ typedef struct D12Backend const char * codeName; // creation/init/free - bool (*create)(unsigned frameBuffers); + bool (*create)(D12Backend ** instance, unsigned frameBuffers); bool (*init)( + D12Backend * instance, bool debug, ID3D12Device3 * device, IDXGIAdapter1 * adapter, IDXGIOutput * output); - bool (*deinit)(void); - void (*free)(void); + bool (*deinit)(D12Backend * instance); + void (*free)(D12Backend ** instance); // capture callbacks - CaptureResult (*capture)(unsigned frameBufferIndex); - CaptureResult (*sync )(ID3D12CommandQueue * commandQueue); - ID3D12Resource * (*fetch )(unsigned frameBufferIndex); + CaptureResult (*capture)(D12Backend * instance, + unsigned frameBufferIndex); + + CaptureResult (*sync)(D12Backend * instance, + ID3D12CommandQueue * commandQueue); + + ID3D12Resource * (*fetch)(D12Backend * instance, + unsigned frameBufferIndex); +}; + +// helpers for the interface + +static inline bool d12_createBackend( + D12Backend * backend, D12Backend ** instance, unsigned frameBuffers) +{ + if (!backend->create(instance, frameBuffers)) + return false; + memcpy(*instance, backend, sizeof(*backend)); + return true; } -D12Backend; // apis for the backend void d12_updatePointer( diff --git a/host/platform/Windows/capture/D12/backend/dd.c b/host/platform/Windows/capture/D12/backend/dd.c index 92a2c049..a758d778 100644 --- a/host/platform/Windows/capture/D12/backend/dd.c +++ b/host/platform/Windows/capture/D12/backend/dd.c @@ -29,8 +29,10 @@ typedef struct DDCacheInfo } DDCacheInfo; -struct DDInstance +typedef struct DDInstance { + D12Backend base; + ComScope * comScope; HDESK desktop; @@ -49,43 +51,47 @@ struct DDInstance void * shapeBuffer; unsigned shapeBufferSize; -}; - -struct DDInstance * this = NULL; +} +DDInstance; #define comRef_toGlobal(dst, src) \ _comRef_toGlobal(this->comScope, dst, src) -static void d12_dd_openDesktop(void); -static bool d12_dd_handleFrameUpdate(IDXGIResource * res); +static void d12_dd_openDesktop(DDInstance * this); +static bool d12_dd_handleFrameUpdate(DDInstance * this, IDXGIResource * res); -static void d12_dd_handlePointerMovement(DXGI_OUTDUPL_POINTER_POSITION * pos, - CapturePointer * pointer, bool * changed); -static void d12_dd_handlePointerShape( +static void d12_dd_handlePointerMovement(DDInstance * this, + DXGI_OUTDUPL_POINTER_POSITION * pos, CapturePointer * pointer, bool * changed); +static void d12_dd_handlePointerShape(DDInstance * this, CapturePointer * pointer, size_t size, bool * changed); -static bool d12_dd_getCache(ID3D11Texture2D * srcTex, DDCacheInfo ** result); -static bool d12_dd_convertResource(ID3D11Texture2D * srcTex, - DDCacheInfo * cache); +static bool d12_dd_getCache(DDInstance * this, + ID3D11Texture2D * srcTex, DDCacheInfo ** result); +static bool d12_dd_convertResource(DDInstance * this, + ID3D11Texture2D * srcTex, DDCacheInfo * cache); -static bool d12_dd_create(unsigned frameBuffers) +static bool d12_dd_create(D12Backend ** instance, unsigned frameBuffers) { - this = calloc(1, sizeof(*this)); + DDInstance * this = calloc(1, sizeof(*this)); if (!this) { DEBUG_ERROR("out of memory"); return false; } + *instance = &this->base; return true; } static bool d12_dd_init( + D12Backend * instance, bool debug, ID3D12Device3 * device, IDXGIAdapter1 * adapter, IDXGIOutput * output) { + DDInstance * this = UPCAST(DDInstance, instance); + bool result = false; HRESULT hr; @@ -93,7 +99,7 @@ static bool d12_dd_init( comRef_scopePush(10); // try to open the desktop so we can capture the secure desktop - d12_dd_openDesktop(); + d12_dd_openDesktop(this); comRef_defineLocal(IDXGIAdapter, _adapter); hr = IDXGIAdapter1_QueryInterface( @@ -249,8 +255,10 @@ exit: return result; } -static bool d12_dd_deinit(void) +static bool d12_dd_deinit(D12Backend * instance) { + DDInstance * this = UPCAST(DDInstance, instance); + if (this->release) { IDXGIOutputDuplication_ReleaseFrame(*this->dup); @@ -264,15 +272,17 @@ static bool d12_dd_deinit(void) } comRef_freeScope(&this->comScope); - memset(this, 0, sizeof(*this)); + memset(this->cache, 0, sizeof(this->cache)); return true; } -static void d12_dd_free(void) +static void d12_dd_free(D12Backend ** instance) { + DDInstance * this = UPCAST(DDInstance, *instance); + free(this->shapeBuffer); free(this); - this = NULL; + *instance = NULL; } static CaptureResult d12_dd_hResultToCaptureResult(const HRESULT status) @@ -295,8 +305,11 @@ static CaptureResult d12_dd_hResultToCaptureResult(const HRESULT status) } } -static CaptureResult d12_dd_capture(unsigned frameBufferIndex) +static CaptureResult d12_dd_capture(D12Backend * instance, + unsigned frameBufferIndex) { + DDInstance * this = UPCAST(DDInstance, instance); + HRESULT hr; CaptureResult result = CAPTURE_RESULT_ERROR; comRef_scopePush(10); @@ -337,7 +350,7 @@ retry: // if we have a new frame if (frameInfo.LastPresentTime.QuadPart != 0) - if (!d12_dd_handleFrameUpdate(*res)) + if (!d12_dd_handleFrameUpdate(this, *res)) { result = CAPTURE_RESULT_ERROR; goto exit; @@ -348,12 +361,12 @@ retry: // if the pointer has moved if (frameInfo.LastMouseUpdateTime.QuadPart != 0) - d12_dd_handlePointerMovement( + d12_dd_handlePointerMovement(this, &frameInfo.PointerPosition, &pointer, &postPointer); // if the pointer shape has changed if (frameInfo.PointerShapeBufferSize > 0) - d12_dd_handlePointerShape( + d12_dd_handlePointerShape(this, &pointer, frameInfo.PointerShapeBufferSize, &postPointer); if (postPointer) @@ -368,8 +381,11 @@ exit: return result; } -static CaptureResult d12_dd_sync(ID3D12CommandQueue * commandQueue) +static CaptureResult d12_dd_sync(D12Backend * instance, + ID3D12CommandQueue * commandQueue) { + DDInstance * this = UPCAST(DDInstance, instance); + if (!this->current) return CAPTURE_RESULT_TIMEOUT; @@ -380,8 +396,11 @@ static CaptureResult d12_dd_sync(ID3D12CommandQueue * commandQueue) return CAPTURE_RESULT_OK; } -static ID3D12Resource * d12_dd_fetch(unsigned frameBufferIndex) +static ID3D12Resource * d12_dd_fetch(D12Backend * instance, + unsigned frameBufferIndex) { + DDInstance * this = UPCAST(DDInstance, instance); + if (!this->current) return NULL; @@ -389,7 +408,7 @@ static ID3D12Resource * d12_dd_fetch(unsigned frameBufferIndex) return *this->current->d12Res; } -static void d12_dd_openDesktop(void) +static void d12_dd_openDesktop(DDInstance * this) { this->desktop = OpenInputDesktop(0, FALSE, GENERIC_READ); if (!this->desktop) @@ -415,7 +434,7 @@ static void d12_dd_openDesktop(void) } } -static bool d12_dd_handleFrameUpdate(IDXGIResource * res) +static bool d12_dd_handleFrameUpdate(DDInstance * this, IDXGIResource * res) { bool result = false; comRef_scopePush(1); @@ -429,7 +448,7 @@ static bool d12_dd_handleFrameUpdate(IDXGIResource * res) goto exit; } - if (!d12_dd_getCache(*srcTex, &this->current)) + if (!d12_dd_getCache(this, *srcTex, &this->current)) goto exit; /** @@ -447,8 +466,8 @@ exit: return result; } -static void d12_dd_handlePointerMovement(DXGI_OUTDUPL_POINTER_POSITION * pos, - CapturePointer * pointer, bool * changed) +static void d12_dd_handlePointerMovement(DDInstance * this, + DXGI_OUTDUPL_POINTER_POSITION * pos, CapturePointer * pointer, bool * changed) { bool setPos = false; @@ -488,7 +507,7 @@ static void d12_dd_handlePointerMovement(DXGI_OUTDUPL_POINTER_POSITION * pos, this->lastPosValid = true; } -static void d12_dd_handlePointerShape( +static void d12_dd_handlePointerShape(DDInstance * this, CapturePointer * pointer, size_t size, bool * changed) { HRESULT hr; @@ -556,7 +575,8 @@ retry: *changed = true; } -static bool d12_dd_getCache(ID3D11Texture2D * srcTex, DDCacheInfo ** result) +static bool d12_dd_getCache(DDInstance * this, + ID3D11Texture2D * srcTex, DDCacheInfo ** result) { *result = NULL; D3D11_TEXTURE2D_DESC srcDesc; @@ -597,7 +617,7 @@ static bool d12_dd_getCache(ID3D11Texture2D * srcTex, DDCacheInfo ** result) return false; // convert the resource - if (!d12_dd_convertResource(srcTex, &this->cache[freeSlot])) + if (!d12_dd_convertResource(this, srcTex, &this->cache[freeSlot])) return false; // return the new cache entry @@ -605,7 +625,8 @@ static bool d12_dd_getCache(ID3D11Texture2D * srcTex, DDCacheInfo ** result) return true; } -static bool d12_dd_convertResource(ID3D11Texture2D * srcTex, DDCacheInfo * cache) +static bool d12_dd_convertResource(DDInstance * this, + ID3D11Texture2D * srcTex, DDCacheInfo * cache) { bool result = false; HRESULT hr; diff --git a/host/platform/Windows/capture/D12/d12.c b/host/platform/Windows/capture/D12/d12.c index 6dc68173..36af179b 100644 --- a/host/platform/Windows/capture/D12/d12.c +++ b/host/platform/Windows/capture/D12/d12.c @@ -166,8 +166,7 @@ static bool d12_create( this->getPointerBufferFn = getPointerBufferFn; this->postPointerBufferFn = postPointerBufferFn; - this->backend = &D12Backend_DD; - if (!this->backend->create(frameBuffers)) + if (!d12_createBackend(&D12Backend_DD, &this->backend, frameBuffers)) { DEBUG_ERROR("backend \"%s\" failed to create", this->backend->codeName); CloseHandle(this->d3d12); @@ -279,7 +278,8 @@ retryCreateCommandQueue: *alignSize = heapDesc.Alignment; // initialize the backend - if (!this->backend->init(this->debug, *device, *adapter, *output)) + if (!this->backend->init(this->backend, + this->debug, *device, *adapter, *output)) goto exit; comRef_toGlobal(this->factory , factory ); @@ -304,7 +304,7 @@ static void d12_stop(void) static bool d12_deinit(void) { bool result = true; - if (!this->backend->deinit()) + if (!this->backend->deinit(this->backend)) result = false; d12_freeCommandGroup(&this->copyCommand); @@ -314,7 +314,7 @@ static bool d12_deinit(void) static void d12_free(void) { - this->backend->free(); + this->backend->free(&this->backend); FreeLibrary(this->d3d12); free(this); this = NULL; @@ -323,7 +323,7 @@ static void d12_free(void) static CaptureResult d12_capture( unsigned frameBufferIndex, FrameBuffer * frameBuffer) { - return this->backend->capture(frameBufferIndex); + return this->backend->capture(this->backend, frameBufferIndex); } static CaptureResult d12_waitFrame(unsigned frameBufferIndex, @@ -333,7 +333,7 @@ static CaptureResult d12_waitFrame(unsigned frameBufferIndex, comRef_scopePush(1); comRef_defineLocal(ID3D12Resource, src); - *src = this->backend->fetch(frameBufferIndex); + *src = this->backend->fetch(this->backend, frameBufferIndex); if (!*src) { DEBUG_ERROR("D12 backend failed to produce an expected frame: %u", @@ -383,7 +383,7 @@ static CaptureResult d12_getFrame(unsigned frameBufferIndex, comRef_scopePush(2); comRef_defineLocal(ID3D12Resource, src); - *src = this->backend->fetch(frameBufferIndex); + *src = this->backend->fetch(this->backend, frameBufferIndex); if (!*src) { DEBUG_ERROR("D12 backend failed to produce an expected frame: %u", @@ -427,7 +427,7 @@ static CaptureResult d12_getFrame(unsigned frameBufferIndex, *this->copyCommand.gfxList, &dstLoc, 0, 0, 0, &srcLoc, NULL); // allow the backend to insert a fence into the command queue if it needs it - result = this->backend->sync(*this->commandQueue); + result = this->backend->sync(this->backend, *this->commandQueue); if (result != CAPTURE_RESULT_OK) goto exit;