libobs-winrt,win-capture: Support desktop capture

Add display capture support via winrt_capture_init_monitor. Almost all
of the existing window capture code is reused.

Rename winrt_capture_init to winrt_capture_init_window for symmetry.
master
jpark37 2021-01-25 18:53:35 -08:00
parent b460f025ed
commit db35a022cd
3 changed files with 81 additions and 43 deletions

View File

@ -110,6 +110,7 @@ static bool get_client_box(HWND window, uint32_t width, uint32_t height,
struct winrt_capture {
HWND window;
bool client_area;
HMONITOR monitor;
bool capture_cursor;
BOOL cursor_visible;
@ -260,6 +261,53 @@ try {
}
#endif
static winrt::Windows::Graphics::Capture::GraphicsCaptureItem
winrt_capture_create_item(IGraphicsCaptureItemInterop *const interop_factory,
HWND window, HMONITOR monitor)
{
winrt::Windows::Graphics::Capture::GraphicsCaptureItem item = {nullptr};
if (window) {
try {
const HRESULT hr = interop_factory->CreateForWindow(
window,
winrt::guid_of<ABI::Windows::Graphics::Capture::
IGraphicsCaptureItem>(),
reinterpret_cast<void **>(
winrt::put_abi(item)));
if (FAILED(hr))
blog(LOG_ERROR, "CreateForWindow (0x%08X)", hr);
} catch (winrt::hresult_error &err) {
blog(LOG_ERROR, "CreateForWindow (0x%08X): %ls",
err.to_abi(), err.message().c_str());
} catch (...) {
blog(LOG_ERROR, "CreateForWindow (0x%08X)",
winrt::to_hresult());
}
} else {
assert(monitor);
try {
const HRESULT hr = interop_factory->CreateForMonitor(
monitor,
winrt::guid_of<ABI::Windows::Graphics::Capture::
IGraphicsCaptureItem>(),
reinterpret_cast<void **>(
winrt::put_abi(item)));
if (FAILED(hr))
blog(LOG_ERROR, "CreateForMonitor (0x%08X)",
hr);
} catch (winrt::hresult_error &err) {
blog(LOG_ERROR, "CreateForMonitor (0x%08X): %ls",
err.to_abi(), err.message().c_str());
} catch (...) {
blog(LOG_ERROR, "CreateForMonitor (0x%08X)",
winrt::to_hresult());
}
}
return item;
}
static void winrt_capture_device_loss_rebuild(void *device_void, void *data)
{
winrt_capture *capture = static_cast<winrt_capture *>(data);
@ -268,20 +316,9 @@ static void winrt_capture_device_loss_rebuild(void *device_void, void *data)
winrt::Windows::Graphics::Capture::GraphicsCaptureItem>();
auto interop_factory =
activation_factory.as<IGraphicsCaptureItemInterop>();
winrt::Windows::Graphics::Capture::GraphicsCaptureItem item = {nullptr};
try {
interop_factory->CreateForWindow(
capture->window,
winrt::guid_of<ABI::Windows::Graphics::Capture::
IGraphicsCaptureItem>(),
reinterpret_cast<void **>(winrt::put_abi(item)));
} catch (winrt::hresult_error &err) {
blog(LOG_ERROR, "CreateForWindow (0x%08X): %ls", err.to_abi(),
err.message().c_str());
} catch (...) {
blog(LOG_ERROR, "CreateForWindow (0x%08X)",
winrt::to_hresult());
}
winrt::Windows::Graphics::Capture::GraphicsCaptureItem item =
winrt_capture_create_item(interop_factory.get(),
capture->window, capture->monitor);
ID3D11Device *const d3d_device = (ID3D11Device *)device_void;
ComPtr<IDXGIDevice> dxgi_device;
@ -341,8 +378,10 @@ static void winrt_capture_device_loss_rebuild(void *device_void, void *data)
}
}
extern "C" EXPORT struct winrt_capture *
winrt_capture_init(BOOL cursor, HWND window, BOOL client_area)
static struct winrt_capture *winrt_capture_init_internal(BOOL cursor,
HWND window,
BOOL client_area,
HMONITOR monitor)
try {
ID3D11Device *const d3d_device = (ID3D11Device *)gs_get_device_obj();
ComPtr<IDXGIDevice> dxgi_device;
@ -365,26 +404,11 @@ try {
winrt::Windows::Graphics::Capture::GraphicsCaptureItem>();
auto interop_factory =
activation_factory.as<IGraphicsCaptureItemInterop>();
winrt::Windows::Graphics::Capture::GraphicsCaptureItem item = {nullptr};
try {
hr = interop_factory->CreateForWindow(
window,
winrt::guid_of<ABI::Windows::Graphics::Capture::
IGraphicsCaptureItem>(),
reinterpret_cast<void **>(winrt::put_abi(item)));
if (FAILED(hr)) {
blog(LOG_ERROR, "CreateForWindow (0x%08X)", hr);
return nullptr;
}
} catch (winrt::hresult_error &err) {
blog(LOG_ERROR, "CreateForWindow (0x%08X): %ls", err.to_abi(),
err.message().c_str());
winrt::Windows::Graphics::Capture::GraphicsCaptureItem item =
winrt_capture_create_item(interop_factory.get(), window,
monitor);
if (!item)
return nullptr;
} catch (...) {
blog(LOG_ERROR, "CreateForWindow (0x%08X)",
winrt::to_hresult());
return nullptr;
}
const winrt::Windows::Graphics::DirectX::Direct3D11::IDirect3DDevice
device = inspectable.as<winrt::Windows::Graphics::DirectX::
@ -420,6 +444,7 @@ try {
struct winrt_capture *capture = new winrt_capture{};
capture->window = window;
capture->client_area = client_area;
capture->monitor = monitor;
capture->capture_cursor = cursor && cursor_toggle_supported;
capture->cursor_visible = cursor;
capture->item = item;
@ -456,6 +481,18 @@ try {
return nullptr;
}
extern "C" EXPORT struct winrt_capture *
winrt_capture_init_window(BOOL cursor, HWND window, BOOL client_area)
{
return winrt_capture_init_internal(cursor, window, client_area, NULL);
}
extern "C" EXPORT struct winrt_capture *
winrt_capture_init_monitor(BOOL cursor, HMONITOR monitor)
{
return winrt_capture_init_internal(cursor, NULL, false, monitor);
}
extern "C" EXPORT void winrt_capture_free(struct winrt_capture *capture)
{
if (capture) {

View File

@ -11,8 +11,10 @@ extern "C" {
EXPORT BOOL winrt_capture_supported();
EXPORT BOOL winrt_capture_cursor_toggle_supported();
EXPORT struct winrt_capture *winrt_capture_init(BOOL cursor, HWND window,
BOOL client_area);
EXPORT struct winrt_capture *winrt_capture_init_window(BOOL cursor, HWND window,
BOOL client_area);
EXPORT struct winrt_capture *winrt_capture_init_monitor(BOOL cursor,
HMONITOR monitor);
EXPORT void winrt_capture_free(struct winrt_capture *capture);
EXPORT BOOL winrt_capture_active(const struct winrt_capture *capture);

View File

@ -28,9 +28,8 @@
typedef BOOL (*PFN_winrt_capture_supported)();
typedef BOOL (*PFN_winrt_capture_cursor_toggle_supported)();
typedef struct winrt_capture *(*PFN_winrt_capture_init)(BOOL cursor,
HWND window,
BOOL client_area);
typedef struct winrt_capture *(*PFN_winrt_capture_init_window)(
BOOL cursor, HWND window, BOOL client_area);
typedef void (*PFN_winrt_capture_free)(struct winrt_capture *capture);
typedef BOOL (*PFN_winrt_capture_active)(const struct winrt_capture *capture);
@ -46,7 +45,7 @@ struct winrt_exports {
PFN_winrt_capture_supported winrt_capture_supported;
PFN_winrt_capture_cursor_toggle_supported
winrt_capture_cursor_toggle_supported;
PFN_winrt_capture_init winrt_capture_init;
PFN_winrt_capture_init_window winrt_capture_init_window;
PFN_winrt_capture_free winrt_capture_free;
PFN_winrt_capture_active winrt_capture_active;
PFN_winrt_capture_show_cursor winrt_capture_show_cursor;
@ -224,7 +223,7 @@ static bool load_winrt_imports(struct winrt_exports *exports, void *module,
WINRT_IMPORT(winrt_capture_supported);
WINRT_IMPORT(winrt_capture_cursor_toggle_supported);
WINRT_IMPORT(winrt_capture_init);
WINRT_IMPORT(winrt_capture_init_window);
WINRT_IMPORT(winrt_capture_free);
WINRT_IMPORT(winrt_capture_active);
WINRT_IMPORT(winrt_capture_show_cursor);
@ -544,7 +543,7 @@ static void wc_tick(void *data, float seconds)
if (wc->window && (wc->capture_winrt == NULL)) {
if (!wc->previously_failed) {
wc->capture_winrt =
wc->exports.winrt_capture_init(
wc->exports.winrt_capture_init_window(
wc->cursor, wc->window,
wc->client_area);