diff --git a/docs/sphinx/reference-libobs-graphics-effects.rst b/docs/sphinx/reference-libobs-graphics-effects.rst index 1392b418a..e7c0ec389 100644 --- a/docs/sphinx/reference-libobs-graphics-effects.rst +++ b/docs/sphinx/reference-libobs-graphics-effects.rst @@ -154,6 +154,36 @@ HLSL format. --------------------- +.. function:: size_t gs_param_get_num_annotations(const gs_eparam_t *param) + + Gets the number of annotations associated with the parameter. + + :param param: Param object + :return: Number of annotations the param has + +--------------------- + +.. function:: gs_eparam_t *gs_param_get_annotation_by_idx(const gs_eparam_t *param, size_t annotation) + + Gets an annotation of a param by its index. + + :param param: Param object + :param param: Annotation index + :return: The effect parameter object (annotation), or *NULL* if index + invalid + +--------------------- + +.. function:: gs_eparam_t *gs_param_get_annotation_by_name(const gs_eparam_t *pardam, const char *annotation) + + Gets parameter of an effect by its name. + + :param param: Param object + :param name: Name of the annotation + :return: The effect parameter object (annotation), or *NULL* if not found + +--------------------- + .. function:: bool gs_effect_loop(gs_effect_t *effect, const char *name) Helper function that automatically begins techniques/passes. @@ -332,3 +362,39 @@ HLSL format. :param param: Effect parameter :param sampler: Sampler state object + +--------------------- + +.. function:: void *gs_effect_get_val(gs_eparam_t *param) + + Returns a copy of the param's current value. + + :param param: Effect parameter + :return: A pointer to the copied byte value of the param's current value. Freed with :c:func:`bfree()`. + +--------------------- + +.. function:: void gs_effect_get_default_val(gs_eparam_t *param) + + Returns a copy of the param's default value. + + :param param: Effect parameter + :return: A pointer to the copied byte value of the param's default value. Freed with :c:func:`bfree()`. + +--------------------- + +.. function:: size_t gs_effect_get_val_size(gs_eparam_t *param) + + Returns the size in bytes of the param's current value. + + :param param: Effect parameter + :return: The size in bytes of the param's current value. + +--------------------- + +.. function:: size_t gs_effect_get_default_val_size(gs_eparam_t *param) + + Returns the size in bytes of the param's default value. + + :param param: Effect parameter + :return: The size in bytes of the param's default value. diff --git a/libobs-d3d11/d3d11-shader.cpp b/libobs-d3d11/d3d11-shader.cpp index 453ff24ea..1a710486b 100644 --- a/libobs-d3d11/d3d11-shader.cpp +++ b/libobs-d3d11/d3d11-shader.cpp @@ -137,8 +137,11 @@ void gs_shader::BuildConstantBuffer() case GS_SHADER_PARAM_BOOL: case GS_SHADER_PARAM_INT: case GS_SHADER_PARAM_FLOAT: size = sizeof(float); break; + case GS_SHADER_PARAM_INT2: case GS_SHADER_PARAM_VEC2: size = sizeof(vec2); break; + case GS_SHADER_PARAM_INT3: case GS_SHADER_PARAM_VEC3: size = sizeof(float)*3; break; + case GS_SHADER_PARAM_INT4: case GS_SHADER_PARAM_VEC4: size = sizeof(vec4); break; case GS_SHADER_PARAM_MATRIX4X4: size = sizeof(float)*4*4; diff --git a/libobs/graphics/effect-parser.c b/libobs/graphics/effect-parser.c index d721b41f3..84b46a564 100644 --- a/libobs/graphics/effect-parser.c +++ b/libobs/graphics/effect-parser.c @@ -21,6 +21,39 @@ #include "effect-parser.h" #include "effect.h" +static inline bool ep_parse_param_assign(struct effect_parser *ep, + struct ep_param *param); + +static enum gs_shader_param_type get_effect_param_type(const char *type) +{ + if (strcmp(type, "float") == 0) + return GS_SHADER_PARAM_FLOAT; + else if (strcmp(type, "float2") == 0) + return GS_SHADER_PARAM_VEC2; + else if (strcmp(type, "float3") == 0) + return GS_SHADER_PARAM_VEC3; + else if (strcmp(type, "float4") == 0) + return GS_SHADER_PARAM_VEC4; + else if (strcmp(type, "int2") == 0) + return GS_SHADER_PARAM_INT2; + else if (strcmp(type, "int3") == 0) + return GS_SHADER_PARAM_INT3; + else if (strcmp(type, "int4") == 0) + return GS_SHADER_PARAM_INT4; + else if (astrcmp_n(type, "texture", 7) == 0) + return GS_SHADER_PARAM_TEXTURE; + else if (strcmp(type, "float4x4") == 0) + return GS_SHADER_PARAM_MATRIX4X4; + else if (strcmp(type, "bool") == 0) + return GS_SHADER_PARAM_BOOL; + else if (strcmp(type, "int") == 0) + return GS_SHADER_PARAM_INT; + else if (strcmp(type, "string") == 0) + return GS_SHADER_PARAM_STRING; + + return GS_SHADER_PARAM_UNKNOWN; +} + void ep_free(struct effect_parser *ep) { size_t i; @@ -92,6 +125,18 @@ static inline struct ep_param *ep_getparam(struct effect_parser *ep, return NULL; } +static inline struct ep_param *ep_getannotation(struct ep_param *param, + const char *name) +{ + size_t i; + for (i = 0; i < param->annotations.num; i++) { + if (strcmp(name, param->annotations.array[i].name) == 0) + return param->annotations.array+i; + } + + return NULL; +} + static inline struct ep_func *ep_getfunc_strref(struct effect_parser *ep, const struct strref *ref) { @@ -262,6 +307,145 @@ error: ep_struct_free(&eps); } +static inline int ep_parse_param_annotation_var(struct effect_parser *ep, + struct ep_param *var) +{ + int code; + + /* -------------------------------------- */ + /* variable type */ + + if (!cf_next_valid_token(&ep->cfp)) + return PARSE_EOF; + + if (cf_token_is(&ep->cfp, ";")) + return PARSE_CONTINUE; + if (cf_token_is(&ep->cfp, ">")) + return PARSE_BREAK; + + code = cf_token_is_type(&ep->cfp, CFTOKEN_NAME, "type name", ";"); + if (code != PARSE_SUCCESS) + return code; + + bfree(var->type); + cf_copy_token(&ep->cfp, &var->type); + + /* -------------------------------------- */ + /* variable name */ + + if (!cf_next_valid_token(&ep->cfp)) + return PARSE_EOF; + + if (cf_token_is(&ep->cfp, ";")) { + cf_adderror_expecting(&ep->cfp, "variable name"); + return PARSE_UNEXPECTED_CONTINUE; + } + if (cf_token_is(&ep->cfp, ">")) { + cf_adderror_expecting(&ep->cfp, "variable name"); + return PARSE_UNEXPECTED_BREAK; + } + + code = cf_token_is_type(&ep->cfp, CFTOKEN_NAME, "variable name", ";"); + if (code != PARSE_SUCCESS) + return code; + + bfree(var->name); + cf_copy_token(&ep->cfp, &var->name); + + /* -------------------------------------- */ + /* variable mapping if any (POSITION, TEXCOORD, etc) */ + + if (!cf_next_valid_token(&ep->cfp)) + return PARSE_EOF; + + if (cf_token_is(&ep->cfp, ":")) { + cf_adderror_expecting(&ep->cfp, "= or ;"); + return PARSE_UNEXPECTED_BREAK; + } else if (cf_token_is(&ep->cfp, ">")) { + cf_adderror_expecting(&ep->cfp, "= or ;"); + return PARSE_UNEXPECTED_BREAK; + } else if (cf_token_is(&ep->cfp, "=")) { + if (!ep_parse_param_assign(ep, var)) { + cf_adderror_expecting(&ep->cfp, "assignment value"); + return PARSE_UNEXPECTED_BREAK; + } + } + + /* -------------------------------------- */ + + if (!cf_token_is(&ep->cfp, ";")) { + if (!cf_go_to_valid_token(&ep->cfp, ";", ">")) { + cf_adderror_expecting(&ep->cfp, "; or >"); + return PARSE_EOF; + } + return PARSE_CONTINUE; + } + + return PARSE_SUCCESS; +} + +static int ep_parse_annotations(struct effect_parser *ep, + struct darray *annotations) +{ + if (!cf_token_is(&ep->cfp, "<")) { + cf_adderror_expecting(&ep->cfp, "<"); + goto error; + } + + /* get annotation variables */ + while (true) { + bool do_break = false; + struct ep_param var; + + ep_param_init(&var, bstrdup(""), bstrdup(""), false, false, + false); + + switch (ep_parse_param_annotation_var(ep, &var)) { + case PARSE_UNEXPECTED_CONTINUE: + cf_adderror_syntax_error(&ep->cfp); + /* Falls through. */ + case PARSE_CONTINUE: + ep_param_free(&var); + continue; + + case PARSE_UNEXPECTED_BREAK: + cf_adderror_syntax_error(&ep->cfp); + /* Falls through. */ + case PARSE_BREAK: + ep_param_free(&var); + do_break = true; + break; + + case PARSE_EOF: + ep_param_free(&var); + goto error; + } + + if (do_break) + break; + + darray_push_back(sizeof(struct ep_param), annotations, &var); + } + + if (!cf_token_is(&ep->cfp, ">")) { + cf_adderror_expecting(&ep->cfp, ">"); + goto error; + } + if (!cf_next_valid_token(&ep->cfp)) + goto error; + + return true; + +error: + return false; +} + +static int ep_parse_param_annotations(struct effect_parser *ep, + struct ep_param *param) +{ + return ep_parse_annotations(ep, ¶m->annotations.da); +} + static inline int ep_parse_pass_command_call(struct effect_parser *ep, struct darray *call) { @@ -328,7 +512,7 @@ static int ep_parse_pass(struct effect_parser *ep, struct ep_pass *pass) if (!cf_token_is(&ep->cfp, "{")) { pass->name = bstrdup_n(ep->cfp.cur_token->str.array, - ep->cfp.cur_token->str.len); + ep->cfp.cur_token->str.len); if (!cf_next_valid_token(&ep->cfp)) return PARSE_EOF; } @@ -356,9 +540,19 @@ static void ep_parse_technique(struct effect_parser *ep) if (cf_next_name(&ep->cfp, &ept.name, "name", ";") != PARSE_SUCCESS) goto error; - if (cf_next_token_should_be(&ep->cfp, "{", ";", NULL) != PARSE_SUCCESS) - goto error; + if (!cf_next_valid_token(&ep->cfp)) + return; + + if (!cf_token_is(&ep->cfp, "{")) { + if (!cf_go_to_token(&ep->cfp, ";", NULL)) { + cf_adderror_expecting(&ep->cfp, ";"); + return; + } + + cf_adderror_expecting(&ep->cfp, "{"); + goto error; + } if (!cf_next_valid_token(&ep->cfp)) goto error; @@ -756,6 +950,30 @@ static inline int ep_parse_param_assign_texture(struct effect_parser *ep, return PARSE_SUCCESS; } +static inline int ep_parse_param_assign_string(struct effect_parser *ep, + struct ep_param *param) +{ + int code; + char *str = NULL; + + if (!cf_next_valid_token(&ep->cfp)) + return PARSE_EOF; + + code = cf_token_is_type(&ep->cfp, CFTOKEN_STRING, "string", ";"); + if (code != PARSE_SUCCESS) + return code; + + str = cf_literal_to_str(ep->cfp.cur_token->str.array, + ep->cfp.cur_token->str.len); + + if (str) { + da_copy_array(param->default_val, str, strlen(str) + 1); + bfree(str); + } + + return PARSE_SUCCESS; +} + static inline int ep_parse_param_assign_intfloat(struct effect_parser *ep, struct ep_param *param, bool is_float) { @@ -789,30 +1007,51 @@ static inline int ep_parse_param_assign_intfloat(struct effect_parser *ep, return PARSE_SUCCESS; } -/* - * parses assignment for float1, float2, float3, float4, and any combination - * for float3x3, float4x4, etc - */ -static inline int ep_parse_param_assign_float_array(struct effect_parser *ep, +static inline int ep_parse_param_assign_bool(struct effect_parser *ep, struct ep_param *param) { - const char *float_type = param->type+5; - int float_count = 0, code, i; + if (!cf_next_valid_token(&ep->cfp)) + return PARSE_EOF; + + if (cf_token_is(&ep->cfp, "true")) { + long l = 1; + da_push_back_array(param->default_val, &l, sizeof(long)); + return PARSE_SUCCESS; + } else if (cf_token_is(&ep->cfp, "false")) { + long l = 0; + da_push_back_array(param->default_val, &l, sizeof(long)); + return PARSE_SUCCESS; + } + + cf_adderror_expecting(&ep->cfp, "true or false"); + + return PARSE_EOF; +} + +/* + * parses assignment for float1, float2, float3, float4, int1, int2, int3, int4, + * and any combination for float3x3, float4x4, int3x3, int4x4, etc +*/ +static inline int ep_parse_param_assign_intfloat_array(struct effect_parser *ep, + struct ep_param *param, bool is_float) +{ + const char *intfloat_type = param->type + (is_float ? 5 : 3); + int intfloat_count = 0, code, i; /* -------------------------------------------- */ - if (float_type[0] < '1' || float_type[0] > '4') + if (intfloat_type[0] < '1' || intfloat_type[0] > '4') cf_adderror(&ep->cfp, "Invalid row count", LEX_ERROR, NULL, NULL, NULL); - float_count = float_type[0]-'0'; + intfloat_count = intfloat_type[0]-'0'; - if (float_type[1] == 'x') { - if (float_type[2] < '1' || float_type[2] > '4') + if (intfloat_type[1] == 'x') { + if (intfloat_type[2] < '1' || intfloat_type[2] > '4') cf_adderror(&ep->cfp, "Invalid column count", LEX_ERROR, NULL, NULL, NULL); - float_count *= float_type[2]-'0'; + intfloat_count *= intfloat_type[2]-'0'; } /* -------------------------------------------- */ @@ -820,10 +1059,10 @@ static inline int ep_parse_param_assign_float_array(struct effect_parser *ep, code = cf_next_token_should_be(&ep->cfp, "{", ";", NULL); if (code != PARSE_SUCCESS) return code; - for (i = 0; i < float_count; i++) { - char *next = ((i+1) < float_count) ? "," : "}"; + for (i = 0; i < intfloat_count; i++) { + char *next = ((i+1) < intfloat_count) ? "," : "}"; - code = ep_parse_param_assign_intfloat(ep, param, true); + code = ep_parse_param_assign_intfloat(ep, param, is_float); if (code != PARSE_SUCCESS) return code; code = cf_next_token_should_be(&ep->cfp, next, ";", NULL); @@ -842,8 +1081,14 @@ static int ep_parse_param_assignment_val(struct effect_parser *ep, return ep_parse_param_assign_intfloat(ep, param, false); else if (strcmp(param->type, "float") == 0) return ep_parse_param_assign_intfloat(ep, param, true); + else if (astrcmp_n(param->type, "int", 3) == 0) + return ep_parse_param_assign_intfloat_array(ep, param, false); else if (astrcmp_n(param->type, "float", 5) == 0) - return ep_parse_param_assign_float_array(ep, param); + return ep_parse_param_assign_intfloat_array(ep, param, true); + else if (astrcmp_n(param->type, "string", 6) == 0) + return ep_parse_param_assign_string(ep, param); + else if (strcmp(param->type, "bool") == 0) + return ep_parse_param_assign_bool(ep, param); cf_adderror(&ep->cfp, "Invalid type '$1' used for assignment", LEX_ERROR, param->type, NULL, NULL); @@ -879,6 +1124,9 @@ static void ep_parse_param(struct effect_parser *ep, goto complete; if (cf_token_is(&ep->cfp, "[") && !ep_parse_param_array(ep, ¶m)) goto error; + if (cf_token_is(&ep->cfp, "<") && !ep_parse_param_annotations(ep, + ¶m)) + goto error; if (cf_token_is(&ep->cfp, "=") && !ep_parse_param_assign(ep, ¶m)) goto error; /* @@ -945,7 +1193,6 @@ static void ep_parse_other(struct effect_parser *ep) goto error; if (cf_next_name(&ep->cfp, &name, "name", ";") != PARSE_SUCCESS) goto error; - if (!cf_next_valid_token(&ep->cfp)) goto error; @@ -1339,6 +1586,35 @@ static void ep_makeshaderstring(struct effect_parser *ep, ep_reset_written(ep); } +static void ep_compile_annotations(struct darray *ep_annotations, + struct darray *gsp_annotations, struct effect_parser *ep) +{ + darray_resize(sizeof(struct gs_effect_param), + gsp_annotations, ep_annotations->num); + + size_t i; + for (i = 0; i < ep_annotations->num; i++) { + struct gs_effect_param *param = ((struct gs_effect_param *) + gsp_annotations->array)+i; + struct ep_param *param_in = ((struct ep_param *) + ep_annotations->array)+i; + + param->name = bstrdup(param_in->name); + param->section = EFFECT_ANNOTATION; + param->effect = ep->effect; + da_move(param->default_val, param_in->default_val); + + param->type = get_effect_param_type(param_in->type); + } +} + +static void ep_compile_param_annotations(struct ep_param *ep_param_input, + struct gs_effect_param *gs_effect_input, struct effect_parser *ep) +{ + ep_compile_annotations(&(ep_param_input->annotations.da), + &(gs_effect_input->annotations.da), ep); +} + static void ep_compile_param(struct effect_parser *ep, size_t idx) { struct gs_effect_param *param; @@ -1353,27 +1629,14 @@ static void ep_compile_param(struct effect_parser *ep, size_t idx) param->effect = ep->effect; da_move(param->default_val, param_in->default_val); - if (strcmp(param_in->type, "bool") == 0) - param->type = GS_SHADER_PARAM_BOOL; - else if (strcmp(param_in->type, "float") == 0) - param->type = GS_SHADER_PARAM_FLOAT; - else if (strcmp(param_in->type, "int") == 0) - param->type = GS_SHADER_PARAM_INT; - else if (strcmp(param_in->type, "float2") == 0) - param->type = GS_SHADER_PARAM_VEC2; - else if (strcmp(param_in->type, "float3") == 0) - param->type = GS_SHADER_PARAM_VEC3; - else if (strcmp(param_in->type, "float4") == 0) - param->type = GS_SHADER_PARAM_VEC4; - else if (strcmp(param_in->type, "float4x4") == 0) - param->type = GS_SHADER_PARAM_MATRIX4X4; - else if (param_in->is_texture) - param->type = GS_SHADER_PARAM_TEXTURE; + param->type = get_effect_param_type(param_in->type); if (strcmp(param_in->name, "ViewProj") == 0) ep->effect->view_proj = param; else if (strcmp(param_in->name, "World") == 0) ep->effect->world = param; + + ep_compile_param_annotations(param_in, param, ep); } static bool ep_compile_pass_shaderparams(struct effect_parser *ep, diff --git a/libobs/graphics/effect-parser.h b/libobs/graphics/effect-parser.h index c0eb6f064..128139917 100644 --- a/libobs/graphics/effect-parser.h +++ b/libobs/graphics/effect-parser.h @@ -20,6 +20,7 @@ #include "../util/darray.h" #include "../util/cf-parser.h" #include "graphics.h" +#include "shader-parser.h" #ifdef __cplusplus extern "C" { @@ -72,6 +73,7 @@ struct ep_param { struct gs_effect_param *param; bool is_const, is_property, is_uniform, is_texture, written; int writeorder, array_count; + DARRAY(struct ep_param) annotations; }; extern void ep_param_writevar(struct dstr *dst, struct darray *use_params); @@ -91,6 +93,7 @@ static inline void ep_param_init(struct ep_param *epp, epp->array_count = 0; da_init(epp->default_val); da_init(epp->properties); + da_init(epp->annotations); } static inline void ep_param_free(struct ep_param *epp) @@ -99,6 +102,10 @@ static inline void ep_param_free(struct ep_param *epp) bfree(epp->name); da_free(epp->default_val); da_free(epp->properties); + + for (size_t i = 0; i < epp->annotations.num; i++) + ep_param_free(epp->annotations.array + i); + da_free(epp->annotations); } /* ------------------------------------------------------------------------- */ diff --git a/libobs/graphics/effect.c b/libobs/graphics/effect.c index 4b2a71660..ddd5d5a74 100644 --- a/libobs/graphics/effect.c +++ b/libobs/graphics/effect.c @@ -286,6 +286,63 @@ gs_eparam_t *gs_effect_get_param_by_name(const gs_effect_t *effect, return NULL; } +size_t gs_param_get_num_annotations(const gs_eparam_t *param) +{ + return param ? param->annotations.num : 0; +} + +gs_eparam_t *gs_param_get_annotation_by_idx(const gs_eparam_t *param, + size_t annotation) +{ + if (!param) return NULL; + + struct gs_effect_param *params = param->annotations.array; + if (annotation > param->annotations.num) + return NULL; + + return params + annotation; +} + +gs_eparam_t *gs_param_get_annotation_by_name(const gs_eparam_t *param, + const char *name) +{ + if (!param) return NULL; + struct gs_effect_param *params = param->annotations.array; + + for (size_t i = 0; i < param->annotations.num; i++) { + struct gs_effect_param *g_param = params + i; + if (strcmp(g_param->name, name) == 0) + return g_param; + } + return NULL; +} + +gs_epass_t *gs_technique_get_pass_by_idx(const gs_technique_t *technique, + size_t pass) +{ + if (!technique) return NULL; + struct gs_effect_pass *passes = technique->passes.array; + + if (pass > technique->passes.num) + return NULL; + + return passes + pass; +} + +gs_epass_t *gs_technique_get_pass_by_name(const gs_technique_t *technique, + const char *name) +{ + if (!technique) return NULL; + struct gs_effect_pass *passes = technique->passes.array; + + for (size_t i = 0; i < technique->passes.num; i++) { + struct gs_effect_pass *g_pass = passes + i; + if (strcmp(g_pass->name, name) == 0) + return g_pass; + } + return NULL; +} + gs_eparam_t *gs_effect_get_viewproj_matrix(const gs_effect_t *effect) { return effect ? effect->view_proj : NULL; @@ -332,6 +389,45 @@ static inline void effect_setval_inline(gs_eparam_t *param, } } +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif +static inline void effect_getval_inline(gs_eparam_t *param, void *data, + size_t size) +{ + if (!param) { + blog(LOG_ERROR, "effect_getval_inline: invalid param"); + return; + } + + if (!data) { + blog(LOG_ERROR, "effect_getval_inline: invalid data"); + return; + } + + size_t bytes = min(size, param->cur_val.num); + + memcpy(data, param->cur_val.array, bytes); +} + +static inline void effect_getdefaultval_inline(gs_eparam_t *param, void *data, + size_t size) +{ + if (!param) { + blog(LOG_ERROR, "effect_getdefaultval_inline: invalid param"); + return; + } + + if (!data) { + blog(LOG_ERROR, "effect_getdefaultval_inline: invalid data"); + return; + } + + size_t bytes = min(size, param->default_val.num); + + memcpy(data, param->default_val.array, bytes); +} + void gs_effect_set_bool(gs_eparam_t *param, bool val) { int b_val = (int)val; @@ -385,6 +481,54 @@ void gs_effect_set_val(gs_eparam_t *param, const void *val, size_t size) effect_setval_inline(param, val, size); } +void *gs_effect_get_val(gs_eparam_t *param) +{ + if (!param) { + blog(LOG_ERROR, "gs_effect_get_val: invalid param"); + return NULL; + } + size_t size = param->cur_val.num; + void *data; + + if (size) + data = (void*)bzalloc(size); + else + return NULL; + + effect_getval_inline(param, data, size); + + return data; +} + +size_t gs_effect_get_val_size(gs_eparam_t *param) +{ + return param ? param->cur_val.num : 0; +} + +void *gs_effect_get_default_val(gs_eparam_t *param) +{ + if (!param) { + blog(LOG_ERROR, "gs_effect_get_default_val: invalid param"); + return NULL; + } + size_t size = param->default_val.num; + void *data; + + if (size) + data = (void*)bzalloc(size); + else + return NULL; + + effect_getdefaultval_inline(param, data, size); + + return data; +} + +size_t gs_effect_get_default_val_size(gs_eparam_t *param) +{ + return param ? param->default_val.num : 0; +} + void gs_effect_set_default(gs_eparam_t *param) { effect_setval_inline(param, param->default_val.array, diff --git a/libobs/graphics/effect.h b/libobs/graphics/effect.h index d76fb85e7..9a868689e 100644 --- a/libobs/graphics/effect.h +++ b/libobs/graphics/effect.h @@ -41,7 +41,8 @@ enum effect_section { EFFECT_PARAM, EFFECT_TECHNIQUE, EFFECT_SAMPLER, - EFFECT_PASS + EFFECT_PASS, + EFFECT_ANNOTATION }; /* ------------------------------------------------------------------------- */ @@ -61,11 +62,13 @@ struct gs_effect_param { /*char *full_name; float scroller_min, scroller_max, scroller_inc, scroller_mul;*/ + DARRAY(struct gs_effect_param) annotations; }; static inline void effect_param_init(struct gs_effect_param *param) { memset(param, 0, sizeof(struct gs_effect_param)); + da_init(param->annotations); } static inline void effect_param_free(struct gs_effect_param *param) @@ -74,6 +77,12 @@ static inline void effect_param_free(struct gs_effect_param *param) //bfree(param->full_name); da_free(param->cur_val); da_free(param->default_val); + + size_t i; + for (i = 0; i < param->annotations.num; i++) + effect_param_free(param->annotations.array + i); + + da_free(param->annotations); } EXPORT void effect_param_parse_property(gs_eparam_t *param, @@ -106,6 +115,7 @@ static inline void effect_pass_free(struct gs_effect_pass *pass) bfree(pass->name); da_free(pass->vertshader_params); da_free(pass->pixelshader_params); + gs_shader_destroy(pass->vertshader); gs_shader_destroy(pass->pixelshader); } @@ -130,6 +140,7 @@ static inline void effect_technique_free(struct gs_effect_technique *t) size_t i; for (i = 0; i < t->passes.num; i++) effect_pass_free(t->passes.array+i); + da_free(t->passes); bfree(t->name); } diff --git a/libobs/graphics/graphics.h b/libobs/graphics/graphics.h index df9583f0b..33c254af6 100644 --- a/libobs/graphics/graphics.h +++ b/libobs/graphics/graphics.h @@ -267,6 +267,7 @@ typedef struct gs_shader gs_shader_t; typedef struct gs_shader_param gs_sparam_t; typedef struct gs_effect gs_effect_t; typedef struct gs_effect_technique gs_technique_t; +typedef struct gs_effect_pass gs_epass_t; typedef struct gs_effect_param gs_eparam_t; typedef struct gs_device gs_device_t; typedef struct graphics_subsystem graphics_t; @@ -368,12 +369,21 @@ EXPORT bool gs_technique_begin_pass(gs_technique_t *technique, size_t pass); EXPORT bool gs_technique_begin_pass_by_name(gs_technique_t *technique, const char *name); EXPORT void gs_technique_end_pass(gs_technique_t *technique); +EXPORT gs_epass_t *gs_technique_get_pass_by_idx(const gs_technique_t *technique, + size_t pass); +EXPORT gs_epass_t *gs_technique_get_pass_by_name( + const gs_technique_t *technique, const char *name); EXPORT size_t gs_effect_get_num_params(const gs_effect_t *effect); EXPORT gs_eparam_t *gs_effect_get_param_by_idx(const gs_effect_t *effect, size_t param); EXPORT gs_eparam_t *gs_effect_get_param_by_name(const gs_effect_t *effect, const char *name); +EXPORT size_t gs_param_get_num_annotations(const gs_eparam_t *param); +EXPORT gs_eparam_t *gs_param_get_annotation_by_idx(const gs_eparam_t *param, + size_t annotation); +EXPORT gs_eparam_t *gs_param_get_annotation_by_name(const gs_eparam_t *param, + const char *name); /** Helper function to simplify effect usage. Use with a while loop that * contains drawing functions. Automatically handles techniques, passes, and @@ -402,6 +412,10 @@ EXPORT void gs_effect_set_vec4(gs_eparam_t *param, const struct vec4 *val); EXPORT void gs_effect_set_texture(gs_eparam_t *param, gs_texture_t *val); EXPORT void gs_effect_set_val(gs_eparam_t *param, const void *val, size_t size); EXPORT void gs_effect_set_default(gs_eparam_t *param); +EXPORT size_t gs_effect_get_val_size(gs_eparam_t *param); +EXPORT void *gs_effect_get_val(gs_eparam_t *param); +EXPORT size_t gs_effect_get_default_val_size(gs_eparam_t *param); +EXPORT void *gs_effect_get_default_val(gs_eparam_t *param); EXPORT void gs_effect_set_next_sampler(gs_eparam_t *param, gs_samplerstate_t *sampler);