diff --git a/common/include/common/vector.h b/common/include/common/vector.h index 53911e03..478b5d96 100644 --- a/common/include/common/vector.h +++ b/common/include/common/vector.h @@ -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; diff --git a/host/platform/Windows/capture/DXGI/src/d3d11.c b/host/platform/Windows/capture/DXGI/src/d3d11.c index e2710b6b..38a78e71 100644 --- a/host/platform/Windows/capture/DXGI/src/d3d11.c +++ b/host/platform/Windows/capture/DXGI/src/d3d11.c @@ -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; diff --git a/host/platform/Windows/capture/DXGI/src/dxgi.c b/host/platform/Windows/capture/DXGI/src/dxgi.c index 8250b0c5..af6ef610 100644 --- a/host/platform/Windows/capture/DXGI/src/dxgi.c +++ b/host/platform/Windows/capture/DXGI/src/dxgi.c @@ -43,6 +43,7 @@ #include #include +#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: diff --git a/host/platform/Windows/capture/DXGI/src/dxgi_capture.h b/host/platform/Windows/capture/DXGI/src/dxgi_capture.h index 842b53a9..225dc8c6 100644 --- a/host/platform/Windows/capture/DXGI/src/dxgi_capture.h +++ b/host/platform/Windows/capture/DXGI/src/dxgi_capture.h @@ -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;