diff options
author | 2016-04-21 01:33:13 +0200 | |
---|---|---|
committer | 2016-05-15 20:42:02 +0200 | |
commit | 7c3d78fd82d4d1e1a0b15284386d39b4014cb7d1 (patch) | |
tree | 9fb8e7c6f7d38bb3b45f65d5406a83dfcba45b4a /video/out/opengl/user_shaders.c | |
parent | d53142f9bac1d8b17d3eeed258625b6739d34487 (diff) |
vo_opengl: support external user hooks
This allows users to add their own near-arbitrary hooks to the vo_opengl
processing pipeline, greatly enhancing the flexibility of user shaders.
This enables, among other things, user shaders such as CrossBilateral,
SuperRes, LumaSharpen and many more.
To make parsing the user shaders easier, shaders are now loaded as
bstrs, and the hooks are set up during video reconfig instead of on
every single frame.
Diffstat (limited to 'video/out/opengl/user_shaders.c')
-rw-r--r-- | video/out/opengl/user_shaders.c | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/video/out/opengl/user_shaders.c b/video/out/opengl/user_shaders.c new file mode 100644 index 0000000000..0c1b765400 --- /dev/null +++ b/video/out/opengl/user_shaders.c @@ -0,0 +1,106 @@ +/* + * This file is part of mpv. + * + * mpv is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * mpv 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with mpv. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "user_shaders.h" + +// Returns false if no more shaders could be parsed +bool parse_user_shader_pass(struct mp_log *log, struct bstr *body, + struct gl_user_shader *out) +{ + if (!body || !out || !body->start || body->len == 0) + return false; + + *out = (struct gl_user_shader){ .transform = identity_trans }; + 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); + + // Check for the presence of the magic line beginning + if (!bstr_eatstart0(&line, "//!")) + break; + + *body = rest; + + // Parse the supported commands + if (bstr_eatstart0(&line, "HOOK")) { + if (hook_idx == SHADER_MAX_HOOKS) { + mp_err(log, "Passes may only hook up to %d textures!\n", + SHADER_MAX_HOOKS); + return false; + } + out->hook_tex[hook_idx++] = bstr_strip(line); + continue; + } + + if (bstr_eatstart0(&line, "BIND")) { + if (bind_idx == SHADER_MAX_BINDS) { + mp_err(log, "Passes may only bind up to %d textures!\n", + SHADER_MAX_BINDS); + return false; + } + out->bind_tex[bind_idx++] = bstr_strip(line); + continue; + } + + if (bstr_eatstart0(&line, "SAVE")) { + out->save_tex = bstr_strip(line); + 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"); + return false; + } + out->transform = (struct gl_transform){{{sx, 0}, {0, sy}}, {ox, oy}}; + continue; + } + + if (bstr_eatstart0(&line, "COMPONENTS")) { + if (bstr_sscanf(line, "%d", &out->components) != 1) { + mp_err(log, "Error while parsing COMPONENTS!\n"); + return false; + } + continue; + } + + // Unknown command type + char *str = bstrto0(NULL, line); + mp_err(log, "Unrecognized command '%s'!\n", str); + talloc_free(str); + return false; + } + + // The rest of the file up until the next magic line beginning (if any) + // shall be the shader body + if (bstr_split_tok(*body, "//!", &out->pass_body, body)) { + // Make sure the magic line is part of the rest + body->start -= 3; + body->len += 3; + } + + // Sanity checking + if (hook_idx == 0) + mp_warn(log, "Pass has no hooked textures (will be ignored)!\n"); + + return true; +} |