summaryrefslogtreecommitdiffstats
path: root/options
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2016-06-04 20:48:56 +0200
committerwm4 <wm4@nowhere>2016-06-04 20:48:56 +0200
commit65f5fbc5d4457b68a304a68a52a41fecc0b25f15 (patch)
treea6e6b54597889a989d3e92e59f45cc76a7c888d0 /options
parent352904fd036c5d9dbe53e3726a0c4fdcfe408c24 (diff)
downloadmpv-65f5fbc5d4457b68a304a68a52a41fecc0b25f15.tar.bz2
mpv-65f5fbc5d4457b68a304a68a52a41fecc0b25f15.tar.xz
vo_opengl: somewhat simplify suboption handling mess
Enable m_sub_options_copy() to copy nested sub-options, and also enable it to create an option struct from defaults. We can get rid of most of the crap in assign_options() now. Calling handle_scaler_opt() to get a static allocation for scaler name is still needed. It's moved to reinit_scaler(), which seems to be a better place for it. Without it, dangling pointers could be created when options are changed. (And in fact, this fixes possible dangling pointers for window.name.) In theory we could create a dynamic copy, but that seemed even more messy. Chance of regressions.
Diffstat (limited to 'options')
-rw-r--r--options/m_config.c51
1 files changed, 37 insertions, 14 deletions
diff --git a/options/m_config.c b/options/m_config.c
index d58c406ed8..a3dcb30067 100644
--- a/options/m_config.c
+++ b/options/m_config.c
@@ -358,6 +358,18 @@ static void add_options(struct m_config *config,
m_config_add_option(config, parent_name, optstruct, optstruct_def, &defs[i]);
}
+// Initialize a field with a given value. In case this is dynamic data, it has
+// to be allocated and copied. src can alias dst, also can be NULL.
+static void init_opt_inplace(const struct m_option *opt, void *dst,
+ const void *src)
+{
+ union m_option_value temp = {0};
+ if (src)
+ memcpy(&temp, src, opt->type->size);
+ memset(dst, 0, opt->type->size);
+ m_option_copy(opt, dst, &temp);
+}
+
static void m_config_add_option(struct m_config *config,
const char *parent_name,
void *optstruct,
@@ -418,11 +430,7 @@ static void m_config_add_option(struct m_config *config,
assert(0);
}
}
- // In case this is dynamic data, it has to be allocated and copied.
- union m_option_value temp = {0};
- memcpy(&temp, co.default_data, arg->type->size);
- memset(co.data, 0, arg->type->size);
- m_option_copy(arg, co.data, &temp);
+ init_opt_inplace(arg, co.data, co.default_data);
}
}
@@ -942,24 +950,39 @@ static void free_substruct(void *ptr)
}
}
+// Passing ptr==NULL initializes it from proper defaults.
void *m_sub_options_copy(void *talloc_ctx, const struct m_sub_options *opts,
const void *ptr)
{
- void *new = talloc_zero_size(talloc_ctx, opts->size);
+ void *new = m_config_alloc_struct(talloc_ctx, opts);
struct dtor_info *dtor = talloc_ptrtype(new, dtor);
*dtor = (struct dtor_info){opts, new};
talloc_set_destructor(dtor, free_substruct);
- // also fill/initialize members not described by opts
- if (opts->defaults)
- memcpy(new, opts->defaults, opts->size);
for (int n = 0; opts->opts && opts->opts[n].type; n++) {
const struct m_option *opt = &opts->opts[n];
- // not implemented, because it adds lots of complexity
- assert(!(opt->type->flags & M_OPT_TYPE_HAS_CHILD));
- void *src = (char *)ptr + opt->offset;
+ if (opt->offset < 0)
+ continue;
+ void *src = ptr ? (char *)ptr + opt->offset : NULL;
void *dst = (char *)new + opt->offset;
- memset(dst, 0, opt->type->size);
- m_option_copy(opt, dst, src);
+ if (opt->type->flags & M_OPT_TYPE_HAS_CHILD) {
+ // Specifying a default struct for a sub-option field in the
+ // containing struct's default struct is not supported here.
+ // (Out of laziness. Could possibly be supported.)
+ assert(!substruct_read_ptr(dst));
+
+ const struct m_sub_options *subopts = opt->priv;
+
+ const void *sub_src = NULL;
+ if (src)
+ sub_src = substruct_read_ptr(src);
+ if (!sub_src)
+ sub_src = subopts->defaults;
+
+ void *sub_dst = m_sub_options_copy(new, subopts, sub_src);
+ substruct_write_ptr(dst, sub_dst);
+ } else {
+ init_opt_inplace(opt, dst, src);
+ }
}
return new;
}