summaryrefslogtreecommitdiffstats
path: root/video/out/opengl/video.c
diff options
context:
space:
mode:
Diffstat (limited to 'video/out/opengl/video.c')
-rw-r--r--video/out/opengl/video.c71
1 files changed, 55 insertions, 16 deletions
diff --git a/video/out/opengl/video.c b/video/out/opengl/video.c
index 52dbe19961..e23bfb4edf 100644
--- a/video/out/opengl/video.c
+++ b/video/out/opengl/video.c
@@ -154,6 +154,7 @@ struct tex_hook {
void (*hook)(struct gl_video *p, struct img_tex tex, // generates GLSL
struct gl_transform *trans, void *priv);
void (*free)(struct tex_hook *hook);
+ bool (*cond)(struct gl_video *p, struct img_tex tex, void *priv);
};
struct fbosurface {
@@ -1132,6 +1133,12 @@ static struct img_tex pass_hook(struct gl_video *p, const char *name,
if (strcmp(hook->hook_tex, name) != 0)
continue;
+ // Check the hook's condition
+ if (hook->cond && !hook->cond(p, tex, hook->priv)) {
+ MP_DBG(p, "Skipping hook on %s due to condition.\n", name);
+ continue;
+ }
+
// Bind all necessary textures and add them to the prelude
for (int t = 0; t < TEXUNIT_VIDEO_NUM; t++) {
const char *bind_name = hook->bind_tex[t];
@@ -1149,12 +1156,11 @@ static struct img_tex pass_hook(struct gl_video *p, const char *name,
}
if (!saved_tex_find(p, bind_name, &bind_tex)) {
- // Clean up texture bindings and just return as-is, stop
- // all further processing of this hook
- MP_ERR(p, "Failed running hook for %s: No saved texture named"
- " %s!\n", name, bind_name);
+ // Clean up texture bindings and move on to the next hook
+ MP_DBG(p, "Skipping hook on %s due to no texture named %s.\n",
+ name, bind_name);
p->pass_tex_num -= t;
- return tex;
+ goto next_hook;
}
hook_prelude(p, bind_name, pass_bind(p, bind_tex), bind_tex);
@@ -1197,6 +1203,8 @@ static struct img_tex pass_hook(struct gl_video *p, const char *name,
}
saved_tex_store(p, store_name, saved_tex);
+
+next_hook: ;
}
return tex;
@@ -1615,9 +1623,10 @@ static void user_hook_old(struct gl_video *p, struct img_tex tex,
GLSLF("color = %s(HOOKED_raw, HOOKED_pos, HOOKED_size);\n", fn_name);
}
-// Returns 1.0 on failure to at least create a legal FBO
-static float eval_szexpr(struct gl_video *p, struct img_tex tex,
- struct szexp expr[MAX_SZEXP_SIZE])
+// Returns whether successful. 'result' is left untouched on failure
+static bool eval_szexpr(struct gl_video *p, struct img_tex tex,
+ struct szexp expr[MAX_SZEXP_SIZE],
+ float *result)
{
float stack[MAX_SZEXP_SIZE] = {0};
int idx = 0; // points to next element to push
@@ -1634,10 +1643,22 @@ static float eval_szexpr(struct gl_video *p, struct img_tex tex,
stack[idx++] = expr[i].val.cval;
continue;
+ case SZEXP_OP1:
+ if (idx < 1) {
+ MP_WARN(p, "Stack underflow in RPN expression!\n");
+ return false;
+ }
+
+ switch (expr[i].val.op) {
+ case SZEXP_OP_NOT: stack[idx-1] = !stack[idx-1]; break;
+ default: abort();
+ }
+ continue;
+
case SZEXP_OP2:
if (idx < 2) {
MP_WARN(p, "Stack underflow in RPN expression!\n");
- return 1.0;
+ return false;
}
// Pop the operands in reverse order
@@ -1649,12 +1670,14 @@ static float eval_szexpr(struct gl_video *p, struct img_tex tex,
case SZEXP_OP_SUB: res = op1 - op2; break;
case SZEXP_OP_MUL: res = op1 * op2; break;
case SZEXP_OP_DIV: res = op1 / op2; break;
+ case SZEXP_OP_GT: res = op1 > op2; break;
+ case SZEXP_OP_LT: res = op1 < op2; break;
default: abort();
}
- if (isnan(res)) {
+ if (!isfinite(res)) {
MP_WARN(p, "Illegal operation in RPN expression!\n");
- return 1.0;
+ return false;
}
stack[idx++] = res;
@@ -1679,7 +1702,7 @@ static float eval_szexpr(struct gl_video *p, struct img_tex tex,
}
MP_WARN(p, "Texture %.*s not found in RPN expression!\n", BSTR_P(name));
- return 1.0;
+ return false;
found_tex:
stack[idx++] = (expr[i].tag == SZEXP_VAR_W) ? var_tex.w : var_tex.h;
@@ -1692,10 +1715,21 @@ done:
// Return the single stack element
if (idx != 1) {
MP_WARN(p, "Malformed stack after RPN expression!\n");
- return 1.0;
+ return false;
}
- return stack[0];
+ *result = stack[0];
+ return true;
+}
+
+static bool user_hook_cond(struct gl_video *p, struct img_tex tex, void *priv)
+{
+ struct gl_user_shader *shader = priv;
+ assert(shader);
+
+ float res = false;
+ eval_szexpr(p, tex, shader->cond, &res);
+ return res;
}
static void user_hook(struct gl_video *p, struct img_tex tex,
@@ -1708,8 +1742,12 @@ static void user_hook(struct gl_video *p, struct img_tex tex,
GLSLF("// custom hook\n");
GLSLF("color = hook();\n");
- float w = eval_szexpr(p, tex, shader->width);
- float h = eval_szexpr(p, tex, shader->height);
+ // Make sure we at least create a legal FBO on failure, since it's better
+ // to do this and display an error message than just crash OpenGL
+ float w = 1.0, h = 1.0;
+
+ eval_szexpr(p, tex, shader->width, &w);
+ eval_szexpr(p, tex, shader->height, &h);
*trans = (struct gl_transform){{{w / tex.w, 0}, {0, h / tex.h}}};
gl_transform_trans(shader->offset, trans);
@@ -1757,6 +1795,7 @@ static void pass_hook_user_shaders(struct gl_video *p, char **shaders)
.components = out.components,
.hook = user_hook,
.free = user_hook_free,
+ .cond = user_hook_cond,
};
for (int i = 0; i < SHADER_MAX_HOOKS; i++) {