瀏覽代碼

libobs,libobs-opengl,libobs-d3d11: Add opengl gs_enum_adapters

This adds gs_enum_adapters and gs_get_adapter_count to the opengl
backend and promotes these to multiplatform graphics functions.

However we need to make an internal device change, device_enum_adapters
must pass in the current device on opengl to ensure that adapter #0 is
the display adapter. We do this to avoid changes to plugins already
checking against obs_video_info.adapter which is always 0 and expected
to be the device OBS was initialized on.

The actual implementation reports the dri render node (or /Software).
This allows plugins to query non-video features of the adapters like
VA-API/NVENC/etc or other cross device functionality. `/Software` is
chosen to avoid opening random files in the current directory if its
passed along as a file path like the regular dri render nodes.
Kurt Kartaltepe 1 年之前
父節點
當前提交
3e49e89611

+ 4 - 1
libobs-d3d11/d3d11-subsystem.cpp

@@ -1016,10 +1016,13 @@ EnumD3DAdapters(bool (*callback)(void *, const char *, uint32_t), void *param)
 	}
 }
 
-bool device_enum_adapters(bool (*callback)(void *param, const char *name,
+bool device_enum_adapters(gs_device_t *device,
+			  bool (*callback)(void *param, const char *name,
 					   uint32_t id),
 			  void *param)
 {
+	UNUSED_PARAMETER(device);
+
 	try {
 		EnumD3DAdapters(callback, param);
 		return true;

+ 47 - 0
libobs-opengl/gl-egl-common.c

@@ -204,6 +204,53 @@ struct gs_texture *gl_egl_create_texture_from_eglimage(
 	return texture;
 }
 
+bool gl_egl_enum_adapters(EGLDisplay display,
+			  bool (*callback)(void *param, const char *name,
+					   uint32_t id),
+			  void *param)
+{
+	EGLDeviceEXT display_dev;
+	if (eglQueryDisplayAttribEXT(display, EGL_DEVICE_EXT,
+				     (EGLAttrib *)&display_dev) &&
+	    eglGetError() == EGL_SUCCESS) {
+		const char *display_node = eglQueryDeviceStringEXT(
+			display_dev, EGL_DRM_RENDER_NODE_FILE_EXT);
+		if (eglGetError() != EGL_SUCCESS || display_node == NULL) {
+			display_node = "/Software";
+		}
+		if (!callback(param, display_node, 0)) {
+			return true;
+		}
+	}
+
+	EGLint num_devices = 0;
+	EGLDeviceEXT devices[32];
+	if (!eglQueryDevicesEXT(32, devices, &num_devices)) {
+		eglGetError();
+		return true;
+	}
+
+	for (int i = 0; i < num_devices; i++) {
+		const char *node = eglQueryDeviceStringEXT(
+			devices[i], EGL_DRM_RENDER_NODE_FILE_EXT);
+		if (node == NULL || eglGetError() != EGL_SUCCESS) {
+			// Do not enumerate additional software renderers.
+			continue;
+		}
+		if (!callback(param, node, i + 1)) {
+			return true;
+		}
+	}
+	return true;
+}
+
+uint32_t gs_get_adapter_count()
+{
+	EGLint num_devices = 0;
+	eglQueryDevicesEXT(0, NULL, &num_devices);
+	return 1 + num_devices; // Display + devices.
+}
+
 struct gs_texture *
 gl_egl_create_dmabuf_image(EGLDisplay egl_display, unsigned int width,
 			   unsigned int height, uint32_t drm_format,

+ 6 - 0
libobs-opengl/gl-egl-common.h

@@ -27,3 +27,9 @@ gl_egl_create_texture_from_pixmap(EGLDisplay egl_display, uint32_t width,
 				  uint32_t height,
 				  enum gs_color_format color_format,
 				  EGLint target, EGLClientBuffer pixmap);
+
+bool gl_egl_enum_adapters(EGLDisplay display,
+			  bool (*callback)(void *param, const char *name,
+					   uint32_t id),
+			  void *param);
+uint32_t gs_get_adapter_count();

+ 8 - 0
libobs-opengl/gl-nix.c

@@ -95,6 +95,14 @@ extern void device_leave_context(gs_device_t *device)
 	gl_vtable->device_leave_context(device);
 }
 
+extern bool device_enum_adapters(gs_device_t *device,
+				 bool (*callback)(void *param, const char *name,
+						  uint32_t id),
+				 void *param)
+{
+	return gl_vtable->device_enum_adapters(device, callback, param);
+}
+
 extern void *device_get_device_obj(gs_device_t *device)
 {
 	return gl_vtable->device_get_device_obj(device);

+ 5 - 0
libobs-opengl/gl-nix.h

@@ -73,4 +73,9 @@ struct gl_winsys_vtable {
 		gs_device_t *device, uint32_t width, uint32_t height,
 		enum gs_color_format color_format, uint32_t target,
 		void *pixmap);
+	bool (*device_enum_adapters)(gs_device_t *device,
+				     bool (*callback)(void *param,
+						      const char *name,
+						      uint32_t id),
+				     void *param);
 };

+ 10 - 0
libobs-opengl/gl-wayland-egl.c

@@ -397,6 +397,15 @@ static struct gs_texture *gl_wayland_egl_device_texture_create_from_pixmap(
 	return NULL;
 }
 
+static bool gl_wayland_egl_enum_adapters(gs_device_t *device,
+					 bool (*callback)(void *param,
+							  const char *name,
+							  uint32_t id),
+					 void *param)
+{
+	return gl_egl_enum_adapters(device->plat->display, callback, param);
+}
+
 static const struct gl_winsys_vtable egl_wayland_winsys_vtable = {
 	.windowinfo_create = gl_wayland_egl_windowinfo_create,
 	.windowinfo_destroy = gl_wayland_egl_windowinfo_destroy,
@@ -420,6 +429,7 @@ static const struct gl_winsys_vtable egl_wayland_winsys_vtable = {
 		gl_wayland_egl_device_query_dmabuf_modifiers_for_format,
 	.device_texture_create_from_pixmap =
 		gl_wayland_egl_device_texture_create_from_pixmap,
+	.device_enum_adapters = gl_wayland_egl_enum_adapters,
 };
 
 const struct gl_winsys_vtable *gl_wayland_egl_get_winsys_vtable(void)

+ 10 - 0
libobs-opengl/gl-x11-egl.c

@@ -612,6 +612,15 @@ static bool gl_x11_egl_device_query_dmabuf_modifiers_for_format(
 		plat->edisplay, drm_format, modifiers, n_modifiers);
 }
 
+static bool gl_x11_egl_enum_adapters(gs_device_t *device,
+				     bool (*callback)(void *param,
+						      const char *name,
+						      uint32_t id),
+				     void *param)
+{
+	return gl_egl_enum_adapters(device->plat->edisplay, callback, param);
+}
+
 static const struct gl_winsys_vtable egl_x11_winsys_vtable = {
 	.windowinfo_create = gl_x11_egl_windowinfo_create,
 	.windowinfo_destroy = gl_x11_egl_windowinfo_destroy,
@@ -635,6 +644,7 @@ static const struct gl_winsys_vtable egl_x11_winsys_vtable = {
 		gl_x11_egl_device_query_dmabuf_modifiers_for_format,
 	.device_texture_create_from_pixmap =
 		gl_x11_egl_device_texture_create_from_pixmap,
+	.device_enum_adapters = gl_x11_egl_enum_adapters,
 };
 
 const struct gl_winsys_vtable *gl_x11_egl_get_winsys_vtable(void)

+ 2 - 1
libobs/graphics/device-exports.h

@@ -25,7 +25,8 @@ extern "C" {
 
 EXPORT const char *device_get_name(void);
 EXPORT int device_get_type(void);
-EXPORT bool device_enum_adapters(bool (*callback)(void *param, const char *name,
+EXPORT bool device_enum_adapters(gs_device_t *device,
+				 bool (*callback)(void *param, const char *name,
 						  uint32_t id),
 				 void *param);
 EXPORT const char *device_preprocessor_name(void);

+ 2 - 1
libobs/graphics/graphics-imports.c

@@ -203,6 +203,8 @@ bool load_graphics_imports(struct gs_exports *exports, void *module,
 	GRAPHICS_IMPORT(device_debug_marker_begin);
 	GRAPHICS_IMPORT(device_debug_marker_end);
 
+	GRAPHICS_IMPORT_OPTIONAL(gs_get_adapter_count);
+
 	/* OSX/Cocoa specific functions */
 #ifdef __APPLE__
 	GRAPHICS_IMPORT(device_shared_texture_available);
@@ -222,7 +224,6 @@ bool load_graphics_imports(struct gs_exports *exports, void *module,
 	GRAPHICS_IMPORT_OPTIONAL(gs_duplicator_get_texture);
 	GRAPHICS_IMPORT_OPTIONAL(gs_duplicator_get_color_space);
 	GRAPHICS_IMPORT_OPTIONAL(gs_duplicator_get_sdr_white_level);
-	GRAPHICS_IMPORT_OPTIONAL(gs_get_adapter_count);
 	GRAPHICS_IMPORT_OPTIONAL(device_can_adapter_fast_clear);
 	GRAPHICS_IMPORT_OPTIONAL(device_texture_create_gdi);
 	GRAPHICS_IMPORT_OPTIONAL(gs_texture_get_dc);

+ 4 - 2
libobs/graphics/graphics-internal.h

@@ -26,7 +26,8 @@
 struct gs_exports {
 	const char *(*device_get_name)(void);
 	int (*device_get_type)(void);
-	bool (*device_enum_adapters)(bool (*callback)(void *, const char *,
+	bool (*device_enum_adapters)(gs_device_t *device,
+				     bool (*callback)(void *, const char *,
 						      uint32_t),
 				     void *);
 	const char *(*device_preprocessor_name)(void);
@@ -291,6 +292,8 @@ struct gs_exports {
 					  const float color[4]);
 	void (*device_debug_marker_end)(gs_device_t *device);
 
+	uint32_t (*gs_get_adapter_count)(void);
+
 #ifdef __APPLE__
 	/* OSX/Cocoa specific functions */
 	gs_texture_t *(*device_texture_create_from_iosurface)(gs_device_t *dev,
@@ -321,7 +324,6 @@ struct gs_exports {
 		gs_duplicator_t *duplicator);
 	float (*gs_duplicator_get_sdr_white_level)(gs_duplicator_t *duplicator);
 
-	uint32_t (*gs_get_adapter_count)(void);
 	bool (*device_can_adapter_fast_clear)(gs_device_t *device);
 
 	gs_texture_t *(*device_texture_create_gdi)(gs_device_t *device,

+ 12 - 11
libobs/graphics/graphics.c

@@ -82,7 +82,8 @@ void gs_enum_adapters(bool (*callback)(void *param, const char *name,
 		return;
 
 	if (graphics->exports.device_enum_adapters) {
-		if (graphics->exports.device_enum_adapters(callback, param)) {
+		if (graphics->exports.device_enum_adapters(graphics->device,
+							   callback, param)) {
 			return;
 		}
 	}
@@ -2986,6 +2987,16 @@ bool gs_texture_create_p010(gs_texture_t **tex_y, gs_texture_t **tex_uv,
 	return true;
 }
 
+uint32_t gs_get_adapter_count(void)
+{
+	if (!gs_valid("gs_get_adapter_count"))
+		return 0;
+	if (!thread_graphics->exports.gs_get_adapter_count)
+		return 0;
+
+	return thread_graphics->exports.gs_get_adapter_count();
+}
+
 #ifdef __APPLE__
 
 /** Platform specific functions */
@@ -3108,16 +3119,6 @@ bool gs_duplicator_update_frame(gs_duplicator_t *duplicator)
 	return thread_graphics->exports.gs_duplicator_update_frame(duplicator);
 }
 
-uint32_t gs_get_adapter_count(void)
-{
-	if (!gs_valid("gs_get_adapter_count"))
-		return 0;
-	if (!thread_graphics->exports.gs_get_adapter_count)
-		return 0;
-
-	return thread_graphics->exports.gs_get_adapter_count();
-}
-
 bool gs_can_adapter_fast_clear(void)
 {
 	if (!gs_valid("gs_can_adapter_fast_clear"))

+ 1 - 1
libobs/graphics/graphics.h

@@ -525,6 +525,7 @@ struct gs_init_data {
 
 EXPORT const char *gs_get_device_name(void);
 EXPORT int gs_get_device_type(void);
+EXPORT uint32_t gs_get_adapter_count(void);
 EXPORT void gs_enum_adapters(bool (*callback)(void *param, const char *name,
 					      uint32_t id),
 			     void *param);
@@ -929,7 +930,6 @@ EXPORT enum gs_color_space
 gs_duplicator_get_color_space(gs_duplicator_t *duplicator);
 EXPORT float gs_duplicator_get_sdr_white_level(gs_duplicator_t *duplicator);
 
-EXPORT uint32_t gs_get_adapter_count(void);
 EXPORT bool gs_can_adapter_fast_clear(void);
 
 /** creates a windows GDI-lockable texture */