瀏覽代碼

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.
jpark37 4 年之前
父節點
當前提交
db35a022cd
共有 3 個文件被更改,包括 81 次插入43 次删除
  1. 72 35
      libobs-winrt/winrt-capture.cpp
  2. 4 2
      libobs-winrt/winrt-capture.h
  3. 5 6
      plugins/win-capture/window-capture.c

+ 72 - 35
libobs-winrt/winrt-capture.cpp

@@ -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) {

+ 4 - 2
libobs-winrt/winrt-capture.h

@@ -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);

+ 5 - 6
plugins/win-capture/window-capture.c

@@ -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);