summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/man/options.rst22
-rw-r--r--video/out/opengl/user_shaders.c79
-rw-r--r--video/out/opengl/user_shaders.h12
-rw-r--r--video/out/opengl/video.c28
4 files changed, 62 insertions, 79 deletions
diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst
index 814f6fe2d9..02cb4d826d 100644
--- a/DOCS/man/options.rst
+++ b/DOCS/man/options.rst
@@ -4249,20 +4249,22 @@ The following video options are currently all specific to ``--vo=opengl`` and
The name of this texture. Hooks can then bind the texture under this
name using BIND. This must be the first option of the texture block.
- SIZE <width> [<height>] [<depth>]
+ SIZE <width> [<height>] [<depth>] (required)
The dimensions of the texture. The height and depth are optional. The
type of texture (1D, 2D or 3D) depends on the number of components
specified.
- COMPONENTS <n>
- The number of components per texel contained in the texture. Defaults
- to 1.
-
- FORMAT <spec>
- The texture format for the samples. A valid texture specification is
- the number of bits followed by a single letter which is either ``f``
- (for float), ``i`` (for uint) or ``u`` (for unorm), for example
- ``32f``. Defaults to ``8i``.
+ FORMAT <name> (required)
+ The texture format for the samples. Supported texture formats are listed
+ in debug logging when the ``opengl`` VO is initialized (look for
+ ``Texture formats:``). Usually, this follows OpenGL naming conventions.
+ For example, ``rgb16`` provides 3 channels with normalized 16 bit
+ components. One oddity are float formats: for example, ``rgba16f`` has
+ 16 bit internal precision, but the texture data is provided as 32 bit
+ floats, and the driver converts the data on texture upload.
+
+ Although format names follow a common naming convention, not all of them
+ are available on all hardware, drivers, GL versions, and so on.
FILTER <LINEAR|NEAREST>
The min/magnification filter used when sampling from this texture.
diff --git a/video/out/opengl/user_shaders.c b/video/out/opengl/user_shaders.c
index a2cb766d48..799367f3e1 100644
--- a/video/out/opengl/user_shaders.c
+++ b/video/out/opengl/user_shaders.c
@@ -286,16 +286,19 @@ static bool parse_hook(struct mp_log *log, struct bstr *body,
return true;
}
-static bool parse_tex(struct mp_log *log, struct bstr *body,
+static bool parse_tex(struct mp_log *log, struct ra *ra, struct bstr *body,
struct gl_user_shader_tex *out)
{
*out = (struct gl_user_shader_tex){
.name = bstr0("USER_TEX"),
- .w = 1, .h = 1, .d = 1,
- .components = 1,
- .bytes = 1,
- .ctype = RA_CTYPE_UINT,
+ .params = {
+ .dimensions = 2,
+ .w = 1, .h = 1, .d = 1,
+ .render_src = true,
+ .src_linear = true,
+ },
};
+ struct ra_tex_params *p = &out->params;
while (true) {
struct bstr rest;
@@ -312,36 +315,29 @@ static bool parse_tex(struct mp_log *log, struct bstr *body,
}
if (bstr_eatstart0(&line, "SIZE")) {
- int num = bstr_sscanf(line, "%d %d %d", &out->w, &out->h, &out->d);
- if (num < 1 || num > 3 || out->w < 1 || out->h < 1 || out->d < 1) {
+ p->dimensions = bstr_sscanf(line, "%d %d %d", &p->w, &p->h, &p->d);
+ if (p->dimensions < 1 || p->dimensions > 3 ||
+ p->w < 1 || p->h < 1 || p->d < 1)
+ {
mp_err(log, "Error while parsing SIZE!\n");
return false;
}
- out->dimensions = num;
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;
- }
-
- if (bstr_eatstart0(&line, "FORMAT")) {
- int bits;
- char fmt;
- if (bstr_sscanf(line, "%d%c", &bits, &fmt) != 2) {
- mp_err(log, "Error while parsing FORMAT!\n");
- return false;
+ if (bstr_eatstart0(&line, "FORMAT ")) {
+ p->format = NULL;
+ for (int n = 0; n < ra->num_formats; n++) {
+ const struct ra_format *fmt = ra->formats[n];
+ if (bstr_equals0(line, fmt->name)) {
+ p->format = fmt;
+ break;
+ }
}
-
- out->bytes = bits / 8;
- switch (fmt) {
- case 'u': out->ctype = RA_CTYPE_UINT; break;
- default:
- mp_err(log, "Unrecognized FORMAT description: '%c'!\n", fmt);
+ // (pixel_size==0 is for opaque formats)
+ if (!p->format || !p->format->pixel_size) {
+ mp_err(log, "Unrecognized/unavailable FORMAT name: '%.*s'!\n",
+ BSTR_P(line));
return false;
}
continue;
@@ -350,9 +346,9 @@ static bool parse_tex(struct mp_log *log, struct bstr *body,
if (bstr_eatstart0(&line, "FILTER")) {
line = bstr_strip(line);
if (bstr_equals0(line, "LINEAR")) {
- out->filter = true;
+ p->src_linear = true;
} else if (bstr_equals0(line, "NEAREST")) {
- out->filter = false;
+ p->src_linear = false;
} else {
mp_err(log, "Unrecognized FILTER: '%.*s'!\n", BSTR_P(line));
return false;
@@ -363,9 +359,9 @@ static bool parse_tex(struct mp_log *log, struct bstr *body,
if (bstr_eatstart0(&line, "BORDER")) {
line = bstr_strip(line);
if (bstr_equals0(line, "CLAMP")) {
- out->border = GL_CLAMP_TO_EDGE;
+ p->src_repeat = false;
} else if (bstr_equals0(line, "REPEAT")) {
- out->border = true;
+ p->src_repeat = true;
} else {
mp_err(log, "Unrecognized BORDER: '%.*s'!\n", BSTR_P(line));
return false;
@@ -377,6 +373,16 @@ static bool parse_tex(struct mp_log *log, struct bstr *body,
return false;
}
+ if (!p->format) {
+ mp_err(log, "No FORMAT specified.\n");
+ return false;
+ }
+
+ if (p->src_linear && !p->format->linear_filter) {
+ mp_err(log, "The specified texture format cannot be filtered!\n");
+ return false;
+ }
+
// Decode the rest of the section (up to the next //! marker) as raw hex
// data for the texture
struct bstr hexdata;
@@ -393,7 +399,7 @@ static bool parse_tex(struct mp_log *log, struct bstr *body,
return false;
}
- int expected_len = out->w * out->h * out->d * out->components * out->bytes;
+ int expected_len = p->w * p->h * p->d * p->format->pixel_size;
if (tex.len != expected_len) {
mp_err(log, "Shader TEXTURE size mismatch: got %zd bytes, expected %d!\n",
tex.len, expected_len);
@@ -401,11 +407,12 @@ static bool parse_tex(struct mp_log *log, struct bstr *body,
return false;
}
- out->texdata = tex.start;
+ p->initial_data = tex.start;
return true;
}
-void parse_user_shader(struct mp_log *log, struct bstr shader, void *priv,
+void parse_user_shader(struct mp_log *log, struct ra *ra, struct bstr shader,
+ void *priv,
bool (*dohook)(void *p, struct gl_user_shader_hook hook),
bool (*dotex)(void *p, struct gl_user_shader_tex tex))
{
@@ -426,7 +433,7 @@ void parse_user_shader(struct mp_log *log, struct bstr shader, void *priv,
// Peek at the first header to dispatch the right type
if (bstr_startswith0(shader, "//!TEXTURE")) {
struct gl_user_shader_tex t;
- if (!parse_tex(log, &shader, &t) || !dotex(priv, t))
+ if (!parse_tex(log, ra, &shader, &t) || !dotex(priv, t))
return;
continue;
}
diff --git a/video/out/opengl/user_shaders.h b/video/out/opengl/user_shaders.h
index bd36387de9..888422608c 100644
--- a/video/out/opengl/user_shaders.h
+++ b/video/out/opengl/user_shaders.h
@@ -72,21 +72,15 @@ struct gl_user_shader_hook {
struct gl_user_shader_tex {
struct bstr name;
- int dimensions;
- int w, h, d;
- int components;
- int bytes;
- enum ra_ctype ctype;
- bool filter;
- bool border;
- void *texdata;
+ struct ra_tex_params params;
// for video.c
struct ra_tex *tex;
};
// Parse the next shader block from `body`. The callbacks are invoked on every
// valid shader block parsed.
-void parse_user_shader(struct mp_log *log, struct bstr shader, void *priv,
+void parse_user_shader(struct mp_log *log, struct ra *ra, struct bstr shader,
+ void *priv,
bool (*dohook)(void *p, struct gl_user_shader_hook hook),
bool (*dotex)(void *p, struct gl_user_shader_tex tex));
diff --git a/video/out/opengl/video.c b/video/out/opengl/video.c
index 0cd7ef3688..b6be230b53 100644
--- a/video/out/opengl/video.c
+++ b/video/out/opengl/video.c
@@ -1973,34 +1973,14 @@ static bool add_user_tex(void *priv, struct gl_user_shader_tex tex)
goto err;
}
- const struct ra_format *format = ra_find_unorm_format(p->ra, tex.components,
- tex.bytes);
-
- if (!format) {
- MP_ERR(p, "Could not satisfy format requirements for user "
- "shader texture '%.*s'!\n", BSTR_P(tex.name));
- goto err;
- }
-
- struct ra_tex_params params = {
- .dimensions = tex.dimensions,
- .w = tex.w,
- .h = tex.h,
- .d = tex.d,
- .format = format,
- .render_src = true,
- .src_linear = tex.filter,
- .src_repeat = tex.border,
- .initial_data = tex.texdata,
- };
- tex.tex = ra_tex_create(p->ra, &params);
- talloc_free(tex.texdata);
+ tex.tex = ra_tex_create(p->ra, &tex.params);
+ TA_FREEP(&tex.params.initial_data);
p->user_textures[p->user_tex_num++] = tex;
return true;
err:
- talloc_free(tex.texdata);
+ talloc_free(tex.params.initial_data);
return false;
}
@@ -2011,7 +1991,7 @@ static void load_user_shaders(struct gl_video *p, char **shaders)
for (int n = 0; shaders[n] != NULL; n++) {
struct bstr file = load_cached_file(p, shaders[n]);
- parse_user_shader(p->log, file, p, add_user_hook, add_user_tex);
+ parse_user_shader(p->log, p->ra, file, p, add_user_hook, add_user_tex);
}
}