[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;
}
inline static size_t vector_capacity(Vector * vector)
{
return vector->capacity;
}
inline static void * vector_data(Vector * vector)
{
return vector->data;

View file

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

View file

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

View file

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