Skip to content

Commit

Permalink
Merge pull request #47 from BradyBrenot/dxgifixes
Browse files Browse the repository at this point in the history
fix two DXGI issues
  • Loading branch information
smasherprog authored Mar 13, 2018
2 parents 775d058 + 76b9e30 commit 4392dba
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 74 deletions.
1 change: 1 addition & 0 deletions include/SCCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ namespace Screen_Capture {
enum DUPL_RETURN { DUPL_RETURN_SUCCESS = 0, DUPL_RETURN_ERROR_EXPECTED = 1, DUPL_RETURN_ERROR_UNEXPECTED = 2 };
const int PixelStride = 4;
Monitor CreateMonitor(int index, int id, int h, int w, int ox, int oy, const std::string &n, float scale);
Monitor CreateMonitor(int index, int id, int adapter, int h, int w, int ox, int oy, const std::string &n, float scale);

Image Create(const ImageRect &imgrect, int pixelstride, int rowpadding, const unsigned char *data);
// this function will copy data from the src into the dst. The only requirement is that src must not be larger than dst, but it can be smaller
Expand Down
2 changes: 2 additions & 0 deletions include/ScreenCapture.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ namespace Screen_Capture {
struct Monitor {
int Id = INT32_MAX;
int Index = INT32_MAX;
int Adapter = INT32_MAX;
int Height = 0;
int Width = 0;
// Offsets are the number of pixels that a monitor can be from the origin. For example, users can shuffle their
Expand Down Expand Up @@ -68,6 +69,7 @@ namespace Screen_Capture {
SC_LITE_EXTERN int Index(const Monitor &mointor);
// unique identifier
SC_LITE_EXTERN int Id(const Monitor &mointor);
SC_LITE_EXTERN int Adapter(const Monitor &mointor);
SC_LITE_EXTERN int OffsetX(const Monitor &mointor);
SC_LITE_EXTERN int OffsetY(const Monitor &mointor);
SC_LITE_EXTERN const char *Name(const Monitor &mointor);
Expand Down
43 changes: 20 additions & 23 deletions include/windows/DXFrameProcessor.h
Original file line number Diff line number Diff line change
@@ -1,35 +1,32 @@
#pragma once
#include "SCCommon.h"
#include <DXGI.h>
#include <memory>
#include <wrl.h>

#define NOMINMAX
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <d3d11.h>
#include <dxgi1_2.h>
#include <wrl.h>

#pragma comment(lib,"dxgi.lib")
#pragma comment(lib,"d3d11.lib")
#pragma comment(lib, "dxgi.lib")
#pragma comment(lib, "d3d11.lib")

namespace SL {
namespace Screen_Capture {
class DXFrameProcessor: public BaseFrameProcessor {
Microsoft::WRL::ComPtr<ID3D11Device> Device;
Microsoft::WRL::ComPtr<ID3D11DeviceContext> DeviceContext;
Microsoft::WRL::ComPtr<ID3D11Texture2D> StagingSurf;

Microsoft::WRL::ComPtr<IDXGIOutputDuplication> OutputDuplication;
DXGI_OUTPUT_DESC OutputDesc;
UINT Output;
std::vector<BYTE> MetaDataBuffer;
Monitor SelectedMonitor;
namespace Screen_Capture {
class DXFrameProcessor : public BaseFrameProcessor {
Microsoft::WRL::ComPtr<ID3D11Device> Device;
Microsoft::WRL::ComPtr<ID3D11DeviceContext> DeviceContext;
Microsoft::WRL::ComPtr<ID3D11Texture2D> StagingSurf;

public:
DUPL_RETURN Init(std::shared_ptr<Thread_Data> data, Monitor& monitor);
DUPL_RETURN ProcessFrame(const Monitor& currentmonitorinfo);
Microsoft::WRL::ComPtr<IDXGIOutputDuplication> OutputDuplication;
DXGI_OUTPUT_DESC OutputDesc;
UINT Output;
std::vector<BYTE> MetaDataBuffer;
Monitor SelectedMonitor;

};
public:
DUPL_RETURN Init(std::shared_ptr<Thread_Data> data, Monitor &monitor);
DUPL_RETURN ProcessFrame(const Monitor &currentmonitorinfo);
};

}
}
} // namespace Screen_Capture
} // namespace SL
8 changes: 8 additions & 0 deletions src/SCCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,13 @@ namespace Screen_Capture {
return ret;
}

Monitor CreateMonitor(int index, int id, int adapter, int h, int w, int ox, int oy, const std::string &n, float scaling)
{
Monitor ret = CreateMonitor(index, id, h, w, ox, oy, n, scaling);
ret.Adapter = adapter;
return ret;
}

Image Create(const ImageRect &imgrect, int pixelstride, int rowpadding, const unsigned char *data)
{
Image ret;
Expand All @@ -149,6 +156,7 @@ namespace Screen_Capture {
}
int Index(const Monitor &mointor) { return mointor.Index; }
int Id(const Monitor &mointor) { return mointor.Id; }
int Adapter(const Monitor &mointor) { return mointor.Adapter; }
int OffsetX(const Monitor &mointor) { return mointor.OffsetX; }
int OffsetY(const Monitor &mointor) { return mointor.OffsetY; }
const char *Name(const Monitor &mointor) { return mointor.Name; }
Expand Down
20 changes: 10 additions & 10 deletions src/windows/DXFrameProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
#include <atomic>
#include <iostream>
#include <memory>
#include <mutex>
#include <string>

#if (_MSC_VER >= 1700) && defined(_USING_V110_SDK71_)
Expand Down Expand Up @@ -137,21 +136,21 @@ namespace Screen_Capture {
return DUPL_RETURN_SUCCESS;
}

DUPL_RETURN Initialize(DUPLE_RESOURCES &r, ID3D11Device *device, const UINT output)
DUPL_RETURN Initialize(DUPLE_RESOURCES &r, ID3D11Device *device, const UINT adapter, const UINT output)
{
Microsoft::WRL::ComPtr<IDXGIFactory> pFactory;

// Get DXGI device
Microsoft::WRL::ComPtr<IDXGIDevice> DxgiDevice;
HRESULT hr = device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void **>(DxgiDevice.GetAddressOf()));
// Create a DXGIFactory object.
HRESULT hr = CreateDXGIFactory(__uuidof(IDXGIFactory), (void **)pFactory.GetAddressOf());
if (FAILED(hr)) {
return ProcessFailure(nullptr, L"Failed to QI for DXGI Device", L"Error", hr);
return ProcessFailure(nullptr, L"Failed to construct DXGIFactory", L"Error", hr);
}

// Get DXGI adapter
Microsoft::WRL::ComPtr<IDXGIAdapter> DxgiAdapter;
hr = DxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void **>(DxgiAdapter.GetAddressOf()));
hr = pFactory->EnumAdapters(adapter, DxgiAdapter.GetAddressOf());

if (FAILED(hr)) {
return ProcessFailure(device, L"Failed to get parent DXGI Adapter", L"Error", hr, SystemTransitionsExpectedErrors);
return ProcessFailure(device, L"Failed to get DXGI Adapter", L"Error", hr, SystemTransitionsExpectedErrors);
}

// Get output
Expand Down Expand Up @@ -179,6 +178,7 @@ namespace Screen_Capture {
r.Output = output;
return DUPL_RETURN_SUCCESS;
}

RECT ConvertRect(RECT Dirty, const DXGI_OUTPUT_DESC &DeskDesc)
{
RECT DestDirty = Dirty;
Expand Down Expand Up @@ -278,7 +278,7 @@ namespace Screen_Capture {
return ret;
}
DUPLE_RESOURCES dupl;
ret = Initialize(dupl, res.Device.Get(), Id(SelectedMonitor));
ret = Initialize(dupl, res.Device.Get(), Adapter(SelectedMonitor), Id(SelectedMonitor));
if (ret != DUPL_RETURN_SUCCESS) {
return ret;
}
Expand Down
87 changes: 50 additions & 37 deletions src/windows/GetMonitors.cpp
Original file line number Diff line number Diff line change
@@ -1,51 +1,64 @@
#include "SCCommon.h"
#include "ScreenCapture.h"
#define NOMINMAX
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <Windows.h>
#include <DXGI.h>

namespace SL {
namespace Screen_Capture {

float scaleFromDpi(int xdpi)
{
switch (xdpi) {
case 96:
return 1.0f;
break;
case 120:
return 1.25f;
break;
case 144:
return 1.5f;
break;
case 192:
return 2.0f;
break;
}

return 1.0f;
}

std::vector<Monitor> GetMonitors()
{
std::vector<Monitor> ret;
DISPLAY_DEVICEA dd;
ZeroMemory(&dd, sizeof(dd));
dd.cb = sizeof(dd);
for (auto i = 0; EnumDisplayDevicesA(NULL, i, &dd, 0); i++) {
// monitor must be attached to desktop and not a mirroring device

if (((dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) != 0 || (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) != 0) &&
(dd.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) == 0) {
DEVMODEA devMode;
devMode.dmSize = sizeof(devMode);
EnumDisplaySettingsA(dd.DeviceName, ENUM_CURRENT_SETTINGS, &devMode);
std::string name = dd.DeviceName;
auto mon = CreateDCA(dd.DeviceName, NULL, NULL, NULL);
auto xdpi = GetDeviceCaps(mon, LOGPIXELSX);
DeleteDC(mon);
auto scale = 1.0f;
switch (xdpi) {
case 96:
scale = 1.0f;
break;
case 120:
scale = 1.25f;
break;
case 144:
scale = 1.5f;
break;
case 192:
scale = 2.0f;
break;
default:
scale = 1.0f;
break;

IDXGIAdapter *pAdapter = nullptr;
IDXGIFactory *pFactory = nullptr;

// Create a DXGIFactory object.
if (SUCCEEDED(CreateDXGIFactory(__uuidof(IDXGIFactory), (void **)&pFactory))) {
for (UINT i = 0; pFactory->EnumAdapters(i, &pAdapter) != DXGI_ERROR_NOT_FOUND; ++i) {
IDXGIOutput *pOutput;

for (UINT j = 0; pAdapter->EnumOutputs(j, &pOutput) != DXGI_ERROR_NOT_FOUND; ++j) {
DXGI_OUTPUT_DESC desc;
pOutput->GetDesc(&desc);
pOutput->Release();
std::wstring wname = desc.DeviceName;
std::string name(wname.begin(), wname.end());
DEVMODEW devMode;
EnumDisplaySettingsW(desc.DeviceName, ENUM_CURRENT_SETTINGS, &devMode);

auto mon = CreateDCW(desc.DeviceName, NULL, NULL, NULL);
auto xdpi = GetDeviceCaps(mon, LOGPIXELSX);
DeleteDC(mon);
auto scale = scaleFromDpi(xdpi);

bool flipSides = desc.Rotation == DXGI_MODE_ROTATION_ROTATE90 || desc.Rotation == DXGI_MODE_ROTATION_ROTATE270;
ret.push_back(CreateMonitor(static_cast<int>(ret.size()), j, i, flipSides ? devMode.dmPelsWidth : devMode.dmPelsHeight,
flipSides ? devMode.dmPelsHeight : devMode.dmPelsWidth, devMode.dmPosition.x, devMode.dmPosition.y,
name, scale));
}
ret.push_back(CreateMonitor(static_cast<int>(ret.size()), i, devMode.dmPelsHeight, devMode.dmPelsWidth, devMode.dmPosition.x,
devMode.dmPosition.y, name, scale));
pAdapter->Release();
}
pFactory->Release();
}
return ret;
}
Expand Down
10 changes: 6 additions & 4 deletions src/windows/ThreadRunner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,14 @@ namespace SL {
std::cout << "Starting to Capture on Monitor " << Name(monitor) << std::endl;
std::cout << "Trying DirectX Desktop Duplication " << std::endl;
#endif
if (!TryCaptureMonitor<DXFrameProcessor>(data, monitor)) {//if DX is not supported, fallback to GDI capture
#if defined _DEBUG || !defined NDEBUG
std::cout << "DirectX Desktop Duplication not supprted, falling back to GDI Capturing . . ." << std::endl;
#endif
if (monitor.Adapter == -1)
{
TryCaptureMonitor<GDIFrameProcessor>(data, monitor);
}
else
{
TryCaptureMonitor<DXFrameProcessor>(data, monitor);
}
}

void RunCaptureWindow(std::shared_ptr<Thread_Data> data, Window wnd) {
Expand Down

0 comments on commit 4392dba

Please sign in to comment.