mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-22 05:27:20 +00:00
[host] d12: adjust backend API to allow multiple instances
This commit is contained in:
parent
462d8187b6
commit
c07b72883a
@ -25,7 +25,9 @@
|
|||||||
#include <d3d12.h>
|
#include <d3d12.h>
|
||||||
#include "interface/capture.h"
|
#include "interface/capture.h"
|
||||||
|
|
||||||
typedef struct D12Backend
|
typedef struct D12Backend D12Backend;
|
||||||
|
|
||||||
|
struct D12Backend
|
||||||
{
|
{
|
||||||
// friendly name
|
// friendly name
|
||||||
const char * name;
|
const char * name;
|
||||||
@ -34,21 +36,37 @@ typedef struct D12Backend
|
|||||||
const char * codeName;
|
const char * codeName;
|
||||||
|
|
||||||
// creation/init/free
|
// creation/init/free
|
||||||
bool (*create)(unsigned frameBuffers);
|
bool (*create)(D12Backend ** instance, unsigned frameBuffers);
|
||||||
bool (*init)(
|
bool (*init)(
|
||||||
|
D12Backend * instance,
|
||||||
bool debug,
|
bool debug,
|
||||||
ID3D12Device3 * device,
|
ID3D12Device3 * device,
|
||||||
IDXGIAdapter1 * adapter,
|
IDXGIAdapter1 * adapter,
|
||||||
IDXGIOutput * output);
|
IDXGIOutput * output);
|
||||||
bool (*deinit)(void);
|
bool (*deinit)(D12Backend * instance);
|
||||||
void (*free)(void);
|
void (*free)(D12Backend ** instance);
|
||||||
|
|
||||||
// capture callbacks
|
// capture callbacks
|
||||||
CaptureResult (*capture)(unsigned frameBufferIndex);
|
CaptureResult (*capture)(D12Backend * instance,
|
||||||
CaptureResult (*sync )(ID3D12CommandQueue * commandQueue);
|
unsigned frameBufferIndex);
|
||||||
ID3D12Resource * (*fetch )(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
|
// apis for the backend
|
||||||
void d12_updatePointer(
|
void d12_updatePointer(
|
||||||
|
@ -29,8 +29,10 @@ typedef struct DDCacheInfo
|
|||||||
}
|
}
|
||||||
DDCacheInfo;
|
DDCacheInfo;
|
||||||
|
|
||||||
struct DDInstance
|
typedef struct DDInstance
|
||||||
{
|
{
|
||||||
|
D12Backend base;
|
||||||
|
|
||||||
ComScope * comScope;
|
ComScope * comScope;
|
||||||
|
|
||||||
HDESK desktop;
|
HDESK desktop;
|
||||||
@ -49,43 +51,47 @@ struct DDInstance
|
|||||||
|
|
||||||
void * shapeBuffer;
|
void * shapeBuffer;
|
||||||
unsigned shapeBufferSize;
|
unsigned shapeBufferSize;
|
||||||
};
|
}
|
||||||
|
DDInstance;
|
||||||
struct DDInstance * this = NULL;
|
|
||||||
|
|
||||||
#define comRef_toGlobal(dst, src) \
|
#define comRef_toGlobal(dst, src) \
|
||||||
_comRef_toGlobal(this->comScope, dst, src)
|
_comRef_toGlobal(this->comScope, dst, src)
|
||||||
|
|
||||||
static void d12_dd_openDesktop(void);
|
static void d12_dd_openDesktop(DDInstance * this);
|
||||||
static bool d12_dd_handleFrameUpdate(IDXGIResource * res);
|
static bool d12_dd_handleFrameUpdate(DDInstance * this, IDXGIResource * res);
|
||||||
|
|
||||||
static void d12_dd_handlePointerMovement(DXGI_OUTDUPL_POINTER_POSITION * pos,
|
static void d12_dd_handlePointerMovement(DDInstance * this,
|
||||||
CapturePointer * pointer, bool * changed);
|
DXGI_OUTDUPL_POINTER_POSITION * pos, CapturePointer * pointer, bool * changed);
|
||||||
static void d12_dd_handlePointerShape(
|
static void d12_dd_handlePointerShape(DDInstance * this,
|
||||||
CapturePointer * pointer, size_t size, bool * changed);
|
CapturePointer * pointer, size_t size, bool * changed);
|
||||||
|
|
||||||
static bool d12_dd_getCache(ID3D11Texture2D * srcTex, DDCacheInfo ** result);
|
static bool d12_dd_getCache(DDInstance * this,
|
||||||
static bool d12_dd_convertResource(ID3D11Texture2D * srcTex,
|
ID3D11Texture2D * srcTex, DDCacheInfo ** result);
|
||||||
DDCacheInfo * cache);
|
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)
|
if (!this)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("out of memory");
|
DEBUG_ERROR("out of memory");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*instance = &this->base;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool d12_dd_init(
|
static bool d12_dd_init(
|
||||||
|
D12Backend * instance,
|
||||||
bool debug,
|
bool debug,
|
||||||
ID3D12Device3 * device,
|
ID3D12Device3 * device,
|
||||||
IDXGIAdapter1 * adapter,
|
IDXGIAdapter1 * adapter,
|
||||||
IDXGIOutput * output)
|
IDXGIOutput * output)
|
||||||
{
|
{
|
||||||
|
DDInstance * this = UPCAST(DDInstance, instance);
|
||||||
|
|
||||||
bool result = false;
|
bool result = false;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
@ -93,7 +99,7 @@ static bool d12_dd_init(
|
|||||||
comRef_scopePush(10);
|
comRef_scopePush(10);
|
||||||
|
|
||||||
// try to open the desktop so we can capture the secure desktop
|
// try to open the desktop so we can capture the secure desktop
|
||||||
d12_dd_openDesktop();
|
d12_dd_openDesktop(this);
|
||||||
|
|
||||||
comRef_defineLocal(IDXGIAdapter, _adapter);
|
comRef_defineLocal(IDXGIAdapter, _adapter);
|
||||||
hr = IDXGIAdapter1_QueryInterface(
|
hr = IDXGIAdapter1_QueryInterface(
|
||||||
@ -249,8 +255,10 @@ exit:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool d12_dd_deinit(void)
|
static bool d12_dd_deinit(D12Backend * instance)
|
||||||
{
|
{
|
||||||
|
DDInstance * this = UPCAST(DDInstance, instance);
|
||||||
|
|
||||||
if (this->release)
|
if (this->release)
|
||||||
{
|
{
|
||||||
IDXGIOutputDuplication_ReleaseFrame(*this->dup);
|
IDXGIOutputDuplication_ReleaseFrame(*this->dup);
|
||||||
@ -264,15 +272,17 @@ static bool d12_dd_deinit(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
comRef_freeScope(&this->comScope);
|
comRef_freeScope(&this->comScope);
|
||||||
memset(this, 0, sizeof(*this));
|
memset(this->cache, 0, sizeof(this->cache));
|
||||||
return true;
|
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->shapeBuffer);
|
||||||
free(this);
|
free(this);
|
||||||
this = NULL;
|
*instance = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CaptureResult d12_dd_hResultToCaptureResult(const HRESULT status)
|
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;
|
HRESULT hr;
|
||||||
CaptureResult result = CAPTURE_RESULT_ERROR;
|
CaptureResult result = CAPTURE_RESULT_ERROR;
|
||||||
comRef_scopePush(10);
|
comRef_scopePush(10);
|
||||||
@ -337,7 +350,7 @@ retry:
|
|||||||
|
|
||||||
// if we have a new frame
|
// if we have a new frame
|
||||||
if (frameInfo.LastPresentTime.QuadPart != 0)
|
if (frameInfo.LastPresentTime.QuadPart != 0)
|
||||||
if (!d12_dd_handleFrameUpdate(*res))
|
if (!d12_dd_handleFrameUpdate(this, *res))
|
||||||
{
|
{
|
||||||
result = CAPTURE_RESULT_ERROR;
|
result = CAPTURE_RESULT_ERROR;
|
||||||
goto exit;
|
goto exit;
|
||||||
@ -348,12 +361,12 @@ retry:
|
|||||||
|
|
||||||
// if the pointer has moved
|
// if the pointer has moved
|
||||||
if (frameInfo.LastMouseUpdateTime.QuadPart != 0)
|
if (frameInfo.LastMouseUpdateTime.QuadPart != 0)
|
||||||
d12_dd_handlePointerMovement(
|
d12_dd_handlePointerMovement(this,
|
||||||
&frameInfo.PointerPosition, &pointer, &postPointer);
|
&frameInfo.PointerPosition, &pointer, &postPointer);
|
||||||
|
|
||||||
// if the pointer shape has changed
|
// if the pointer shape has changed
|
||||||
if (frameInfo.PointerShapeBufferSize > 0)
|
if (frameInfo.PointerShapeBufferSize > 0)
|
||||||
d12_dd_handlePointerShape(
|
d12_dd_handlePointerShape(this,
|
||||||
&pointer, frameInfo.PointerShapeBufferSize, &postPointer);
|
&pointer, frameInfo.PointerShapeBufferSize, &postPointer);
|
||||||
|
|
||||||
if (postPointer)
|
if (postPointer)
|
||||||
@ -368,8 +381,11 @@ exit:
|
|||||||
return result;
|
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)
|
if (!this->current)
|
||||||
return CAPTURE_RESULT_TIMEOUT;
|
return CAPTURE_RESULT_TIMEOUT;
|
||||||
|
|
||||||
@ -380,8 +396,11 @@ static CaptureResult d12_dd_sync(ID3D12CommandQueue * commandQueue)
|
|||||||
return CAPTURE_RESULT_OK;
|
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)
|
if (!this->current)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -389,7 +408,7 @@ static ID3D12Resource * d12_dd_fetch(unsigned frameBufferIndex)
|
|||||||
return *this->current->d12Res;
|
return *this->current->d12Res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void d12_dd_openDesktop(void)
|
static void d12_dd_openDesktop(DDInstance * this)
|
||||||
{
|
{
|
||||||
this->desktop = OpenInputDesktop(0, FALSE, GENERIC_READ);
|
this->desktop = OpenInputDesktop(0, FALSE, GENERIC_READ);
|
||||||
if (!this->desktop)
|
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;
|
bool result = false;
|
||||||
comRef_scopePush(1);
|
comRef_scopePush(1);
|
||||||
@ -429,7 +448,7 @@ static bool d12_dd_handleFrameUpdate(IDXGIResource * res)
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!d12_dd_getCache(*srcTex, &this->current))
|
if (!d12_dd_getCache(this, *srcTex, &this->current))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -447,8 +466,8 @@ exit:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void d12_dd_handlePointerMovement(DXGI_OUTDUPL_POINTER_POSITION * pos,
|
static void d12_dd_handlePointerMovement(DDInstance * this,
|
||||||
CapturePointer * pointer, bool * changed)
|
DXGI_OUTDUPL_POINTER_POSITION * pos, CapturePointer * pointer, bool * changed)
|
||||||
{
|
{
|
||||||
bool setPos = false;
|
bool setPos = false;
|
||||||
|
|
||||||
@ -488,7 +507,7 @@ static void d12_dd_handlePointerMovement(DXGI_OUTDUPL_POINTER_POSITION * pos,
|
|||||||
this->lastPosValid = true;
|
this->lastPosValid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void d12_dd_handlePointerShape(
|
static void d12_dd_handlePointerShape(DDInstance * this,
|
||||||
CapturePointer * pointer, size_t size, bool * changed)
|
CapturePointer * pointer, size_t size, bool * changed)
|
||||||
{
|
{
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
@ -556,7 +575,8 @@ retry:
|
|||||||
*changed = true;
|
*changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool d12_dd_getCache(ID3D11Texture2D * srcTex, DDCacheInfo ** result)
|
static bool d12_dd_getCache(DDInstance * this,
|
||||||
|
ID3D11Texture2D * srcTex, DDCacheInfo ** result)
|
||||||
{
|
{
|
||||||
*result = NULL;
|
*result = NULL;
|
||||||
D3D11_TEXTURE2D_DESC srcDesc;
|
D3D11_TEXTURE2D_DESC srcDesc;
|
||||||
@ -597,7 +617,7 @@ static bool d12_dd_getCache(ID3D11Texture2D * srcTex, DDCacheInfo ** result)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// convert the resource
|
// convert the resource
|
||||||
if (!d12_dd_convertResource(srcTex, &this->cache[freeSlot]))
|
if (!d12_dd_convertResource(this, srcTex, &this->cache[freeSlot]))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// return the new cache entry
|
// return the new cache entry
|
||||||
@ -605,7 +625,8 @@ static bool d12_dd_getCache(ID3D11Texture2D * srcTex, DDCacheInfo ** result)
|
|||||||
return true;
|
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;
|
bool result = false;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
@ -166,8 +166,7 @@ static bool d12_create(
|
|||||||
this->getPointerBufferFn = getPointerBufferFn;
|
this->getPointerBufferFn = getPointerBufferFn;
|
||||||
this->postPointerBufferFn = postPointerBufferFn;
|
this->postPointerBufferFn = postPointerBufferFn;
|
||||||
|
|
||||||
this->backend = &D12Backend_DD;
|
if (!d12_createBackend(&D12Backend_DD, &this->backend, frameBuffers))
|
||||||
if (!this->backend->create(frameBuffers))
|
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("backend \"%s\" failed to create", this->backend->codeName);
|
DEBUG_ERROR("backend \"%s\" failed to create", this->backend->codeName);
|
||||||
CloseHandle(this->d3d12);
|
CloseHandle(this->d3d12);
|
||||||
@ -279,7 +278,8 @@ retryCreateCommandQueue:
|
|||||||
*alignSize = heapDesc.Alignment;
|
*alignSize = heapDesc.Alignment;
|
||||||
|
|
||||||
// initialize the backend
|
// 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;
|
goto exit;
|
||||||
|
|
||||||
comRef_toGlobal(this->factory , factory );
|
comRef_toGlobal(this->factory , factory );
|
||||||
@ -304,7 +304,7 @@ static void d12_stop(void)
|
|||||||
static bool d12_deinit(void)
|
static bool d12_deinit(void)
|
||||||
{
|
{
|
||||||
bool result = true;
|
bool result = true;
|
||||||
if (!this->backend->deinit())
|
if (!this->backend->deinit(this->backend))
|
||||||
result = false;
|
result = false;
|
||||||
|
|
||||||
d12_freeCommandGroup(&this->copyCommand);
|
d12_freeCommandGroup(&this->copyCommand);
|
||||||
@ -314,7 +314,7 @@ static bool d12_deinit(void)
|
|||||||
|
|
||||||
static void d12_free(void)
|
static void d12_free(void)
|
||||||
{
|
{
|
||||||
this->backend->free();
|
this->backend->free(&this->backend);
|
||||||
FreeLibrary(this->d3d12);
|
FreeLibrary(this->d3d12);
|
||||||
free(this);
|
free(this);
|
||||||
this = NULL;
|
this = NULL;
|
||||||
@ -323,7 +323,7 @@ static void d12_free(void)
|
|||||||
static CaptureResult d12_capture(
|
static CaptureResult d12_capture(
|
||||||
unsigned frameBufferIndex, FrameBuffer * frameBuffer)
|
unsigned frameBufferIndex, FrameBuffer * frameBuffer)
|
||||||
{
|
{
|
||||||
return this->backend->capture(frameBufferIndex);
|
return this->backend->capture(this->backend, frameBufferIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static CaptureResult d12_waitFrame(unsigned frameBufferIndex,
|
static CaptureResult d12_waitFrame(unsigned frameBufferIndex,
|
||||||
@ -333,7 +333,7 @@ static CaptureResult d12_waitFrame(unsigned frameBufferIndex,
|
|||||||
comRef_scopePush(1);
|
comRef_scopePush(1);
|
||||||
|
|
||||||
comRef_defineLocal(ID3D12Resource, src);
|
comRef_defineLocal(ID3D12Resource, src);
|
||||||
*src = this->backend->fetch(frameBufferIndex);
|
*src = this->backend->fetch(this->backend, frameBufferIndex);
|
||||||
if (!*src)
|
if (!*src)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("D12 backend failed to produce an expected frame: %u",
|
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_scopePush(2);
|
||||||
|
|
||||||
comRef_defineLocal(ID3D12Resource, src);
|
comRef_defineLocal(ID3D12Resource, src);
|
||||||
*src = this->backend->fetch(frameBufferIndex);
|
*src = this->backend->fetch(this->backend, frameBufferIndex);
|
||||||
if (!*src)
|
if (!*src)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("D12 backend failed to produce an expected frame: %u",
|
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);
|
*this->copyCommand.gfxList, &dstLoc, 0, 0, 0, &srcLoc, NULL);
|
||||||
|
|
||||||
// allow the backend to insert a fence into the command queue if it needs it
|
// 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)
|
if (result != CAPTURE_RESULT_OK)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user