Преглед изворни кода

Merge pull request #1485 from SingularityAzure/linux-capture-xcompcap-singularity

linux-capture: Improve XComposite capture robustness
Jim пре 7 година
родитељ
комит
47285c2ba6
1 измењених фајлова са 66 додато и 9 уклоњено
  1. 66 9
      plugins/linux-capture/xcompcap-main.cpp

+ 66 - 9
plugins/linux-capture/xcompcap-main.cpp

@@ -148,6 +148,7 @@ struct XCompcapMain_private
 	bool lockX;
 	bool include_border;
 	bool exclude_alpha;
+	bool draw_opaque;
 
 	double window_check_time = 0.0;
 
@@ -301,6 +302,7 @@ void XCompcapMain::updateSettings(obs_data_t *settings)
 		p->show_cursor = obs_data_get_bool(settings, "show_cursor");
 		p->include_border = obs_data_get_bool(settings, "include_border");
 		p->exclude_alpha = obs_data_get_bool(settings, "exclude_alpha");
+		p->draw_opaque = false;
 	} else {
 		p->win = prevWin;
 	}
@@ -347,6 +349,18 @@ void XCompcapMain::updateSettings(obs_data_t *settings)
 		cf = GS_BGRX;
 	}
 
+	bool has_alpha = true;
+
+	if (attr.depth < 32) {
+		cf = GS_BGRX;
+		has_alpha = false;
+	}
+
+	if (cf == GS_BGRX) {
+		p->swapRedBlue = !p->swapRedBlue;
+		p->draw_opaque = true;
+	}
+
 	p->border = attr.border_width;
 
 	if (p->include_border) {
@@ -395,16 +409,25 @@ void XCompcapMain::updateSettings(obs_data_t *settings)
 		glBindTexture(GL_TEXTURE_2D, 0);
 	}
 
-	const int attrs[] =
+	const int attrs_alpha[] =
 	{
 		GLX_BIND_TO_TEXTURE_RGBA_EXT, GL_TRUE,
 		GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
 		GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT,
 		GLX_ALPHA_SIZE, 8,
-		GLX_DOUBLEBUFFER, GL_FALSE,
 		None
 	};
 
+	const int attrs_no_alpha[] =
+	{
+		GLX_BIND_TO_TEXTURE_RGB_EXT, GL_TRUE,
+		GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
+		GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT,
+		None
+	};
+
+	const int *attrs = has_alpha ? attrs_alpha : attrs_no_alpha;
+
 	int nelem = 0;
 	GLXFBConfig* configs = glXChooseFBConfig(xdisp,
 			XCompcap::getRootWindowScreen(attr.root),
@@ -418,8 +441,26 @@ void XCompcapMain::updateSettings(obs_data_t *settings)
 		return;
 	}
 
-	glXGetFBConfigAttrib(xdisp, configs[0], GLX_Y_INVERTED_EXT, &nelem);
-	p->inverted = nelem != 0;
+	GLXFBConfig config;
+	bool found = false;
+	for (int i = 0; i < nelem; i++) {
+		int visual;
+		config = configs[i];
+		glXGetFBConfigAttrib(xdisp, config, GLX_VISUAL_ID, &visual);
+		if ((int)attr.visual->visualid == visual) {
+			found = true;
+			break;
+		}
+	}
+
+	if (!found) {
+		config = configs[0];
+		p->draw_opaque = true;
+	}
+
+	int inverted;
+	glXGetFBConfigAttrib(xdisp, config, GLX_Y_INVERTED_EXT, &inverted);
+	p->inverted = inverted != 0;
 
 	xlock.resetError();
 
@@ -433,14 +474,23 @@ void XCompcapMain::updateSettings(obs_data_t *settings)
 		return;
 	}
 
-	const int attribs[] =
+	const int attribs_alpha[] =
 	{
 		GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
 		GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT,
 		None
 	};
 
-	p->glxpixmap = glXCreatePixmap(xdisp, configs[0], p->pixmap, attribs);
+	const int attribs_no_alpha[] =
+	{
+		GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
+		GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGB_EXT,
+		None
+	};
+
+	const int *attribs = has_alpha ? attribs_alpha : attribs_no_alpha;
+
+	p->glxpixmap = glXCreatePixmap(xdisp, config, p->pixmap, attribs);
 
 	if (xlock.gotError()) {
 		blog(LOG_ERROR, "glXCreatePixmap failed: %s",
@@ -466,10 +516,14 @@ void XCompcapMain::updateSettings(obs_data_t *settings)
 	if (!p->windowName.empty()) {
 		blog(LOG_INFO, "[window-capture: '%s'] update settings:\n"
 				"\ttitle: %s\n"
-				"\tclass: %s",
+				"\tclass: %s\n"
+				"\tHas alpha: %s\n"
+				"\tFound exact GLXFBConfig: %s",
 				obs_source_get_name(p->source),
 				XCompcap::getWindowName(p->win).c_str(),
-				XCompcap::getWindowClass(p->win).c_str());
+				XCompcap::getWindowClass(p->win).c_str(),
+				has_alpha ? "yes" : "no",
+				found ? "yes" : "no");
 		blog(LOG_DEBUG, "\n"
 				"\tid:    %s",
 				std::to_string((long long)p->win).c_str());
@@ -563,7 +617,10 @@ void XCompcapMain::render(gs_effect_t *effect)
 
 	PLock lock(&p->lock, true);
 
-	effect = obs_get_base_effect(OBS_EFFECT_OPAQUE);
+	if (p->draw_opaque)
+		effect = obs_get_base_effect(OBS_EFFECT_OPAQUE);
+	else
+		effect = obs_get_base_effect(OBS_EFFECT_DEFAULT);
 
 	if (!lock.isLocked() || !p->tex)
 		return;