Ver código fonte

linux-capture: Add randr support

Add randr suport to the xshm plugin and prefer it over xinerama.

Add libxcb-xrandr0-dev as CI dependency
Gary Kramlich 6 anos atrás
pai
commit
758868093b

+ 1 - 0
CI/install-dependencies-linux-ubuntu16.sh

@@ -30,6 +30,7 @@ sudo apt-get install -y \
         libvlc-dev \
         libvlc-dev \
         libx11-dev \
         libx11-dev \
         libx264-dev \
         libx264-dev \
+        libxcb-randr0-dev \
         libxcb-shm0-dev \
         libxcb-shm0-dev \
         libxcb-xinerama0-dev \
         libxcb-xinerama0-dev \
         libxcomposite-dev \
         libxcomposite-dev \

+ 1 - 0
CI/install-dependencies-linux.sh

@@ -33,6 +33,7 @@ sudo apt-get install -y \
         libvlc-dev \
         libvlc-dev \
         libx11-dev \
         libx11-dev \
         libx264-dev \
         libx264-dev \
+        libxcb-randr0-dev \
         libxcb-shm0-dev \
         libxcb-shm0-dev \
         libxcb-xinerama0-dev \
         libxcb-xinerama0-dev \
         libxcomposite-dev \
         libxcomposite-dev \

+ 1 - 1
plugins/linux-capture/CMakeLists.txt

@@ -6,7 +6,7 @@ if(NOT X11_Xcomposite_FOUND)
 	return()
 	return()
 endif()
 endif()
 
 
-find_package(XCB COMPONENTS XCB SHM XFIXES XINERAMA REQUIRED)
+find_package(XCB COMPONENTS XCB RANDR SHM XFIXES XINERAMA REQUIRED)
 find_package(X11_XCB REQUIRED)
 find_package(X11_XCB REQUIRED)
 
 
 include_directories(SYSTEM
 include_directories(SYSTEM

+ 73 - 0
plugins/linux-capture/xhelpers.c

@@ -17,6 +17,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
 #include <stdint.h>
 #include <stdint.h>
 #include <sys/shm.h>
 #include <sys/shm.h>
+#include <xcb/randr.h>
 #include <xcb/xcb.h>
 #include <xcb/xcb.h>
 #include <xcb/xinerama.h>
 #include <xcb/xinerama.h>
 
 
@@ -95,6 +96,78 @@ fail:
 	return -1;
 	return -1;
 }
 }
 
 
+bool randr_is_active(xcb_connection_t *xcb)
+{
+	if (!xcb || !xcb_get_extension_data(xcb, &xcb_randr_id)->present)
+		return false;
+
+	return true;
+}
+
+int randr_screen_count(xcb_connection_t *xcb)
+{
+	if (!xcb)
+		return 0;
+
+	xcb_screen_t *screen;
+	screen = xcb_setup_roots_iterator(xcb_get_setup(xcb)).data;
+
+	xcb_randr_get_screen_resources_cookie_t res_c;
+	xcb_randr_get_screen_resources_reply_t* res_r;
+
+	res_c = xcb_randr_get_screen_resources(xcb, screen->root);
+	res_r = xcb_randr_get_screen_resources_reply(xcb, res_c, 0);
+	if (!res_r)
+		return 0;
+
+	return xcb_randr_get_screen_resources_crtcs_length(res_r);
+}
+
+int randr_screen_geo(xcb_connection_t *xcb, int_fast32_t screen,
+		int_fast32_t *x, int_fast32_t *y,
+		int_fast32_t *w, int_fast32_t *h,
+		xcb_screen_t **rscreen)
+{
+	xcb_screen_t *xscreen;
+	xscreen = xcb_setup_roots_iterator(xcb_get_setup(xcb)).data;
+
+	xcb_randr_get_screen_resources_cookie_t res_c;
+	xcb_randr_get_screen_resources_reply_t* res_r;
+
+	res_c = xcb_randr_get_screen_resources(xcb, xscreen->root);
+	res_r = xcb_randr_get_screen_resources_reply(xcb, res_c, 0);
+	if (!res_r)
+		goto fail;
+
+	int screens = xcb_randr_get_screen_resources_crtcs_length(res_r);
+	if (screen < 0 || screen >= screens)
+		goto fail;
+
+	xcb_randr_crtc_t *crtc = xcb_randr_get_screen_resources_crtcs(res_r);
+
+	xcb_randr_get_crtc_info_cookie_t crtc_c;
+	xcb_randr_get_crtc_info_reply_t *crtc_r;
+
+	crtc_c = xcb_randr_get_crtc_info(xcb, *(crtc + screen), 0);
+	crtc_r = xcb_randr_get_crtc_info_reply(xcb, crtc_c, 0);
+	if (!crtc_r)
+		goto fail;
+
+	*x = crtc_r->x;
+	*y = crtc_r->y;
+	*w = crtc_r->width;
+	*h = crtc_r->height;
+
+	if (rscreen)
+		*rscreen = xscreen;
+
+	return 0;
+
+fail:
+	*x = *y = *w = *h = 0;
+	return -1;
+}
+
 int x11_screen_geo(xcb_connection_t *xcb, int_fast32_t screen,
 int x11_screen_geo(xcb_connection_t *xcb, int_fast32_t screen,
 		int_fast32_t *w, int_fast32_t *h)
 		int_fast32_t *w, int_fast32_t *h)
 {
 {

+ 33 - 0
plugins/linux-capture/xhelpers.h

@@ -64,6 +64,39 @@ int xinerama_screen_geo(xcb_connection_t *xcb, int_fast32_t screen,
 		int_fast32_t *x, int_fast32_t *y,
 		int_fast32_t *x, int_fast32_t *y,
 		int_fast32_t *w, int_fast32_t *h);
 		int_fast32_t *w, int_fast32_t *h);
 
 
+/**
+ * Check for Randr extension
+ *
+ * @return true if randr is available which means it's active.
+ */
+bool randr_is_active(xcb_connection_t *xcb);
+
+/**
+ * Get the number of Randr screens
+ *
+ * @return number of screens
+ */
+int randr_screen_count(xcb_connection_t *xcb);
+
+/**
+ * Get screen geometry for a Rand crtc (screen)
+ *
+ * @note On error the passed coordinates/sizes will be set to 0.
+ *
+ * @param xcb xcb connection
+ * @param screen screen number to get geometry for
+ * @param x x-coordinate of the screen
+ * @param y y-coordinate of the screen
+ * @param w width of the screen
+ * @param h height of the screen
+ *
+ * @return < 0 on error
+ */
+int randr_screen_geo(xcb_connection_t *xcb, int_fast32_t screen,
+		int_fast32_t *x, int_fast32_t *y,
+		int_fast32_t *w, int_fast32_t *h,
+		xcb_screen_t **rscreen);
+
 /**
 /**
  * Get screen geometry for a X11 screen
  * Get screen geometry for a X11 screen
  *
  *

+ 24 - 5
plugins/linux-capture/xshm-input.c

@@ -18,6 +18,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include <stdio.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdlib.h>
 #include <inttypes.h>
 #include <inttypes.h>
+#include <xcb/randr.h>
 #include <xcb/shm.h>
 #include <xcb/shm.h>
 #include <xcb/xfixes.h>
 #include <xcb/xfixes.h>
 #include <xcb/xinerama.h>
 #include <xcb/xinerama.h>
@@ -50,6 +51,7 @@ struct xshm_data {
 
 
 	bool             show_cursor;
 	bool             show_cursor;
 	bool             use_xinerama;
 	bool             use_xinerama;
+	bool             use_randr;
 	bool             advanced;
 	bool             advanced;
 };
 };
 
 
@@ -83,6 +85,9 @@ static bool xshm_check_extensions(xcb_connection_t *xcb)
 	if (!xcb_get_extension_data(xcb, &xcb_xinerama_id)->present)
 	if (!xcb_get_extension_data(xcb, &xcb_xinerama_id)->present)
 		blog(LOG_INFO, "Missing Xinerama extension !");
 		blog(LOG_INFO, "Missing Xinerama extension !");
 
 
+	if (!xcb_get_extension_data(xcb, &xcb_randr_id)->present)
+		blog(LOG_INFO, "Missing Randr extension !");
+
 	return ok;
 	return ok;
 }
 }
 
 
@@ -96,7 +101,15 @@ static int_fast32_t xshm_update_geometry(struct xshm_data *data)
 	int_fast32_t old_width = data->width;
 	int_fast32_t old_width = data->width;
 	int_fast32_t old_height = data->height;
 	int_fast32_t old_height = data->height;
 
 
-	if (data->use_xinerama) {
+	if (data->use_randr) {
+		if (randr_screen_geo(data->xcb, data->screen_id,
+			&data->x_org, &data->y_org,
+			&data->width, &data->height,
+			&data->xcb_screen) < 0) {
+			return -1;
+		}
+	}
+	else if (data->use_xinerama) {
 		if (xinerama_screen_geo(data->xcb, data->screen_id,
 		if (xinerama_screen_geo(data->xcb, data->screen_id,
 			&data->x_org, &data->y_org,
 			&data->x_org, &data->y_org,
 			&data->width, &data->height) < 0) {
 			&data->width, &data->height) < 0) {
@@ -189,6 +202,7 @@ static void xshm_capture_start(struct xshm_data *data)
 	if (!xshm_check_extensions(data->xcb))
 	if (!xshm_check_extensions(data->xcb))
 		goto fail;
 		goto fail;
 
 
+	data->use_randr = randr_is_active(data->xcb) ? true : false;
 	data->use_xinerama = xinerama_is_active(data->xcb) ? true : false;
 	data->use_xinerama = xinerama_is_active(data->xcb) ? true : false;
 
 
 	if (xshm_update_geometry(data) < 0) {
 	if (xshm_update_geometry(data) < 0) {
@@ -287,16 +301,21 @@ static bool xshm_server_changed(obs_properties_t *props,
 
 
 	struct dstr screen_info;
 	struct dstr screen_info;
 	dstr_init(&screen_info);
 	dstr_init(&screen_info);
+	bool randr = randr_is_active(xcb);
 	bool xinerama = xinerama_is_active(xcb);
 	bool xinerama = xinerama_is_active(xcb);
-	int_fast32_t count = (xinerama) ?
-			xinerama_screen_count(xcb) :
-			xcb_setup_roots_length(xcb_get_setup(xcb));
+	int_fast32_t count = (randr) ?
+			randr_screen_count(xcb) :
+			(xinerama) ?
+				xinerama_screen_count(xcb) :
+				xcb_setup_roots_length(xcb_get_setup(xcb));
 
 
 	for (int_fast32_t i = 0; i < count; ++i) {
 	for (int_fast32_t i = 0; i < count; ++i) {
 		int_fast32_t x, y, w, h;
 		int_fast32_t x, y, w, h;
 		x = y = w = h = 0;
 		x = y = w = h = 0;
 
 
-		if (xinerama)
+		if (randr)
+			randr_screen_geo(xcb, i, &x, &y, &w, &h, NULL);
+		else if (xinerama)
 			xinerama_screen_geo(xcb, i, &x, &y, &w, &h);
 			xinerama_screen_geo(xcb, i, &x, &y, &w, &h);
 		else
 		else
 			x11_screen_geo(xcb, i, &w, &h);
 			x11_screen_geo(xcb, i, &w, &h);