summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;