summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2017-06-30 16:57:17 +0200
committerwm4 <wm4@nowhere>2017-06-30 17:07:55 +0200
commit0c0a06140c8460115d5ce357a8adfc4d8c1bae69 (patch)
tree4a776f3152fa74ed81a0a2397d629edfd8ccdfba
parent91583fccac85880ad2199f50463c095560791d56 (diff)
downloadmpv-0c0a06140c8460115d5ce357a8adfc4d8c1bae69.tar.bz2
mpv-0c0a06140c8460115d5ce357a8adfc4d8c1bae69.tar.xz
vo_opengl: restructure format setup
Instead of setting up a weird swizzle (which is linked to how the internal renderer code works, rather than the generic format code), add per-component mapping to gl_imgfmt_desc. The renderer still computes the weird swizzle, but at least it's confined to itself. Also, it appears the hwdec backends don't need this anymore. It's really nice that the messy init_format() goes away too.
-rw-r--r--video/out/opengl/formats.c108
-rw-r--r--video/out/opengl/formats.h20
-rw-r--r--video/out/opengl/hwdec.h1
-rw-r--r--video/out/opengl/hwdec_ios.m3
-rw-r--r--video/out/opengl/hwdec_osx.c3
-rw-r--r--video/out/opengl/hwdec_vaegl.c2
-rw-r--r--video/out/opengl/video.c99
7 files changed, 105 insertions, 131 deletions
diff --git a/video/out/opengl/formats.c b/video/out/opengl/formats.c
index bf8f0f9eb5..562f35da31 100644
--- a/video/out/opengl/formats.c
+++ b/video/out/opengl/formats.c
@@ -96,16 +96,6 @@ static const struct gl_format gl_formats[] = {
{0}
};
-// Pairs of mpv formats and OpenGL types that match directly. Code using this
-// is supposed to look through the gl_formats table, and there is supposed to
-// be exactly 1 matching entry (which tells you format/internal format).
-static const int special_formats[][2] = {
- {IMGFMT_RGB565, GL_UNSIGNED_SHORT_5_6_5},
- {IMGFMT_UYVY, GL_UNSIGNED_SHORT_8_8_APPLE},
- {IMGFMT_YUYV, GL_UNSIGNED_SHORT_8_8_REV_APPLE},
- {0}
-};
-
// Return an or-ed combination of all F_ flags that apply.
int gl_format_feature_flags(GL *gl)
{
@@ -136,19 +126,14 @@ const struct gl_format *gl_find_internal_format(GL *gl, GLint internal_format)
return NULL;
}
-const struct gl_format *gl_find_special_format(GL *gl, int mpfmt)
+// Find the first supported format with a specific gl_format.type
+static const struct gl_format *gl_find_gl_type_format(GL *gl, GLenum type)
{
int features = gl_format_feature_flags(gl);
- for (int n = 0; special_formats[n][0]; n++) {
- if (special_formats[n][0] == mpfmt) {
- GLenum type = special_formats[n][1];
- for (int i = 0; gl_formats[i].type; i++) {
- const struct gl_format *f = &gl_formats[i];
- if (f->type == type && (f->flags & features))
- return f;
- }
- break;
- }
+ for (int i = 0; gl_formats[i].type; i++) {
+ const struct gl_format *f = &gl_formats[i];
+ if (f->type == type && (f->flags & features))
+ return f;
}
return NULL;
}
@@ -297,64 +282,55 @@ static const struct gl_format *find_plane_format(GL *gl, int bytes, int n_channe
return gl_find_uint_format(gl, bytes, n_channels);
}
-static int find_comp(uint8_t *components, int num_components, int component)
-{
- for (int n = 0; n < num_components; n++) {
- if (components[n] == component)
- return n;
- }
- return -1;
-}
-
// Put a mapping of imgfmt to OpenGL textures into *out. Basically it selects
// the correct texture formats needed to represent an imgfmt in OpenGL, with
// textures using the same memory organization as on the CPU.
// Each plane is represented by a texture, and each texture has a RGBA
-// component order. out->color_swizzle is set to permute the components back.
+// component order. out->components describes the meaning of them.
// May return integer formats for >8 bit formats, if the driver has no
// normalized 16 bit formats.
-// Returns false (and *out is set to all-0) if no format found.
+// Returns false (and *out is not touched) if no format found.
bool gl_get_imgfmt_desc(GL *gl, int imgfmt, struct gl_imgfmt_desc *out)
{
- *out = (struct gl_imgfmt_desc){0};
-
- struct mp_imgfmt_desc desc = mp_imgfmt_get_desc(imgfmt);
- if (!desc.id)
- return false;
-
- if (desc.num_planes > 4 || (desc.flags & MP_IMGFLAG_HWACCEL))
- return false;
-
- const struct gl_format *planes[4] = {0};
- char swizzle_tmp[MP_NUM_COMPONENTS + 1] = {0};
- char *swizzle = "rgba";
- struct mp_regular_imgfmt regfmt = {0};
+ struct gl_imgfmt_desc res = {0};
+ struct mp_regular_imgfmt regfmt;
if (mp_get_regular_imgfmt(&regfmt, imgfmt)) {
- uint8_t components[MP_NUM_COMPONENTS + 1] = {0};
- int num_components = 0;
+ res.num_planes = regfmt.num_planes;
+ res.component_bits = regfmt.component_size * 8;
+ res.component_pad = regfmt.component_pad;
for (int n = 0; n < regfmt.num_planes; n++) {
struct mp_regular_imgfmt_plane *plane = &regfmt.planes[n];
- planes[n] = find_plane_format(gl, regfmt.component_size,
- plane->num_components);
+ res.planes[n] = find_plane_format(gl, regfmt.component_size,
+ plane->num_components);
+ if (!res.planes[n])
+ return false;
for (int i = 0; i < plane->num_components; i++)
- components[num_components++] = plane->components[i];
- }
- swizzle = swizzle_tmp;
- for (int c = 0; c < 4; c++) {
- int loc = find_comp(components, num_components, c + 1);
- swizzle[c] = "rgba"[loc >= 0 && loc < 4 ? loc : 0];
+ res.components[n][i] = plane->components[i];
}
- swizzle[4] = '\0';
goto supported;
}
// Special formats for which OpenGL happens to have direct support.
- planes[0] = gl_find_special_format(gl, imgfmt);
- if (planes[0]) {
- // Packed YUV Apple formats color permutation
- if (planes[0]->format == GL_RGB_422_APPLE)
- swizzle = "gbra";
+ if (imgfmt == IMGFMT_RGB565) {
+ res.num_planes = 1;
+ res.planes[0] = gl_find_gl_type_format(gl, GL_UNSIGNED_SHORT_5_6_5);
+ if (!res.planes[0])
+ return false;
+ for (int n = 0; n < 3; n++)
+ res.components[0][n] = n + 1;
+ goto supported;
+ }
+ if (imgfmt == IMGFMT_UYVY || imgfmt == IMGFMT_YUYV) {
+ res.num_planes = 1;
+ res.planes[0] = gl_find_gl_type_format(gl, imgfmt == IMGFMT_UYVY
+ ? GL_UNSIGNED_SHORT_8_8_APPLE
+ : GL_UNSIGNED_SHORT_8_8_REV_APPLE);
+ if (!res.planes[0])
+ return false;
+ res.components[0][0] = 3;
+ res.components[0][1] = 1;
+ res.components[0][2] = 2;
goto supported;
}
@@ -363,14 +339,6 @@ bool gl_get_imgfmt_desc(GL *gl, int imgfmt, struct gl_imgfmt_desc *out)
supported:
- snprintf(out->swizzle, sizeof(out->swizzle), "%s", swizzle);
- out->num_planes = desc.num_planes;
- for (int n = 0; n < desc.num_planes; n++) {
- if (!planes[n])
- return false;
- out->xs[n] = desc.xs[n];
- out->ys[n] = desc.ys[n];
- out->planes[n] = planes[n];
- }
+ *out = res;
return true;
}
diff --git a/video/out/opengl/formats.h b/video/out/opengl/formats.h
index 288e92f5db..d86577547b 100644
--- a/video/out/opengl/formats.h
+++ b/video/out/opengl/formats.h
@@ -40,7 +40,6 @@ enum {
int gl_format_feature_flags(GL *gl);
const struct gl_format *gl_find_internal_format(GL *gl, GLint internal_format);
-const struct gl_format *gl_find_special_format(GL *gl, int mpfmt);
const struct gl_format *gl_find_format(GL *gl, int type, int flags,
int bytes_per_component, int n_components);
const struct gl_format *gl_find_unorm_format(GL *gl, int bytes_per_component,
@@ -59,12 +58,19 @@ int gl_bytes_per_pixel(GLenum format, GLenum type);
struct gl_imgfmt_desc {
int num_planes;
const struct gl_format *planes[4];
- // Chroma shift (sub-sampling) for each plane.
- int xs[4], ys[4];
- // Component order (e.g. "rgba"), applied after all planes are combined.
- // This has always 4 components (the excess components have no meaning).
- // (For GL_LUMINANCE_ALPHA, it is assumed "ra" has been assigned to "rg".)
- char swizzle[5];
+ // Component storage size in bits (possibly padded). For formats with
+ // different sizes per component, this is arbitrary. For padded formats
+ // like P010 or YUV420P10, padding is included.
+ int component_bits;
+ // Like mp_regular_imgfmt.component_pad.
+ int component_pad;
+ // For each texture and each texture output (rgba order) describe what
+ // component it returns.
+ // The values are like the values in mp_regular_imgfmt_plane.components[].
+ // Access as components[plane_nr][component_index]. Set unused items to 0.
+ // This pretends GL_RG is used instead of GL_LUMINANCE_ALPHA. The renderer
+ // fixes this later.
+ uint8_t components[4][4];
};
bool gl_get_imgfmt_desc(GL *gl, int imgfmt, struct gl_imgfmt_desc *out);
diff --git a/video/out/opengl/hwdec.h b/video/out/opengl/hwdec.h
index 962bd7b1bd..92875d915e 100644
--- a/video/out/opengl/hwdec.h
+++ b/video/out/opengl/hwdec.h
@@ -32,7 +32,6 @@ struct gl_hwdec_plane {
struct gl_hwdec_frame {
struct gl_hwdec_plane planes[4];
bool vdpau_fields;
- char swizzle[5]; // optional component swizzle (4 components if set)
};
struct gl_hwdec_driver {
diff --git a/video/out/opengl/hwdec_ios.m b/video/out/opengl/hwdec_ios.m
index 6cf1b803bd..9461f3d980 100644
--- a/video/out/opengl/hwdec_ios.m
+++ b/video/out/opengl/hwdec_ios.m
@@ -194,9 +194,6 @@ static int map_frame(struct gl_hwdec *hw, struct mp_image *hw_image,
};
}
- snprintf(out_frame->swizzle, sizeof(out_frame->swizzle), "%s",
- p->desc.swizzle);
-
return 0;
}
diff --git a/video/out/opengl/hwdec_osx.c b/video/out/opengl/hwdec_osx.c
index d4594e2dcc..81cd155cc5 100644
--- a/video/out/opengl/hwdec_osx.c
+++ b/video/out/opengl/hwdec_osx.c
@@ -151,9 +151,6 @@ static int map_frame(struct gl_hwdec *hw, struct mp_image *hw_image,
};
}
- snprintf(out_frame->swizzle, sizeof(out_frame->swizzle), "%s",
- p->desc.swizzle);
-
return 0;
}
diff --git a/video/out/opengl/hwdec_vaegl.c b/video/out/opengl/hwdec_vaegl.c
index 0d2f1b1a17..8306541586 100644
--- a/video/out/opengl/hwdec_vaegl.c
+++ b/video/out/opengl/hwdec_vaegl.c
@@ -381,8 +381,6 @@ static int map_frame(struct gl_hwdec *hw, struct mp_image *hw_image,
if (va_image->format.fourcc == VA_FOURCC_YV12)
MPSWAP(struct gl_hwdec_plane, out_frame->planes[1], out_frame->planes[2]);
- snprintf(out_frame->swizzle, sizeof(out_frame->swizzle), "%s", desc.swizzle);
-
return 0;
err:
diff --git a/video/out/opengl/video.c b/video/out/opengl/video.c
index d21a3d397a..3d765d0656 100644
--- a/video/out/opengl/video.c
+++ b/video/out/opengl/video.c
@@ -193,6 +193,7 @@ struct gl_video {
struct mp_image_params real_image_params; // configured format
struct mp_image_params image_params; // texture format (mind hwdec case)
struct mp_imgfmt_desc image_desc;
+ struct gl_imgfmt_desc gl_format; // texture format
int plane_count;
bool is_yuv, is_packed_yuv;
@@ -397,8 +398,6 @@ const struct m_sub_options gl_video_conf = {
static void uninit_rendering(struct gl_video *p);
static void uninit_scaler(struct gl_video *p, struct scaler *scaler);
static void check_gl_features(struct gl_video *p);
-static bool init_format(struct gl_video *p, int fmt, bool test_only);
-static void init_image_desc(struct gl_video *p, int fmt);
static bool gl_video_upload_image(struct gl_video *p, struct mp_image *mpi,
uint64_t id);
static const char *handle_scaler_opt(const char *name, bool tscale);
@@ -745,14 +744,33 @@ static void pass_get_img_tex(struct gl_video *p, struct video_image *vimg,
}
}
+// Return the index of the given component (assuming all non-padding components
+// of all planes are concatenated into a linear list).
+static int find_comp(struct gl_imgfmt_desc *desc, int component)
+{
+ int cur = 0;
+ for (int n = 0; n < desc->num_planes; n++) {
+ for (int i = 0; i < 4; i++) {
+ if (desc->components[n][i]) {
+ if (desc->components[n][i] == component)
+ return cur;
+ cur++;
+ }
+ }
+ }
+ return -1;
+}
+
static void init_video(struct gl_video *p)
{
GL *gl = p->gl;
+ p->hwdec_active = false;
+ p->use_integer_conversion = false;
+
if (p->hwdec && gl_hwdec_test_format(p->hwdec, p->image_params.imgfmt)) {
if (p->hwdec->driver->reinit(p->hwdec, &p->image_params) < 0)
MP_ERR(p, "Initializing texture for hardware decoding failed.\n");
- init_image_desc(p, p->image_params.imgfmt);
const char **exts = p->hwdec->glsl_extensions;
for (int n = 0; exts && exts[n]; n++)
gl_sc_enable_extension(p->sc, (char *)exts[n]);
@@ -761,10 +779,25 @@ static void init_video(struct gl_video *p)
MP_WARN(p, "Using HW-overlay mode. No GL filtering is performed "
"on the video!\n");
}
- } else {
- init_format(p, p->image_params.imgfmt, false);
}
+ p->gl_format = (struct gl_imgfmt_desc){0};
+ gl_get_imgfmt_desc(p->gl, p->image_params.imgfmt, &p->gl_format);
+
+ p->plane_count = p->gl_format.num_planes;
+
+ p->image_desc = mp_imgfmt_get_desc(p->image_params.imgfmt);
+ p->is_yuv = p->image_desc.flags & MP_IMGFLAG_YUV;
+ p->has_alpha = p->image_desc.flags & MP_IMGFLAG_ALPHA;
+ p->is_packed_yuv = p->image_params.imgfmt == IMGFMT_UYVY ||
+ p->image_params.imgfmt == IMGFMT_YUYV;
+
+ for (int c = 0; c < 4; c++) {
+ int loc = find_comp(&p->gl_format, c + 1);
+ p->color_swizzle[c] = "rgba"[loc >= 0 && loc < 4 ? loc : 0];
+ }
+ p->color_swizzle[4] = '\0';
+
// Format-dependent checks.
check_gl_features(p);
@@ -792,8 +825,14 @@ static void init_video(struct gl_video *p)
for (int n = 0; n < p->plane_count; n++) {
struct texplane *plane = &vimg->planes[n];
+ const struct gl_format *format = p->gl_format.planes[n];
plane->gl_target = gl_target;
+ plane->gl_format = format->format;
+ plane->gl_internal_format = format->internal_format;
+ plane->gl_type = format->type;
+
+ p->use_integer_conversion |= gl_is_integer_format(plane->gl_format);
plane->w = mp_image_plane_w(&layout, n);
plane->h = mp_image_plane_h(&layout, n);
@@ -2917,8 +2956,6 @@ static bool gl_video_upload_image(struct gl_video *p, struct mp_image *mpi,
.gl_format = plane->gl_format,
};
}
- snprintf(p->color_swizzle, sizeof(p->color_swizzle), "%s",
- gl_frame.swizzle);
} else {
MP_FATAL(p, "Mapping hardware decoded surface failed.\n");
goto error;
@@ -3197,34 +3234,19 @@ bool gl_video_showing_interpolated_frame(struct gl_video *p)
return p->is_interpolated;
}
-static void init_image_desc(struct gl_video *p, int fmt)
-{
- p->image_desc = mp_imgfmt_get_desc(fmt);
-
- p->plane_count = p->image_desc.num_planes;
- p->is_yuv = p->image_desc.flags & MP_IMGFLAG_YUV;
- p->has_alpha = p->image_desc.flags & MP_IMGFLAG_ALPHA;
- p->use_integer_conversion = false;
- p->color_swizzle[0] = '\0';
- p->is_packed_yuv = fmt == IMGFMT_UYVY || fmt == IMGFMT_YUYV;
- p->hwdec_active = false;
-}
-
-// test_only=true checks if the format is supported
-// test_only=false also initializes some rendering parameters accordingly
-static bool init_format(struct gl_video *p, int fmt, bool test_only)
+static bool is_imgfmt_desc_supported(struct gl_video *p,
+ const struct gl_imgfmt_desc *desc)
{
- int cdepth = mp_imgfmt_get_desc(fmt).component_bits;
- if (cdepth > 8 && cdepth < 16 && p->texture_16bit_depth < 16)
+ if (!desc->num_planes)
return false;
- struct gl_imgfmt_desc desc;
- if (!gl_get_imgfmt_desc(p->gl, fmt, &desc))
+ if (desc->component_bits > 8 && desc->component_bits < 16 &&
+ desc->component_pad < 0 && p->texture_16bit_depth < 16)
return false;
int use_integer = -1;
- for (int n = 0; n < desc.num_planes; n++) {
- int use_int_plane = gl_is_integer_format(desc.planes[n]->format);
+ for (int n = 0; n < desc->num_planes; n++) {
+ int use_int_plane = gl_is_integer_format(desc->planes[n]->format);
if (use_integer < 0)
use_integer = use_int_plane;
if (use_integer != use_int_plane)
@@ -3234,27 +3256,14 @@ static bool init_format(struct gl_video *p, int fmt, bool test_only)
if (use_integer && p->forced_dumb_mode)
return false;
- if (!test_only) {
- for (int n = 0; n < desc.num_planes; n++) {
- struct texplane *plane = &p->image.planes[n];
- const struct gl_format *format = desc.planes[n];
- plane->gl_format = format->format;
- plane->gl_internal_format = format->internal_format;
- plane->gl_type = format->type;
- }
-
- init_image_desc(p, fmt);
-
- p->use_integer_conversion = use_integer;
- snprintf(p->color_swizzle, sizeof(p->color_swizzle), "%s", desc.swizzle);
- }
-
return true;
}
bool gl_video_check_format(struct gl_video *p, int mp_format)
{
- if (init_format(p, mp_format, true))
+ struct gl_imgfmt_desc desc;
+ if (gl_get_imgfmt_desc(p->gl, mp_format, &desc) &&
+ is_imgfmt_desc_supported(p, &desc))
return true;
if (p->hwdec && gl_hwdec_test_format(p->hwdec, mp_format))
return true;