diff options
author | 2016-05-12 03:34:47 +0200 | |
---|---|---|
committer | 2016-05-15 20:42:02 +0200 | |
commit | 034faaa9d818bd8c1c52c879e383b8e7350d3df5 (patch) | |
tree | 18333dad4b120905363456479bafb14fff1db299 /video/out/opengl/user_shaders.c | |
parent | 7c3d78fd82d4d1e1a0b15284386d39b4014cb7d1 (diff) |
vo_opengl: use RPN expressions for user hook sizes
This replaces the previous TRANSFORM by WIDTH, HEIGHT and OFFSET where
WIDTH and HEIGHT are RPN expressions. This allows for more fine-grained
control over the output size, and also makes sure that overwriting
existing textures works more cleanly.
(Also add some more useful bstr functions)
Diffstat (limited to 'video/out/opengl/user_shaders.c')
-rw-r--r-- | video/out/opengl/user_shaders.c | 84 |
1 files changed, 77 insertions, 7 deletions
diff --git a/video/out/opengl/user_shaders.c b/video/out/opengl/user_shaders.c index 0c1b765400..0cf80af115 100644 --- a/video/out/opengl/user_shaders.c +++ b/video/out/opengl/user_shaders.c @@ -16,6 +16,54 @@ */ #include "user_shaders.h" +#include "ctype.h" + +static bool parse_rpn_szexpr(struct bstr line, struct szexp out[MAX_SZEXP_SIZE]) +{ + int pos = 0; + + while (line.len > 0) { + struct bstr word = bstr_strip(bstr_splitchar(line, &line, ' ')); + if (word.len == 0) + continue; + + if (pos >= MAX_SZEXP_SIZE) + return false; + + struct szexp *exp = &out[pos++]; + + if (bstr_eatend0(&word, ".w") || bstr_eatend0(&word, ".width")) { + exp->tag = SZEXP_VAR_W; + exp->val.varname = word; + continue; + } + + if (bstr_eatend0(&word, ".h") || bstr_eatend0(&word, ".height")) { + exp->tag = SZEXP_VAR_H; + exp->val.varname = word; + continue; + } + + switch (word.start[0]) { + case '+': exp->tag = SZEXP_OP2; exp->val.op = SZEXP_OP_ADD; continue; + case '-': exp->tag = SZEXP_OP2; exp->val.op = SZEXP_OP_SUB; continue; + case '*': exp->tag = SZEXP_OP2; exp->val.op = SZEXP_OP_MUL; continue; + case '/': exp->tag = SZEXP_OP2; exp->val.op = SZEXP_OP_DIV; continue; + } + + if (isdigit(word.start[0])) { + exp->tag = SZEXP_CONST; + if (bstr_sscanf(word, "%f", &exp->val.cval) != 1) + return false; + continue; + } + + // Some sort of illegal expression + return false; + } + + return true; +} // Returns false if no more shaders could be parsed bool parse_user_shader_pass(struct mp_log *log, struct bstr *body, @@ -24,14 +72,19 @@ bool parse_user_shader_pass(struct mp_log *log, struct bstr *body, if (!body || !out || !body->start || body->len == 0) return false; - *out = (struct gl_user_shader){ .transform = identity_trans }; + *out = (struct gl_user_shader){ + .offset = identity_trans, + .width = {{ SZEXP_VAR_W, { .varname = bstr0("HOOKED") }}}, + .height = {{ SZEXP_VAR_H, { .varname = bstr0("HOOKED") }}}, + }; + int hook_idx = 0; int bind_idx = 0; // First parse all the headers while (true) { struct bstr rest; - struct bstr line = bstr_getline(*body, &rest); + struct bstr line = bstr_strip(bstr_getline(*body, &rest)); // Check for the presence of the magic line beginning if (!bstr_eatstart0(&line, "//!")) @@ -65,13 +118,30 @@ bool parse_user_shader_pass(struct mp_log *log, struct bstr *body, continue; } - if (bstr_eatstart0(&line, "TRANSFORM")) { - float sx, sy, ox, oy; - if (bstr_sscanf(line, "%f %f %f %f", &sx, &sy, &ox, &oy) != 4) { - mp_err(log, "Error while parsing TRANSFORM!\n"); + if (bstr_eatstart0(&line, "OFFSET")) { + float ox, oy; + if (bstr_sscanf(line, "%f %f", &ox, &oy) != 2) { + mp_err(log, "Error while parsing OFFSET!\n"); + return false; + } + out->offset.t[0] = ox; + out->offset.t[1] = oy; + continue; + } + + if (bstr_eatstart0(&line, "WIDTH")) { + if (!parse_rpn_szexpr(line, out->width)) { + mp_err(log, "Error while parsing WIDTH!\n"); + return false; + } + continue; + } + + if (bstr_eatstart0(&line, "HEIGHT")) { + if (!parse_rpn_szexpr(line, out->height)) { + mp_err(log, "Error while parsing HEIGHT!\n"); return false; } - out->transform = (struct gl_transform){{{sx, 0}, {0, sy}}, {ox, oy}}; continue; } |