[host] dxgi: update to make use of comRef (part 1 of 2)

This commit is contained in:
Geoffrey McRae 2023-10-27 17:34:34 +11:00
parent 69b984aa2c
commit b94166177f
4 changed files with 187 additions and 232 deletions

View File

@ -44,6 +44,11 @@ inline static size_t vector_size(Vector * vector)
return vector->size; return vector->size;
} }
inline static size_t vector_capacity(Vector * vector)
{
return vector->capacity;
}
inline static void * vector_data(Vector * vector) inline static void * vector_data(Vector * vector)
{ {
return vector->data; return vector->data;

View File

@ -102,7 +102,7 @@ static bool d3d11_create(struct DXGIInterface * intf)
struct D3D11TexImpl * teximpl = TEXIMPL(dxgi->texture[i]); struct D3D11TexImpl * teximpl = TEXIMPL(dxgi->texture[i]);
status = ID3D11Device_CreateTexture2D(dxgi->device, &cpuTexDesc, NULL, status = ID3D11Device_CreateTexture2D(*dxgi->device, &cpuTexDesc, NULL,
&teximpl->cpu); &teximpl->cpu);
if (FAILED(status)) if (FAILED(status))
@ -114,7 +114,7 @@ static bool d3d11_create(struct DXGIInterface * intf)
if (!dxgi->downsampleLevel) if (!dxgi->downsampleLevel)
continue; continue;
status = ID3D11Device_CreateTexture2D(dxgi->device, &gpuTexDesc, NULL, status = ID3D11Device_CreateTexture2D(*dxgi->device, &gpuTexDesc, NULL,
&teximpl->gpu); &teximpl->gpu);
if (FAILED(status)) if (FAILED(status))
@ -123,13 +123,13 @@ static bool d3d11_create(struct DXGIInterface * intf)
goto fail; goto fail;
} }
ID3D11Device_CreateShaderResourceView(dxgi->device, ID3D11Device_CreateShaderResourceView(*dxgi->device,
(ID3D11Resource *)teximpl->gpu, NULL, &teximpl->srv); (ID3D11Resource *)teximpl->gpu, NULL, &teximpl->srv);
} }
// map the texture simply to get the pitch and stride // map the texture simply to get the pitch and stride
D3D11_MAPPED_SUBRESOURCE mapping; D3D11_MAPPED_SUBRESOURCE mapping;
status = ID3D11DeviceContext_Map(dxgi->deviceContext, status = ID3D11DeviceContext_Map(*dxgi->deviceContext,
(ID3D11Resource *)TEXIMPL(dxgi->texture[0])->cpu, 0, (ID3D11Resource *)TEXIMPL(dxgi->texture[0])->cpu, 0,
D3D11_MAP_READ, 0, &mapping); D3D11_MAP_READ, 0, &mapping);
@ -142,7 +142,7 @@ static bool d3d11_create(struct DXGIInterface * intf)
dxgi->pitch = mapping.RowPitch; dxgi->pitch = mapping.RowPitch;
dxgi->stride = mapping.RowPitch / dxgi->bpp; dxgi->stride = mapping.RowPitch / dxgi->bpp;
ID3D11DeviceContext_Unmap(dxgi->deviceContext, ID3D11DeviceContext_Unmap(*dxgi->deviceContext,
(ID3D11Resource *)TEXIMPL(dxgi->texture[0])->cpu, 0); (ID3D11Resource *)TEXIMPL(dxgi->texture[0])->cpu, 0);
return true; return true;
@ -185,7 +185,7 @@ static void copyFrameFull(Texture * tex, ID3D11Texture2D * src)
ID3D11Texture2D * dst = teximpl->cpu; ID3D11Texture2D * dst = teximpl->cpu;
if (tex->texDamageCount < 0) if (tex->texDamageCount < 0)
ID3D11DeviceContext_CopyResource(dxgi->deviceContext, ID3D11DeviceContext_CopyResource(*dxgi->deviceContext,
(ID3D11Resource *)dst, (ID3D11Resource *)src); (ID3D11Resource *)dst, (ID3D11Resource *)src);
else else
{ {
@ -201,7 +201,7 @@ static void copyFrameFull(Texture * tex, ID3D11Texture2D * src)
.right = rect->x + rect->width , .right = rect->x + rect->width ,
.bottom = rect->y + rect->height, .bottom = rect->y + rect->height,
}; };
ID3D11DeviceContext_CopySubresourceRegion(dxgi->deviceContext, ID3D11DeviceContext_CopySubresourceRegion(*dxgi->deviceContext,
(ID3D11Resource *)dst, 0, box.left, box.top, 0, (ID3D11Resource *)dst, 0, box.left, box.top, 0,
(ID3D11Resource *)src, 0, &box); (ID3D11Resource *)src, 0, &box);
} }
@ -214,7 +214,7 @@ static void copyFrameDownsampled(Texture * tex, ID3D11Texture2D * src)
ID3D11Texture2D * dst = teximpl->gpu; ID3D11Texture2D * dst = teximpl->gpu;
if (tex->texDamageCount < 0) if (tex->texDamageCount < 0)
ID3D11DeviceContext_ResolveSubresource(dxgi->deviceContext, ID3D11DeviceContext_ResolveSubresource(*dxgi->deviceContext,
(ID3D11Resource *)dst, 0, (ID3D11Resource *)dst, 0,
(ID3D11Resource *)src, 0, (ID3D11Resource *)src, 0,
dxgi->dxgiFormat); dxgi->dxgiFormat);
@ -232,15 +232,15 @@ static void copyFrameDownsampled(Texture * tex, ID3D11Texture2D * src)
.right = (rect->x + rect->width ) << dxgi->downsampleLevel, .right = (rect->x + rect->width ) << dxgi->downsampleLevel,
.bottom = (rect->y + rect->height) << dxgi->downsampleLevel, .bottom = (rect->y + rect->height) << dxgi->downsampleLevel,
}; };
ID3D11DeviceContext_CopySubresourceRegion(dxgi->deviceContext, ID3D11DeviceContext_CopySubresourceRegion(*dxgi->deviceContext,
(ID3D11Resource *)dst, 0, box.left, box.top, 0, (ID3D11Resource *)dst, 0, box.left, box.top, 0,
(ID3D11Resource *)src, 0, &box); (ID3D11Resource *)src, 0, &box);
} }
} }
ID3D11DeviceContext_GenerateMips(dxgi->deviceContext, teximpl->srv); ID3D11DeviceContext_GenerateMips(*dxgi->deviceContext, teximpl->srv);
if (tex->texDamageCount < 0) if (tex->texDamageCount < 0)
ID3D11DeviceContext_CopySubresourceRegion(dxgi->deviceContext, ID3D11DeviceContext_CopySubresourceRegion(*dxgi->deviceContext,
(ID3D11Resource *)teximpl->cpu, 0, 0, 0, 0, (ID3D11Resource *)teximpl->cpu, 0, 0, 0, 0,
(ID3D11Resource *)dst , dxgi->downsampleLevel, NULL); (ID3D11Resource *)dst , dxgi->downsampleLevel, NULL);
else else
@ -258,7 +258,7 @@ static void copyFrameDownsampled(Texture * tex, ID3D11Texture2D * src)
.bottom = rect->y + rect->height, .bottom = rect->y + rect->height,
}; };
ID3D11DeviceContext_CopySubresourceRegion(dxgi->deviceContext, ID3D11DeviceContext_CopySubresourceRegion(*dxgi->deviceContext,
(ID3D11Resource *)teximpl->cpu, 0, box.left, box.top, 0, (ID3D11Resource *)teximpl->cpu, 0, box.left, box.top, 0,
(ID3D11Resource *)dst , dxgi->downsampleLevel, &box); (ID3D11Resource *)dst , dxgi->downsampleLevel, &box);
} }
@ -278,7 +278,7 @@ static bool d3d11_copyFrame(Texture * tex, ID3D11Texture2D * src)
else else
copyFrameFull(tex, src); copyFrameFull(tex, src);
ID3D11DeviceContext_Flush(dxgi->deviceContext); ID3D11DeviceContext_Flush(*dxgi->deviceContext);
}); });
return true; return true;
} }
@ -299,7 +299,7 @@ static CaptureResult d3d11_mapTexture(Texture * tex)
HRESULT status; HRESULT status;
INTERLOCKED_SECTION(dxgi->deviceContextLock, { INTERLOCKED_SECTION(dxgi->deviceContextLock, {
status = ID3D11DeviceContext_Map(dxgi->deviceContext, status = ID3D11DeviceContext_Map(*dxgi->deviceContext,
(ID3D11Resource *)teximpl->cpu, 0, D3D11_MAP_READ, 0x100000L, &map); (ID3D11Resource *)teximpl->cpu, 0, D3D11_MAP_READ, 0x100000L, &map);
}); });
if (status == DXGI_ERROR_WAS_STILL_DRAWING) if (status == DXGI_ERROR_WAS_STILL_DRAWING)
@ -333,7 +333,7 @@ static void d3d11_unmapTexture(Texture * tex)
struct D3D11TexImpl * teximpl = TEXIMPL(*tex); struct D3D11TexImpl * teximpl = TEXIMPL(*tex);
INTERLOCKED_SECTION(dxgi->deviceContextLock, { INTERLOCKED_SECTION(dxgi->deviceContextLock, {
ID3D11DeviceContext_Unmap(dxgi->deviceContext, ID3D11DeviceContext_Unmap(*dxgi->deviceContext,
(ID3D11Resource *)teximpl->cpu, 0); (ID3D11Resource *)teximpl->cpu, 0);
}); });
tex->map = NULL; tex->map = NULL;

View File

@ -43,6 +43,7 @@
#include <versionhelpers.h> #include <versionhelpers.h>
#include <dwmapi.h> #include <dwmapi.h>
#include "com_ref.h"
#include "dxgi_capture.h" #include "dxgi_capture.h"
#include "util.h" #include "util.h"
@ -256,6 +257,7 @@ static bool dxgi_create(CaptureGetPointerBuffer getPointerBufferFn, CapturePostP
this->texture = calloc(this->maxTextures, sizeof(*this->texture)); this->texture = calloc(this->maxTextures, sizeof(*this->texture));
this->getPointerBufferFn = getPointerBufferFn; this->getPointerBufferFn = getPointerBufferFn;
this->postPointerBufferFn = postPointerBufferFn; this->postPointerBufferFn = postPointerBufferFn;
return true; return true;
} }
@ -263,6 +265,17 @@ static bool dxgi_init(void)
{ {
DEBUG_ASSERT(this); DEBUG_ASSERT(this);
if (!comRef_init(
20 + this->maxTextures * 2, //max total globals
20 //max total locals
))
{
DEBUG_ERROR("failed to intialize the comRef tracking");
return false;
}
comRef_scopePush();
this->desktop = OpenInputDesktop(0, FALSE, GENERIC_READ); this->desktop = OpenInputDesktop(0, FALSE, GENERIC_READ);
if (!this->desktop) if (!this->desktop)
DEBUG_WINERROR("Failed to open the desktop", GetLastError()); DEBUG_WINERROR("Failed to open the desktop", GetLastError());
@ -295,7 +308,9 @@ static bool dxgi_init(void)
lgResetEvent(this->frameEvent); lgResetEvent(this->frameEvent);
status = CreateDXGIFactory2(this->debug ? DXGI_CREATE_FACTORY_DEBUG : 0, status = CreateDXGIFactory2(this->debug ? DXGI_CREATE_FACTORY_DEBUG : 0,
&IID_IDXGIFactory1, (void **)&this->factory); &IID_IDXGIFactory1,
(void **)comRef_newGlobal(&this->factory));
if (FAILED(status)) if (FAILED(status))
{ {
DEBUG_WINERROR("Failed to create DXGIFactory1", status); DEBUG_WINERROR("Failed to create DXGIFactory1", status);
@ -305,10 +320,17 @@ static bool dxgi_init(void)
const char * optAdapter = option_get_string("dxgi", "adapter"); const char * optAdapter = option_get_string("dxgi", "adapter");
const char * optOutput = option_get_string("dxgi", "output" ); const char * optOutput = option_get_string("dxgi", "output" );
for (int i = 0; IDXGIFactory1_EnumAdapters1(this->factory, i, &this->adapter) != DXGI_ERROR_NOT_FOUND; ++i) comRef_defineLocal(IDXGIAdapter1, adapter);
comRef_defineLocal(IDXGIOutput , output );
for (
int i = 0;
IDXGIFactory1_EnumAdapters1(*this->factory, i, adapter)
!= DXGI_ERROR_NOT_FOUND;
++i, comRef_release(adapter))
{ {
DXGI_ADAPTER_DESC1 adapterDesc; DXGI_ADAPTER_DESC1 adapterDesc;
status = IDXGIAdapter1_GetDesc1(this->adapter, &adapterDesc); status = IDXGIAdapter1_GetDesc1(*adapter, &adapterDesc);
if (FAILED(status)) if (FAILED(status))
{ {
DEBUG_WINERROR("Failed to get the device description", status); DEBUG_WINERROR("Failed to get the device description", status);
@ -326,9 +348,6 @@ static bool dxgi_init(void)
{ {
DEBUG_INFO("Not using unsupported adapter: %ls", DEBUG_INFO("Not using unsupported adapter: %ls",
adapterDesc.Description); adapterDesc.Description);
IDXGIAdapter1_Release(this->adapter);
this->adapter = NULL;
continue; continue;
} }
@ -342,9 +361,6 @@ static bool dxgi_init(void)
{ {
DEBUG_INFO("Not using adapter: %ls", adapterDesc.Description); DEBUG_INFO("Not using adapter: %ls", adapterDesc.Description);
free(desc); free(desc);
IDXGIAdapter1_Release(this->adapter);
this->adapter = NULL;
continue; continue;
} }
free(desc); free(desc);
@ -352,9 +368,12 @@ static bool dxgi_init(void)
DEBUG_INFO("Adapter matched, trying: %ls", adapterDesc.Description); DEBUG_INFO("Adapter matched, trying: %ls", adapterDesc.Description);
} }
for (int n = 0; IDXGIAdapter1_EnumOutputs(this->adapter, n, &this->output) != DXGI_ERROR_NOT_FOUND; ++n) for (
int n = 0;
IDXGIAdapter1_EnumOutputs(*adapter, n, output) != DXGI_ERROR_NOT_FOUND;
++n, comRef_release(output))
{ {
IDXGIOutput_GetDesc(this->output, &outputDesc); IDXGIOutput_GetDesc(*output, &outputDesc);
if (optOutput) if (optOutput)
{ {
const size_t s = (wcslen(outputDesc.DeviceName)+1) * 2; const size_t s = (wcslen(outputDesc.DeviceName)+1) * 2;
@ -365,7 +384,7 @@ static bool dxgi_init(void)
{ {
DEBUG_INFO("Not using adapter output: %ls", outputDesc.DeviceName); DEBUG_INFO("Not using adapter output: %ls", outputDesc.DeviceName);
free(desc); free(desc);
goto next_output; continue;
} }
free(desc); free(desc);
@ -374,27 +393,23 @@ static bool dxgi_init(void)
if (outputDesc.AttachedToDesktop) if (outputDesc.AttachedToDesktop)
break; break;
next_output:
IDXGIOutput_Release(this->output);
this->output = NULL;
} }
if (this->output) if (*output)
break; break;
IDXGIAdapter1_Release(this->adapter);
this->adapter = NULL;
} }
if (!this->output) if (!*output)
{ {
DEBUG_ERROR("Failed to locate a valid output device"); DEBUG_ERROR("Failed to locate a valid output device");
goto fail; goto fail;
} }
comRef_toGlobal(this->adapter, adapter);
comRef_toGlobal(this->output , output );
DXGI_ADAPTER_DESC1 adapterDesc; DXGI_ADAPTER_DESC1 adapterDesc;
IDXGIAdapter1_GetDesc1(this->adapter, &adapterDesc); IDXGIAdapter1_GetDesc1(*this->adapter, &adapterDesc);
DEBUG_INFO("Device Name : %ls" , outputDesc.DeviceName); DEBUG_INFO("Device Name : %ls" , outputDesc.DeviceName);
DEBUG_INFO("Device Description: %ls" , adapterDesc.Description); DEBUG_INFO("Device Description: %ls" , adapterDesc.Description);
DEBUG_INFO("Device Vendor ID : 0x%x" , adapterDesc.VendorId); DEBUG_INFO("Device Vendor ID : 0x%x" , adapterDesc.VendorId);
@ -440,8 +455,10 @@ next_output:
featureLevelCount = ARRAY_LENGTH(win8); featureLevelCount = ARRAY_LENGTH(win8);
} }
IDXGIAdapter * tmp; comRef_defineLocal(IDXGIAdapter, tmp);
status = IDXGIAdapter1_QueryInterface(this->adapter, &IID_IDXGIAdapter, (void **)&tmp); status = IDXGIAdapter1_QueryInterface(
*this->adapter, &IID_IDXGIAdapter, (void **)tmp);
if (FAILED(status)) if (FAILED(status))
{ {
DEBUG_ERROR("Failed to query IDXGIAdapter interface"); DEBUG_ERROR("Failed to query IDXGIAdapter interface");
@ -449,20 +466,18 @@ next_output:
} }
status = D3D11CreateDevice( status = D3D11CreateDevice(
tmp, *tmp,
D3D_DRIVER_TYPE_UNKNOWN, D3D_DRIVER_TYPE_UNKNOWN,
NULL, NULL,
D3D11_CREATE_DEVICE_VIDEO_SUPPORT, D3D11_CREATE_DEVICE_VIDEO_SUPPORT,
featureLevels, featureLevelCount, featureLevels, featureLevelCount,
D3D11_SDK_VERSION, D3D11_SDK_VERSION,
&this->device, (ID3D11Device **)comRef_newGlobal(&this->device),
&this->featureLevel, &this->featureLevel,
&this->deviceContext); (ID3D11DeviceContext **)comRef_newGlobal(&this->deviceContext));
LG_LOCK_INIT(this->deviceContextLock); LG_LOCK_INIT(this->deviceContextLock);
IDXGIAdapter_Release(tmp);
if (FAILED(status)) if (FAILED(status))
{ {
DEBUG_WINERROR("Failed to create D3D11 device", status); DEBUG_WINERROR("Failed to create D3D11 device", status);
@ -515,27 +530,32 @@ next_output:
// try to reduce the latency // try to reduce the latency
{ {
IDXGIDevice1 * dxgi; comRef_defineLocal(IDXGIDevice1, dxgi);
status = ID3D11Device_QueryInterface(this->device, &IID_IDXGIDevice1, (void **)&dxgi); status = ID3D11Device_QueryInterface(
*this->device, &IID_IDXGIDevice1, (void **)dxgi);
if (FAILED(status)) if (FAILED(status))
{ {
DEBUG_WINERROR("failed to query DXGI interface from device", status); DEBUG_WINERROR("failed to query DXGI interface from device", status);
goto fail; goto fail;
} }
IDXGIDevice1_SetMaximumFrameLatency(dxgi, 1); IDXGIDevice1_SetMaximumFrameLatency(*dxgi, 1);
IDXGIDevice1_Release(dxgi);
} }
IDXGIOutput5 * output5 = NULL; comRef_defineLocal(IDXGIOutput5, output5);
status = IDXGIOutput_QueryInterface(this->output, &IID_IDXGIOutput5, (void **)&output5); status = IDXGIOutput_QueryInterface(
*this->output, &IID_IDXGIOutput5, (void **)output5);
if (FAILED(status)) if (FAILED(status))
{ {
DEBUG_WARN("IDXGIOutput5 is not available, please update windows for improved performance!"); DEBUG_WARN("IDXGIOutput5 is not available, please update windows for improved performance!");
DEBUG_WARN("Falling back to IDXIGOutput1"); DEBUG_WARN("Falling back to IDXIGOutput1");
IDXGIOutput1 * output1 = NULL; comRef_defineLocal(IDXGIOutput1, output1);
status = IDXGIOutput_QueryInterface(this->output, &IID_IDXGIOutput1, (void **)&output1); status = IDXGIOutput_QueryInterface(
*this->output, &IID_IDXGIOutput1, (void **)output1);
if (FAILED(status)) if (FAILED(status))
{ {
DEBUG_ERROR("Failed to query IDXGIOutput1 from the output"); DEBUG_ERROR("Failed to query IDXGIOutput1 from the output");
@ -545,7 +565,10 @@ next_output:
// we try this twice in case we still get an error on re-initialization // we try this twice in case we still get an error on re-initialization
for (int i = 0; i < 2; ++i) for (int i = 0; i < 2; ++i)
{ {
status = IDXGIOutput1_DuplicateOutput(output1, (IUnknown *)this->device, &this->dup); status = IDXGIOutput1_DuplicateOutput(
*output1, (IUnknown *)*this->device,
(IDXGIOutputDuplication **)comRef_newGlobal(&this->dup));
if (SUCCEEDED(status)) if (SUCCEEDED(status))
break; break;
Sleep(200); Sleep(200);
@ -554,10 +577,8 @@ next_output:
if (FAILED(status)) if (FAILED(status))
{ {
DEBUG_WINERROR("DuplicateOutput Failed", status); DEBUG_WINERROR("DuplicateOutput Failed", status);
IDXGIOutput1_Release(output1);
goto fail; goto fail;
} }
IDXGIOutput1_Release(output1);
} }
else else
{ {
@ -572,12 +593,12 @@ next_output:
for (int i = 0; i < 2; ++i) for (int i = 0; i < 2; ++i)
{ {
status = IDXGIOutput5_DuplicateOutput1( status = IDXGIOutput5_DuplicateOutput1(
output5, *output5,
(IUnknown *)this->device, (IUnknown *)*this->device,
0, 0,
ARRAY_LENGTH(supportedFormats), ARRAY_LENGTH(supportedFormats),
supportedFormats, supportedFormats,
&this->dup); (IDXGIOutputDuplication **)comRef_newGlobal(&this->dup));
if (SUCCEEDED(status)) if (SUCCEEDED(status))
break; break;
@ -592,22 +613,22 @@ next_output:
if (FAILED(status)) if (FAILED(status))
{ {
DEBUG_WINERROR("DuplicateOutput1 Failed", status); DEBUG_WINERROR("DuplicateOutput1 Failed", status);
IDXGIOutput5_Release(output5);
goto fail; goto fail;
} }
IDXGIOutput6 * output6 = NULL; comRef_defineLocal(IDXGIOutput6, output6);
status = IDXGIOutput_QueryInterface(this->output, &IID_IDXGIOutput6, (void **)&output6); status = IDXGIOutput_QueryInterface(
*this->output, &IID_IDXGIOutput6, (void **)output6);
if (SUCCEEDED(status)) if (SUCCEEDED(status))
{ {
DXGI_OUTPUT_DESC1 desc1; DXGI_OUTPUT_DESC1 desc1;
IDXGIOutput6_GetDesc1(output6, &desc1); IDXGIOutput6_GetDesc1(*output6, &desc1);
this->dxgiColorSpace = desc1.ColorSpace; this->dxgiColorSpace = desc1.ColorSpace;
if (!getDisplayPathInfo(desc1.Monitor, &this->displayPathInfo)) if (!getDisplayPathInfo(desc1.Monitor, &this->displayPathInfo))
{ {
DEBUG_ERROR("Failed to get the display path info"); DEBUG_ERROR("Failed to get the display path info");
IDXGIOutput6_Release(output6);
goto fail; goto fail;
} }
this->sdrWhiteLevel = getSDRWhiteLevel(&this->displayPathInfo); this->sdrWhiteLevel = getSDRWhiteLevel(&this->displayPathInfo);
@ -617,47 +638,41 @@ next_output:
DEBUG_INFO("Min/Max Luminance : %f/%f", desc1.MinLuminance, desc1.MaxLuminance); DEBUG_INFO("Min/Max Luminance : %f/%f", desc1.MinLuminance, desc1.MaxLuminance);
DEBUG_INFO("Frame Luminance : %f" , desc1.MaxFullFrameLuminance); DEBUG_INFO("Frame Luminance : %f" , desc1.MaxFullFrameLuminance);
DEBUG_INFO("SDR White Level : %f" , this->sdrWhiteLevel); DEBUG_INFO("SDR White Level : %f" , this->sdrWhiteLevel);
IDXGIOutput6_Release(output6);
} }
IDXGIOutput5_Release(output5);
} }
{ {
DXGI_OUTDUPL_DESC dupDesc; DXGI_OUTDUPL_DESC dupDesc;
IDXGIOutputDuplication_GetDesc(this->dup, &dupDesc); IDXGIOutputDuplication_GetDesc(*this->dup, &dupDesc);
DEBUG_INFO("Source Format : %s", getDXGIFormatStr(dupDesc.ModeDesc.Format)); DEBUG_INFO("Source Format : %s", getDXGIFormatStr(dupDesc.ModeDesc.Format));
DXGI_OUTDUPL_FRAME_INFO frameInfo; DXGI_OUTDUPL_FRAME_INFO frameInfo;
IDXGIResource * res; comRef_defineLocal(IDXGIResource, res);
if (FAILED(status = IDXGIOutputDuplication_AcquireNextFrame(this->dup,
INFINITE, &frameInfo, &res))) if (FAILED(status = IDXGIOutputDuplication_AcquireNextFrame(*this->dup,
INFINITE, &frameInfo, res)))
{ {
DEBUG_WINERROR("AcquireNextFrame Failed", status); DEBUG_WINERROR("AcquireNextFrame Failed", status);
goto fail; goto fail;
} }
ID3D11Texture2D * src; comRef_defineLocal(ID3D11Texture2D, src);
if (FAILED(status = IDXGIResource_QueryInterface(res, &IID_ID3D11Texture2D, if (FAILED(status = IDXGIResource_QueryInterface(*res, &IID_ID3D11Texture2D,
(void **)&src))) (void **)src)))
{ {
DEBUG_WINERROR("ResourceQueryInterface failed", status); DEBUG_WINERROR("ResourceQueryInterface failed", status);
IDXGIResource_Release(res); IDXGIOutputDuplication_ReleaseFrame(*this->dup);
IDXGIOutputDuplication_ReleaseFrame(this->dup);
goto fail; goto fail;
} }
D3D11_TEXTURE2D_DESC desc; D3D11_TEXTURE2D_DESC desc;
ID3D11Texture2D_GetDesc(src, &desc); ID3D11Texture2D_GetDesc(*src, &desc);
this->dxgiSrcFormat = desc.Format; this->dxgiSrcFormat = desc.Format;
this->dxgiFormat = desc.Format; this->dxgiFormat = desc.Format;
DEBUG_INFO("Capture Format : %s", getDXGIFormatStr(desc.Format)); DEBUG_INFO("Capture Format : %s", getDXGIFormatStr(desc.Format));
ID3D11Texture2D_Release(src); IDXGIOutputDuplication_ReleaseFrame(*this->dup);
IDXGIResource_Release(res);
IDXGIOutputDuplication_ReleaseFrame(this->dup);
this->hdr = this->dxgiColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020; this->hdr = this->dxgiColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
} }
@ -756,8 +771,8 @@ next_output:
.MiscFlags = 0 .MiscFlags = 0
}; };
status = ID3D11Device_CreateTexture2D(this->device, &hdrTexDesc, NULL, status = ID3D11Device_CreateTexture2D(*this->device, &hdrTexDesc, NULL,
&this->texture[i].hdrTex); (ID3D11Texture2D **)comRef_newGlobal(&this->texture[i].hdrTex));
if (FAILED(status)) if (FAILED(status))
{ {
@ -765,11 +780,10 @@ next_output:
goto fail; goto fail;
} }
status = ID3D11Device_CreateRenderTargetView(this->device, status = ID3D11Device_CreateRenderTargetView(*this->device,
(ID3D11Resource *)this->texture[i].hdrTex, NULL, (ID3D11Resource *)*this->texture[i].hdrTex, NULL,
&this->texture[i].renderTarget); (ID3D11RenderTargetView **)comRef_newGlobal(
&this->texture[i].renderTarget));
ID3D11Texture2D_Release(this->texture[i].hdrTex);
if (FAILED(status)) if (FAILED(status))
{ {
@ -789,7 +803,7 @@ next_output:
.MinDepth = 0.0f, .MinDepth = 0.0f,
.MaxDepth = 1.0f, .MaxDepth = 1.0f,
}; };
ID3D11DeviceContext_RSSetViewports(this->deviceContext, 1, &vp); ID3D11DeviceContext_RSSetViewports(*this->deviceContext, 1, &vp);
static const char * vshader = static const char * vshader =
"void main(\n" "void main(\n"
@ -834,18 +848,16 @@ next_output:
" return color;\n" " return color;\n"
"}\n"; "}\n";
ID3DBlob * byteCode; comRef_defineLocal(ID3DBlob, byteCode);
if (!compileShader(&byteCode, "main", "vs_5_0", vshader)) if (!compileShader(byteCode, "main", "vs_5_0", vshader))
goto fail; goto fail;
status = ID3D11Device_CreateVertexShader( status = ID3D11Device_CreateVertexShader(
this->device, *this->device,
ID3D10Blob_GetBufferPointer(byteCode), ID3D10Blob_GetBufferPointer(*byteCode),
ID3D10Blob_GetBufferSize (byteCode), ID3D10Blob_GetBufferSize (*byteCode),
NULL, NULL,
&this->vertexShader); (ID3D11VertexShader **)comRef_newGlobal(&this->vertexShader));
ID3D10Blob_Release(byteCode);
if (FAILED(status)) if (FAILED(status))
{ {
@ -853,17 +865,16 @@ next_output:
goto fail; goto fail;
} }
if (!compileShader(&byteCode, "main", "ps_5_0", pshader)) comRef_release(byteCode);
if (!compileShader(byteCode, "main", "ps_5_0", pshader))
goto fail; goto fail;
status = ID3D11Device_CreatePixelShader( status = ID3D11Device_CreatePixelShader(
this->device, *this->device,
ID3D10Blob_GetBufferPointer(byteCode), ID3D10Blob_GetBufferPointer(*byteCode),
ID3D10Blob_GetBufferSize (byteCode), ID3D10Blob_GetBufferSize (*byteCode),
NULL, NULL,
&this->pixelShader); (ID3D11PixelShader **)comRef_newGlobal(&this->pixelShader));
ID3D10Blob_Release(byteCode);
if (FAILED(status)) if (FAILED(status))
{ {
@ -883,7 +894,8 @@ next_output:
}; };
status = ID3D11Device_CreateSamplerState( status = ID3D11Device_CreateSamplerState(
this->device, &samplerDesc, &this->samplerState); *this->device, &samplerDesc,
(ID3D11SamplerState **)comRef_newGlobal(&this->samplerState));
if (FAILED(status)) if (FAILED(status))
{ {
@ -905,7 +917,8 @@ next_output:
D3D11_SUBRESOURCE_DATA initData = { .pSysMem = &consts }; D3D11_SUBRESOURCE_DATA initData = { .pSysMem = &consts };
status = ID3D11Device_CreateBuffer( status = ID3D11Device_CreateBuffer(
this->device, &bufferDesc, &initData, &this->constBuffer); *this->device, &bufferDesc, &initData,
(ID3D11Buffer **)comRef_newGlobal(&this->constBuffer));
if (FAILED(status)) if (FAILED(status))
{ {
@ -920,9 +933,12 @@ next_output:
QueryPerformanceFrequency(&this->perfFreq) ; QueryPerformanceFrequency(&this->perfFreq) ;
QueryPerformanceCounter (&this->frameTime); QueryPerformanceCounter (&this->frameTime);
this->initialized = true; this->initialized = true;
comRef_scopePop();
return true; return true;
fail: fail:
comRef_scopePop();
dxgi_deinit(); dxgi_deinit();
return false; return false;
} }
@ -943,39 +959,9 @@ static bool dxgi_deinit(void)
this->backend->unmapTexture(this->texture + i); this->backend->unmapTexture(this->texture + i);
this->texture[i].map = NULL; this->texture[i].map = NULL;
} }
if (this->texture[i].renderTarget)
{
ID3D11RenderTargetView_Release(this->texture[i].renderTarget);
this->texture[i].renderTarget = NULL;
}
} }
if (this->pixelShader) if (this->dup && *this->dup)
{
ID3D11PixelShader_Release(this->pixelShader);
this->pixelShader = NULL;
}
if (this->vertexShader)
{
ID3D11VertexShader_Release(this->vertexShader);
this->vertexShader = NULL;
}
if (this->samplerState)
{
ID3D11SamplerState_Release(this->samplerState);
this->samplerState = NULL;
}
if (this->constBuffer)
{
ID3D11Buffer_Release(this->constBuffer);
this->constBuffer = NULL;
}
if (this->dup)
dxgi_releaseFrame(); dxgi_releaseFrame();
if (this->backend) if (this->backend)
@ -990,48 +976,6 @@ static bool dxgi_deinit(void)
this->texture[i].impl = NULL; this->texture[i].impl = NULL;
} }
if (this->dup)
{
IDXGIOutputDuplication_Release(this->dup);
this->dup = NULL;
}
if (this->deviceContext)
{
ID3D11DeviceContext_Release(this->deviceContext);
this->deviceContext = NULL;
}
if (this->output)
{
IDXGIOutput_Release(this->output);
this->output = NULL;
}
if (this->device)
{
ID3D11Device_Release(this->device);
this->device = NULL;
}
if (this->adapter)
{
IDXGIAdapter1_Release(this->adapter);
this->adapter = NULL;
}
if (this->factory)
{
// if this doesn't free we have a memory leak
DWORD count = IDXGIFactory1_Release(this->factory);
this->factory = NULL;
if (count != 0)
{
DEBUG_ERROR("Factory release is %lu, there is a memory leak!", count);
return false;
}
}
LG_LOCK_FREE(this->deviceContextLock); LG_LOCK_FREE(this->deviceContextLock);
if (this->desktop) if (this->desktop)
@ -1041,6 +985,7 @@ static bool dxgi_deinit(void)
} }
this->initialized = false; this->initialized = false;
comRef_free();
return true; return true;
} }
@ -1099,7 +1044,7 @@ static void computeFrameDamage(Texture * tex)
// Compute dirty rectangles. // Compute dirty rectangles.
RECT dirtyRects[maxDamageRectsCount]; RECT dirtyRects[maxDamageRectsCount];
UINT dirtyRectsBufferSizeRequired; UINT dirtyRectsBufferSizeRequired;
if (FAILED(IDXGIOutputDuplication_GetFrameDirtyRects(this->dup, if (FAILED(IDXGIOutputDuplication_GetFrameDirtyRects(*this->dup,
sizeof(dirtyRects), dirtyRects, sizeof(dirtyRects), dirtyRects,
&dirtyRectsBufferSizeRequired))) &dirtyRectsBufferSizeRequired)))
return; return;
@ -1114,7 +1059,7 @@ static void computeFrameDamage(Texture * tex)
// Divide by two here since each move generates two dirty regions. // Divide by two here since each move generates two dirty regions.
DXGI_OUTDUPL_MOVE_RECT moveRects[(maxDamageRectsCount - dirtyRectsCount) / 2]; DXGI_OUTDUPL_MOVE_RECT moveRects[(maxDamageRectsCount - dirtyRectsCount) / 2];
UINT moveRectsBufferSizeRequired; UINT moveRectsBufferSizeRequired;
if (FAILED(IDXGIOutputDuplication_GetFrameMoveRects(this->dup, if (FAILED(IDXGIOutputDuplication_GetFrameMoveRects(*this->dup,
sizeof(moveRects), moveRects, sizeof(moveRects), moveRects,
&moveRectsBufferSizeRequired))) &moveRectsBufferSizeRequired)))
return; return;
@ -1171,16 +1116,17 @@ static CaptureResult dxgi_capture(void)
{ {
DEBUG_ASSERT(this); DEBUG_ASSERT(this);
DEBUG_ASSERT(this->initialized); DEBUG_ASSERT(this->initialized);
comRef_scopePush();
Texture * tex = NULL; Texture * tex = NULL;
CaptureResult result; CaptureResult result;
HRESULT status; HRESULT status;
DXGI_OUTDUPL_FRAME_INFO frameInfo; DXGI_OUTDUPL_FRAME_INFO frameInfo;
IDXGIResource * res; comRef_defineLocal(IDXGIResource, res);
bool copyFrame = false; bool copyFrame = false;
bool copyPointer = false; bool copyPointer = false;
ID3D11Texture2D * src = NULL; comRef_defineLocal(ID3D11Texture2D, src);
bool postPointer = false; bool postPointer = false;
CapturePointer pointer = { 0 }; CapturePointer pointer = { 0 };
@ -1190,7 +1136,7 @@ static CaptureResult dxgi_capture(void)
// release the prior frame // release the prior frame
result = dxgi_releaseFrame(); result = dxgi_releaseFrame();
if (result != CAPTURE_RESULT_OK) if (result != CAPTURE_RESULT_OK)
return result; goto exit;
// this is a bit of a hack as it causes this thread to block until the next // this is a bit of a hack as it causes this thread to block until the next
// present, by doing this we can allow the mouse updates to accumulate instead // present, by doing this we can allow the mouse updates to accumulate instead
@ -1202,18 +1148,20 @@ static CaptureResult dxgi_capture(void)
if (this->useAcquireLock) if (this->useAcquireLock)
{ {
LOCKED({ LOCKED({
status = IDXGIOutputDuplication_AcquireNextFrame(this->dup, 1, &frameInfo, &res); status = IDXGIOutputDuplication_AcquireNextFrame(
*this->dup, 1, &frameInfo, res);
}); });
} }
else else
status = IDXGIOutputDuplication_AcquireNextFrame(this->dup, 1000, &frameInfo, &res); status = IDXGIOutputDuplication_AcquireNextFrame(
*this->dup, 1000, &frameInfo, res);
result = dxgi_hResultToCaptureResult(status); result = dxgi_hResultToCaptureResult(status);
if (result != CAPTURE_RESULT_OK) if (result != CAPTURE_RESULT_OK)
{ {
if (result == CAPTURE_RESULT_ERROR) if (result == CAPTURE_RESULT_ERROR)
DEBUG_WINERROR("AcquireNextFrame failed", status); DEBUG_WINERROR("AcquireNextFrame failed", status);
return result; goto exit;
} }
this->needsRelease = true; this->needsRelease = true;
@ -1225,12 +1173,14 @@ static CaptureResult dxgi_capture(void)
if (tex->state == TEXTURE_STATE_UNUSED) if (tex->state == TEXTURE_STATE_UNUSED)
{ {
copyFrame = true; copyFrame = true;
status = IDXGIResource_QueryInterface(res, &IID_ID3D11Texture2D, (void **)&src); status = IDXGIResource_QueryInterface(
*res, &IID_ID3D11Texture2D, (void **)src);
if (FAILED(status)) if (FAILED(status))
{ {
DEBUG_WINERROR("Failed to get the texture from the dxgi resource", status); DEBUG_WINERROR("Failed to get the texture from the dxgi resource", status);
IDXGIResource_Release(res); result = CAPTURE_RESULT_ERROR;
return CAPTURE_RESULT_ERROR; goto exit;
} }
} }
else else
@ -1242,8 +1192,6 @@ static CaptureResult dxgi_capture(void)
} }
} }
IDXGIResource_Release(res);
// if the pointer shape has changed // if the pointer shape has changed
uint32_t bufferSize; uint32_t bufferSize;
if (frameInfo.PointerShapeBufferSize > 0) if (frameInfo.PointerShapeBufferSize > 0)
@ -1269,7 +1217,7 @@ static CaptureResult dxgi_capture(void)
if (this->hdr) if (this->hdr)
{ {
// setup the pixel shader input resource view // setup the pixel shader input resource view
ID3D11ShaderResourceView * inputSRV; comRef_defineLocal(ID3D11ShaderResourceView, inputSRV);
{ {
const D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = const D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc =
{ {
@ -1278,11 +1226,12 @@ static CaptureResult dxgi_capture(void)
.Texture2D.MipLevels = 1 .Texture2D.MipLevels = 1
}; };
status = ID3D11Device_CreateShaderResourceView( status = ID3D11Device_CreateShaderResourceView(
this->device, (ID3D11Resource *)src, &srvDesc, &inputSRV); *this->device, (ID3D11Resource *)*src, &srvDesc, inputSRV);
if (FAILED(status)) if (FAILED(status))
{ {
DEBUG_WINERROR("Failed to create the source resource view", status); DEBUG_WINERROR("Failed to create the source resource view", status);
return CAPTURE_RESULT_ERROR; result = CAPTURE_RESULT_ERROR;
goto exit;
} }
} }
@ -1297,48 +1246,45 @@ static CaptureResult dxgi_capture(void)
}; };
ID3D11DeviceContext_UpdateSubresource( ID3D11DeviceContext_UpdateSubresource(
this->deviceContext, (ID3D11Resource*)this->constBuffer, *this->deviceContext, (ID3D11Resource*)*this->constBuffer,
0, NULL, &consts, 0, 0); 0, NULL, &consts, 0, 0);
} }
ID3D11DeviceContext_VSSetShader( ID3D11DeviceContext_VSSetShader(
this->deviceContext, this->vertexShader, NULL, 0); *this->deviceContext, *this->vertexShader, NULL, 0);
ID3D11DeviceContext_PSSetShader( ID3D11DeviceContext_PSSetShader(
this->deviceContext, this->pixelShader, NULL, 0); *this->deviceContext, *this->pixelShader, NULL, 0);
ID3D11DeviceContext_PSSetShaderResources( ID3D11DeviceContext_PSSetShaderResources(
this->deviceContext, 0, 1, &inputSRV); *this->deviceContext, 0, 1, inputSRV);
ID3D11DeviceContext_PSSetSamplers( ID3D11DeviceContext_PSSetSamplers(
this->deviceContext, 0, 1, &this->samplerState); *this->deviceContext, 0, 1, this->samplerState);
ID3D11DeviceContext_PSSetConstantBuffers( ID3D11DeviceContext_PSSetConstantBuffers(
this->deviceContext, 0, 1, &this->constBuffer); *this->deviceContext, 0, 1, this->constBuffer);
ID3D11DeviceContext_OMSetRenderTargets( ID3D11DeviceContext_OMSetRenderTargets(
this->deviceContext, 1, &tex->renderTarget, NULL); *this->deviceContext, 1, tex->renderTarget, NULL);
ID3D11DeviceContext_IASetPrimitiveTopology(this->deviceContext, ID3D11DeviceContext_IASetPrimitiveTopology(
D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); *this->deviceContext, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
ID3D11DeviceContext_Draw(this->deviceContext, 4, 0); ID3D11DeviceContext_Draw(*this->deviceContext, 4, 0);
ID3D11ShaderResourceView_Release(inputSRV);
if (!this->backend->copyFrame(tex, tex->hdrTex)) if (!this->backend->copyFrame(tex, *tex->hdrTex))
{ {
ID3D11Texture2D_Release(src); result = CAPTURE_RESULT_ERROR;
return CAPTURE_RESULT_ERROR; goto exit;
} }
} }
else else
{ {
if (!this->backend->copyFrame(tex, src)) if (!this->backend->copyFrame(tex, *src))
{ {
ID3D11Texture2D_Release(src); result = CAPTURE_RESULT_ERROR;
return CAPTURE_RESULT_ERROR; goto exit;
} }
} }
ID3D11Texture2D_Release(src);
for (int i = 0; i < this->maxTextures; ++i) for (int i = 0; i < this->maxTextures; ++i)
{ {
Texture * t = this->texture + i; Texture * t = this->texture + i;
@ -1376,19 +1322,19 @@ static CaptureResult dxgi_capture(void)
{ {
LOCKED({ LOCKED({
status = IDXGIOutputDuplication_GetFramePointerShape( status = IDXGIOutputDuplication_GetFramePointerShape(
this->dup, bufferSize, pointerShape, &pointerShapeSize, &shapeInfo); *this->dup, bufferSize, pointerShape, &pointerShapeSize, &shapeInfo);
}); });
} }
else else
status = IDXGIOutputDuplication_GetFramePointerShape( status = IDXGIOutputDuplication_GetFramePointerShape(
this->dup, bufferSize, pointerShape, &pointerShapeSize, &shapeInfo); *this->dup, bufferSize, pointerShape, &pointerShapeSize, &shapeInfo);
result = dxgi_hResultToCaptureResult(status); result = dxgi_hResultToCaptureResult(status);
if (result != CAPTURE_RESULT_OK) if (result != CAPTURE_RESULT_OK)
{ {
if (result == CAPTURE_RESULT_ERROR) if (result == CAPTURE_RESULT_ERROR)
DEBUG_WINERROR("Failed to get the new pointer shape", status); DEBUG_WINERROR("Failed to get the new pointer shape", status);
return result; goto exit;
} }
switch(shapeInfo.Type) switch(shapeInfo.Type)
@ -1398,7 +1344,8 @@ static CaptureResult dxgi_capture(void)
case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MONOCHROME : pointer.format = CAPTURE_FMT_MONO ; break; case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MONOCHROME : pointer.format = CAPTURE_FMT_MONO ; break;
default: default:
DEBUG_ERROR("Unsupported cursor format"); DEBUG_ERROR("Unsupported cursor format");
return CAPTURE_RESULT_ERROR; result = CAPTURE_RESULT_ERROR;
goto exit;
} }
pointer.shapeUpdate = true; pointer.shapeUpdate = true;
@ -1442,7 +1389,10 @@ static CaptureResult dxgi_capture(void)
this->postPointerBufferFn(pointer); this->postPointerBufferFn(pointer);
} }
return CAPTURE_RESULT_OK; result = CAPTURE_RESULT_OK;
exit:
comRef_scopePop();
return result;
} }
static CaptureResult dxgi_waitFrame(CaptureFrame * frame, const size_t maxFrameSize) static CaptureResult dxgi_waitFrame(CaptureFrame * frame, const size_t maxFrameSize)
@ -1549,7 +1499,7 @@ static CaptureResult dxgi_releaseFrame(void)
this->backend->preRelease(); this->backend->preRelease();
HRESULT status; HRESULT status;
LOCKED({status = IDXGIOutputDuplication_ReleaseFrame(this->dup);}); LOCKED({status = IDXGIOutputDuplication_ReleaseFrame(*this->dup);});
switch(status) switch(status)
{ {
case S_OK: case S_OK:

View File

@ -47,8 +47,8 @@ typedef struct Texture
FrameDamageRect damageRects[KVMFR_MAX_DAMAGE_RECTS]; FrameDamageRect damageRects[KVMFR_MAX_DAMAGE_RECTS];
int32_t texDamageCount; int32_t texDamageCount;
FrameDamageRect texDamageRects[KVMFR_MAX_DAMAGE_RECTS]; FrameDamageRect texDamageRects[KVMFR_MAX_DAMAGE_RECTS];
ID3D11RenderTargetView * renderTarget; ID3D11RenderTargetView ** renderTarget;
ID3D11Texture2D * hdrTex; ID3D11Texture2D ** hdrTex;
void * impl; void * impl;
} }
@ -69,18 +69,18 @@ struct DXGIInterface
LARGE_INTEGER frameTime; LARGE_INTEGER frameTime;
bool stop; bool stop;
HDESK desktop; HDESK desktop;
IDXGIFactory1 * factory; IDXGIFactory1 ** factory;
IDXGIAdapter1 * adapter; IDXGIAdapter1 ** adapter;
IDXGIOutput * output; IDXGIOutput ** output;
ID3D11Device * device; ID3D11Device ** device;
ID3D11DeviceContext * deviceContext; ID3D11DeviceContext ** deviceContext;
LG_Lock deviceContextLock; LG_Lock deviceContextLock;
bool debug; bool debug;
bool useAcquireLock; bool useAcquireLock;
bool dwmFlush; bool dwmFlush;
bool disableDamage; bool disableDamage;
D3D_FEATURE_LEVEL featureLevel; D3D_FEATURE_LEVEL featureLevel;
IDXGIOutputDuplication * dup; IDXGIOutputDuplication ** dup;
int maxTextures; int maxTextures;
Texture * texture; Texture * texture;
int texRIndex; int texRIndex;
@ -92,10 +92,10 @@ struct DXGIInterface
DISPLAYCONFIG_PATH_INFO displayPathInfo; DISPLAYCONFIG_PATH_INFO displayPathInfo;
DXGI_COLOR_SPACE_TYPE dxgiColorSpace; DXGI_COLOR_SPACE_TYPE dxgiColorSpace;
float sdrWhiteLevel; float sdrWhiteLevel;
ID3D11Buffer * constBuffer; ID3D11Buffer ** constBuffer;
ID3D11PixelShader * pixelShader; ID3D11PixelShader ** pixelShader;
ID3D11VertexShader * vertexShader; ID3D11VertexShader ** vertexShader;
ID3D11SamplerState * samplerState; ID3D11SamplerState ** samplerState;
struct DXGICopyBackend * backend; struct DXGICopyBackend * backend;
CaptureGetPointerBuffer getPointerBufferFn; CaptureGetPointerBuffer getPointerBufferFn;