Przeglądaj źródła

image-source: Add option (unload when not showing)

If this option is on, the image will unload when the image isn't
displayed anywhere, and then reload it when it's displayed again to
reduce the amount of memory images take up on VRAM at any given time.
If this option is off, then it's always loaded in VRAM regardless of
whether it's displayed or not.

Closes Pull Request #380

(edited by Jim)
Christoph Hohmann 11 lat temu
rodzic
commit
c6008316e2

+ 1 - 0
plugins/image-source/data/locale/en-US.ini

@@ -1,2 +1,3 @@
 ImageInput="Image"
 ImageInput="Image"
 File="Image File"
 File="Image File"
+UnloadWhenNotShowing="Unload image when not showing"

+ 68 - 9
plugins/image-source/image-source.c

@@ -14,6 +14,9 @@
 struct image_source {
 struct image_source {
 	obs_source_t *source;
 	obs_source_t *source;
 
 
+	char         *file;
+	bool         persistent;
+
 	gs_texture_t *tex;
 	gs_texture_t *tex;
 	uint32_t     cx;
 	uint32_t     cx;
 	uint32_t     cy;
 	uint32_t     cy;
@@ -24,19 +27,19 @@ static const char *image_source_get_name(void)
 	return obs_module_text("ImageInput");
 	return obs_module_text("ImageInput");
 }
 }
 
 
-static void image_source_update(void *data, obs_data_t *settings)
+static void image_source_load(struct image_source *context)
 {
 {
-	struct image_source *context = data;
-	const char *file = obs_data_get_string(settings, "file");
+	char *file = context->file;
 
 
 	obs_enter_graphics();
 	obs_enter_graphics();
 
 
-	if (context->tex) {
+	if (context->tex)
 		gs_texture_destroy(context->tex);
 		gs_texture_destroy(context->tex);
-		context->tex = NULL;
-	}
+	context->tex = NULL;
 
 
 	if (file && *file) {
 	if (file && *file) {
+		debug("loading texture '%s'", file);
+
 		context->tex = gs_texture_create_from_file(file);
 		context->tex = gs_texture_create_from_file(file);
 		if (context->tex) {
 		if (context->tex) {
 			context->cx = gs_texture_get_width(context->tex);
 			context->cx = gs_texture_get_width(context->tex);
@@ -51,6 +54,56 @@ static void image_source_update(void *data, obs_data_t *settings)
 	obs_leave_graphics();
 	obs_leave_graphics();
 }
 }
 
 
+static void image_source_unload(struct image_source *context)
+{
+	obs_enter_graphics();
+
+	if (context->tex)
+		gs_texture_destroy(context->tex);
+	context->tex = NULL;
+
+	obs_leave_graphics();
+}
+
+static void image_source_update(void *data, obs_data_t *settings)
+{
+	struct image_source *context = data;
+	const char *file = obs_data_get_string(settings, "file");
+	const bool unload = obs_data_get_bool(settings, "unload");
+
+	if (context->file)
+		bfree(context->file);
+	context->file = bstrdup(file);
+	context->persistent = !unload;
+
+	/* Load the image if the source is persistent or showing */
+	if (context->persistent || obs_source_showing(context->source))
+		image_source_load(data);
+	else
+		image_source_unload(data);
+}
+
+static void image_source_defaults(obs_data_t *settings)
+{
+	obs_data_set_default_bool(settings, "unload", true);
+}
+
+static void image_source_show(void *data)
+{
+	struct image_source *context = data;
+
+	if (!context->persistent)
+		image_source_load(context);
+}
+
+static void image_source_hide(void *data)
+{
+	struct image_source *context = data;
+
+	if (!context->persistent)
+		image_source_unload(context);
+}
+
 static void *image_source_create(obs_data_t *settings, obs_source_t *source)
 static void *image_source_create(obs_data_t *settings, obs_source_t *source)
 {
 {
 	struct image_source *context = bzalloc(sizeof(struct image_source));
 	struct image_source *context = bzalloc(sizeof(struct image_source));
@@ -64,10 +117,10 @@ static void image_source_destroy(void *data)
 {
 {
 	struct image_source *context = data;
 	struct image_source *context = data;
 
 
-	obs_enter_graphics();
-	gs_texture_destroy(context->tex);
-	obs_leave_graphics();
+	image_source_unload(context);
 
 
+	if (context->file)
+		bfree(context->file);
 	bfree(context);
 	bfree(context);
 }
 }
 
 
@@ -86,6 +139,7 @@ static uint32_t image_source_getheight(void *data)
 static void image_source_render(void *data, gs_effect_t *effect)
 static void image_source_render(void *data, gs_effect_t *effect)
 {
 {
 	struct image_source *context = data;
 	struct image_source *context = data;
+
 	if (!context->tex)
 	if (!context->tex)
 		return;
 		return;
 
 
@@ -112,6 +166,8 @@ static obs_properties_t *image_source_properties(void *unused)
 	obs_properties_add_path(props,
 	obs_properties_add_path(props,
 			"file", obs_module_text("File"),
 			"file", obs_module_text("File"),
 			OBS_PATH_FILE, image_filter, NULL);
 			OBS_PATH_FILE, image_filter, NULL);
+	obs_properties_add_bool(props,
+			"unload", obs_module_text("UnloadWhenNotShowing"));
 
 
 	return props;
 	return props;
 }
 }
@@ -124,6 +180,9 @@ static struct obs_source_info image_source_info = {
 	.create         = image_source_create,
 	.create         = image_source_create,
 	.destroy        = image_source_destroy,
 	.destroy        = image_source_destroy,
 	.update         = image_source_update,
 	.update         = image_source_update,
+	.get_defaults   = image_source_defaults,
+	.show           = image_source_show,
+	.hide           = image_source_hide,
 	.get_width      = image_source_getwidth,
 	.get_width      = image_source_getwidth,
 	.get_height     = image_source_getheight,
 	.get_height     = image_source_getheight,
 	.video_render   = image_source_render,
 	.video_render   = image_source_render,