I'm writing a small c++ app that uses Desktop Duplication API to get the display output. I've never done c programming before, and I got to where I am by staring at the win32 API documentation. https://learn.microsoft.com/en-us/windows/win32/api/dxgi1_2/
#include <iostream>
#pragma comment(lib, "windowsapp")
#include <roapi.h>
//#pragma comment(lib, "dxgi")
#include <dxgi1_2.h>
using namespace std;
int main()
{
cout << RoInitialize(RO_INIT_SINGLETHREADED);
// intermediate variables for casting
IDXGIOutput* pDisplay_old;
IDXGIFactory1* pFactory;
IDXGIAdapter1* pGPU;
IDXGIOutput1* pDisplay;
IDXGIOutputDuplication* pCapture;
DXGI_OUTDUPL_DESC captureDesc;
// create factory
if (CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&pFactory) != S_OK) return 1;
// get GPU
if (pFactory -> EnumAdapters1(0, &pGPU) != S_OK) return 1;
// get display
if (pGPU -> EnumOutputs(0, &pDisplay_old) != S_OK) return 1;
pDisplay = (IDXGIOutput1*)pDisplay_old;
DXGI_OUTDUPL_FRAME_INFO frameInfo;
IDXGIResource* pFrame;
HRESULT captureResult;
do
{
// create capture
// cout << pDisplay -> DuplicateOutput(pGPU, &pCapture);
//return 0;
if (pDisplay -> DuplicateOutput(pGPU, &pCapture) != S_OK) return 1;
pCapture -> GetDesc(&captureDesc);
cout << captureDesc.ModeDesc.Width << ' ' << captureDesc.ModeDesc.Height;
do
{
captureResult = pCapture -> AcquireNextFrame(2000, &frameInfo, &pFrame);
if (captureResult == S_OK)
{
cout << "HI";
captureResult = pCapture -> ReleaseFrame();
}
else if (captureResult == DXGI_ERROR_ACCESS_LOST) break;
else return 1;
}
while (true);
}
while (true);
}
I'm using visual studio 2022 witn only "desktop development with c++" enabled, on windows 11 insider build: 22623.1037 ni_release on a regular home PC with display, beyboard, mouse, etc
The code worked fine until DuplicateOutput(), when it complained E_NOINTERFACE. I'm certain there is an interface since index 0 for EnumAdapters1 and EnumOutputs are where the desktop is displayed, and I obviously have a display attached with the desktop. According to this guy https://devblogs.microsoft.com/oldnewthing/20041213-00/?p=37043, I need marshalling and apartments or something, so after more research, I tried RoInitialize() with both RO_INIT_SINGLETHREADED and RO_INIT_MULTITHREADED. Now, DuplicateOutput throws this exception
It seems to happen within the library itself, which makes me think that it's either not my fault or I really messed something up, probably the latter.
I'm really confused now, and would like some assistance, thanks!
EDIT: I replaced "pDisplay = (IDXGIOutput1*)pDisplay_old;" with "pDisplay_old -> QueryInterface(&pDisplay);", and I'm back to E_NOINTERFACE, but I think I'm on the right track, how do I fix this error?
EDIT2: I looked at a related question AcquireNextFrame not working (Desktop Duplication API & D3D11), and followed the answer to add D3D11CreateDevice to my code:
#include <iostream>
#pragma comment(lib, "dxgi")
#pragma comment(lib, "d3d11")
#include <d3d11.h>
#include <dxgi1_2.h>
using namespace std;
int main()
{
// intermediate variables for casting
IDXGIOutput* pDisplay_old;
IDXGIFactory1* pFactory;
IDXGIAdapter* pGPU;
ID3D11Device* pD3DDevice;
IDXGIDevice* pDevice;
IDXGIOutput1* pDisplay;
IDXGIOutputDuplication* pCapture;
DXGI_OUTDUPL_DESC captureDesc;
// create DXGI factory
if (CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&pFactory) != S_OK) return 1;
// get GPU adapter
if (pFactory -> EnumAdapters(0, &pGPU) != S_OK) return 2;
// create D3D11 device
D3D_FEATURE_LEVEL D3DFeatures [6]
{
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_9_3,
D3D_FEATURE_LEVEL_9_2,
D3D_FEATURE_LEVEL_9_1
};
cout << D3D11CreateDevice(pGPU, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, D3DFeatures, sizeof(D3DFeatures), D3D11_SDK_VERSION, &pD3DDevice, NULL, NULL); //!= S_OK) return 3;
return 0;
// get DXGI device from that
pD3DDevice -> QueryInterface(&pDevice);
// get display
if (pGPU -> EnumOutputs(0, &pDisplay_old) != S_OK) return 4;
pDisplay_old -> QueryInterface(&pDisplay);
DXGI_OUTDUPL_FRAME_INFO frameInfo;
IDXGIResource* pFrame;
HRESULT captureResult;
do
{
// create capture
cout << pDisplay -> DuplicateOutput(pD3DDevice, &pCapture);
return 0;
if (pDisplay -> DuplicateOutput(pGPU, &pCapture) != S_OK) return 5;
pCapture -> GetDesc(&captureDesc);
cout << captureDesc.ModeDesc.Width << ' ' << captureDesc.ModeDesc.Height;
do
{
captureResult = pCapture -> AcquireNextFrame(2000, &frameInfo, &pFrame);
if (captureResult == S_OK)
{
cout << "HI";
captureResult = pCapture -> ReleaseFrame();
}
else if (captureResult == DXGI_ERROR_ACCESS_LOST) break;
else return 6;
}
while (true);
}
while (true);
D3D11CreateDevice seems like a complex function and for me it keeps complaining invalid_arg. I'm not sure how to fix that