obs-studio/libobs/graphics/effect-parser.h

284 lines
6.7 KiB
C

/******************************************************************************
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
#pragma once
#include "../util/darray.h"
#include "../util/cf-parser.h"
#include "graphics.h"
#ifdef __cplusplus
extern "C" {
#endif
struct dstr;
/*
* The effect parser takes an effect file and converts it into individual
* shaders for each technique's pass. It automatically writes all dependent
* structures/functions/parameters to the shader and builds shader text for
* each shader component of each pass.
*/
/* ------------------------------------------------------------------------- */
/* effect parser var data */
struct ep_var {
char *type, *name, *mapping;
bool uniform;
};
static inline void ep_var_init(struct ep_var *epv)
{
memset(epv, 0, sizeof(struct ep_var));
}
static inline void ep_var_free(struct ep_var *epv)
{
bfree(epv->type);
bfree(epv->name);
bfree(epv->mapping);
}
/* ------------------------------------------------------------------------- */
/* effect parser param data */
struct ep_param {
char *type, *name;
DARRAY(uint8_t) default_val;
DARRAY(char*) properties;
struct effect_param *param;
bool is_const, is_property, is_uniform, is_texture, written;
int writeorder, array_count;
};
extern void ep_param_writevar(struct dstr *dst, struct darray *use_params);
static inline void ep_param_init(struct ep_param *epp,
char *type, char *name,
bool is_property, bool is_const, bool is_uniform)
{
epp->type = type;
epp->name = name;
epp->is_property = is_property;
epp->is_const = is_const;
epp->is_uniform = is_uniform;
epp->is_texture = (astrcmp_n(epp->type, "texture", 7) == 0);
epp->written = false;
epp->writeorder = false;
epp->array_count = 0;
da_init(epp->default_val);
da_init(epp->properties);
}
static inline void ep_param_free(struct ep_param *epp)
{
bfree(epp->type);
bfree(epp->name);
da_free(epp->default_val);
da_free(epp->properties);
}
/* ------------------------------------------------------------------------- */
/* effect parser struct data */
struct ep_struct {
char *name;
DARRAY(struct ep_var) vars; /* struct ep_var */
bool written;
};
static inline bool ep_struct_mapped(struct ep_struct *eps)
{
if (eps->vars.num > 0)
return eps->vars.array[0].mapping != NULL;
return false;
}
static inline void ep_struct_init(struct ep_struct *eps)
{
memset(eps, 0, sizeof(struct ep_struct));
}
static inline void ep_struct_free(struct ep_struct *eps)
{
size_t i;
bfree(eps->name);
for (i = 0; i < eps->vars.num; i++)
ep_var_free(eps->vars.array+i);
da_free(eps->vars);
}
/* ------------------------------------------------------------------------- */
/* effect parser sampler data */
struct ep_sampler {
char *name;
DARRAY(char*) states;
DARRAY(char*) values;
bool written;
};
static inline void ep_sampler_init(struct ep_sampler *eps)
{
memset(eps, 0, sizeof(struct ep_sampler));
}
static inline void ep_sampler_free(struct ep_sampler *eps)
{
size_t i;
for (i = 0; i < eps->states.num; i++)
bfree(eps->states.array[i]);
for (i = 0; i < eps->values.num; i++)
bfree(eps->values.array[i]);
bfree(eps->name);
da_free(eps->states);
da_free(eps->values);
}
/* ------------------------------------------------------------------------- */
/* effect parser pass data */
struct ep_pass {
char *name;
DARRAY(struct cf_token) vertex_program;
DARRAY(struct cf_token) fragment_program;
struct effect_pass *pass;
};
static inline void ep_pass_init(struct ep_pass *epp)
{
memset(epp, 0, sizeof(struct ep_pass));
}
static inline void ep_pass_free(struct ep_pass *epp)
{
bfree(epp->name);
da_free(epp->vertex_program);
da_free(epp->fragment_program);
}
/* ------------------------------------------------------------------------- */
/* effect parser technique data */
struct ep_technique {
char *name;
DARRAY(struct ep_pass) passes; /* struct ep_pass */
};
static inline void ep_technique_init(struct ep_technique *ept)
{
memset(ept, 0, sizeof(struct ep_technique));
}
static inline void ep_technique_free(struct ep_technique *ept)
{
size_t i;
for (i = 0; i < ept->passes.num; i++)
ep_pass_free(ept->passes.array+i);
bfree(ept->name);
da_free(ept->passes);
}
/* ------------------------------------------------------------------------- */
/* effect parser function data */
struct ep_func {
char *name, *ret_type, *mapping;
struct dstr contents;
DARRAY(struct ep_var) param_vars;
DARRAY(const char*) func_deps;
DARRAY(const char*) struct_deps;
DARRAY(const char*) param_deps;
DARRAY(const char*) sampler_deps;
bool written;
};
static inline void ep_func_init(struct ep_func *epf, char *ret_type,
char *name)
{
memset(epf, 0, sizeof(struct ep_func));
epf->name = name;
epf->ret_type = ret_type;
}
static inline void ep_func_free(struct ep_func *epf)
{
size_t i;
for (i = 0; i < epf->param_vars.num; i++)
ep_var_free(epf->param_vars.array+i);
bfree(epf->name);
bfree(epf->ret_type);
bfree(epf->mapping);
dstr_free(&epf->contents);
da_free(epf->param_vars);
da_free(epf->func_deps);
da_free(epf->struct_deps);
da_free(epf->param_deps);
da_free(epf->sampler_deps);
}
/* ------------------------------------------------------------------------- */
struct effect_parser {
effect_t effect;
DARRAY(struct ep_param) params;
DARRAY(struct ep_struct) structs;
DARRAY(struct ep_func) funcs;
DARRAY(struct ep_sampler) samplers;
DARRAY(struct ep_technique) techniques;
/* internal vars */
DARRAY(struct cf_lexer) files;
DARRAY(struct cf_token) tokens;
struct effect_pass *cur_pass;
struct cf_parser cfp;
};
static inline void ep_init(struct effect_parser *ep)
{
da_init(ep->params);
da_init(ep->structs);
da_init(ep->funcs);
da_init(ep->samplers);
da_init(ep->techniques);
da_init(ep->files);
da_init(ep->tokens);
ep->cur_pass = NULL;
cf_parser_init(&ep->cfp);
}
extern void ep_free(struct effect_parser *ep);
extern bool ep_parse(struct effect_parser *ep, effect_t effect,
const char *effect_string, const char *file);
#ifdef __cplusplus
}
#endif