From 63b1031ca2bb57ce101de274fbe3cbe16ff5222f Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 15 Aug 2017 17:00:35 +0200 Subject: vo_opengl: support float pixel formats Like AV_PIX_FMT_GBRPF32LE. --- video/img_format.c | 25 ++++++++++++++++++++++++- video/img_format.h | 11 +++++++++++ video/out/opengl/ra.c | 38 ++++++++++++++++++++++++++++++++------ 3 files changed, 67 insertions(+), 7 deletions(-) diff --git a/video/img_format.c b/video/img_format.c index 2c495a0a51..e89734031c 100644 --- a/video/img_format.c +++ b/video/img_format.c @@ -128,6 +128,8 @@ struct mp_imgfmt_desc mp_imgfmt_get_desc(int mpfmt) if (!pd || pd->nb_components > 4 || fmt == AV_PIX_FMT_NONE || fmt == AV_PIX_FMT_UYYVYY411) return mp_only_imgfmt_desc(mpfmt); + enum mp_component_type is_uint = + mp_imgfmt_get_component_type(fmt) == MP_COMPONENT_TYPE_UINT; struct mp_imgfmt_desc desc = { .id = mpfmt, @@ -229,7 +231,7 @@ struct mp_imgfmt_desc mp_imgfmt_get_desc(int mpfmt) && (desc.flags & MP_IMGFLAG_BYTE_ALIGNED) && !(pd->flags & AV_PIX_FMT_FLAG_PAL) && !component_byte_overlap - && shift >= 0) + && shift >= 0 && is_uint) { bool same_depth = true; for (int p = 0; p < desc.num_planes; p++) { @@ -332,6 +334,22 @@ enum mp_csp mp_imgfmt_get_forced_csp(int imgfmt) return MP_CSP_AUTO; } +enum mp_component_type mp_imgfmt_get_component_type(int imgfmt) +{ + const AVPixFmtDescriptor *pixdesc = + av_pix_fmt_desc_get(imgfmt2pixfmt(imgfmt)); + + if (!pixdesc) + return MP_COMPONENT_TYPE_UNKNOWN; + +#ifdef AV_PIX_FMT_FLAG_FLOAT + if (pixdesc->flags & AV_PIX_FMT_FLAG_FLOAT) + return MP_COMPONENT_TYPE_FLOAT; +#endif + + return MP_COMPONENT_TYPE_UINT; +} + static bool is_native_endian(const AVPixFmtDescriptor *pixdesc) { enum AVPixelFormat pixfmt = av_pix_fmt_desc_get_id(pixdesc); @@ -357,6 +375,10 @@ bool mp_get_regular_imgfmt(struct mp_regular_imgfmt *dst, int imgfmt) !is_native_endian(pixdesc)) return false; + res.component_type = mp_imgfmt_get_component_type(imgfmt); + if (!res.component_type) + return false; + const AVComponentDescriptor *comp0 = &pixdesc->comp[0]; int depth = comp0->depth + comp0->shift; @@ -497,6 +519,7 @@ int main(int argc, char **argv) int fcsp = mp_imgfmt_get_forced_csp(mpfmt); if (fcsp) printf(" fcsp=%d", fcsp); + printf(" ctype=%d", mp_imgfmt_get_component_type(mpfmt)); printf("\n"); printf(" planes=%d, chroma=%d:%d align=%d:%d bits=%d cbits=%d\n", d.num_planes, d.chroma_xs, d.chroma_ys, d.align_x, d.align_y, diff --git a/video/img_format.h b/video/img_format.h index 631baf4a0a..7f0330d55b 100644 --- a/video/img_format.h +++ b/video/img_format.h @@ -101,6 +101,14 @@ struct mp_imgfmt_desc mp_imgfmt_get_desc(int imgfmt); // (Because IMGFMT/AV_PIX_FMT conflate format and csp for RGB and XYZ.) enum mp_csp mp_imgfmt_get_forced_csp(int imgfmt); +enum mp_component_type { + MP_COMPONENT_TYPE_UNKNOWN = 0, + MP_COMPONENT_TYPE_UINT, + MP_COMPONENT_TYPE_FLOAT, +}; + +enum mp_component_type mp_imgfmt_get_component_type(int imgfmt); + #define MP_NUM_COMPONENTS 4 struct mp_regular_imgfmt_plane { @@ -113,6 +121,9 @@ struct mp_regular_imgfmt_plane { // This describes pixel formats that are byte aligned, have byte aligned // components, native endian, etc. struct mp_regular_imgfmt { + // Type of each component. + enum mp_component_type component_type; + // Size of each component in bytes. uint8_t component_size; diff --git a/video/out/opengl/ra.c b/video/out/opengl/ra.c index 7982beab7c..a5e69876b0 100644 --- a/video/out/opengl/ra.c +++ b/video/out/opengl/ra.c @@ -130,6 +130,23 @@ const struct ra_format *ra_find_uint_format(struct ra *ra, return NULL; } +// Find a float format of any precision that matches the C type of the same +// size for upload. +static const struct ra_format *ra_find_float_format(struct ra *ra, + int bytes_per_component, + int n_components) +{ + // Assumes ra_format are ordered by quality. + for (int n = 0; n < ra->num_formats; n++) { + const struct ra_format *fmt = ra->formats[n]; + if (fmt->ctype == RA_CTYPE_FLOAT && fmt->num_components == n_components && + fmt->pixel_size == bytes_per_component * n_components && + fmt->linear_filter && ra_format_is_regular(fmt)) + return fmt; + } + return NULL; +} + // Return a filterable regular format that uses float16 internally, but does 32 bit // transfer. (This is just so we don't need 32->16 bit conversion on CPU, // which would be ok but messy.) @@ -159,12 +176,20 @@ const struct ra_format *ra_find_named_format(struct ra *ra, const char *name) // Like ra_find_unorm_format(), but if no fixed point format is available, // return an unsigned integer format. static const struct ra_format *find_plane_format(struct ra *ra, int bytes, - int n_channels) + int n_channels, + enum mp_component_type ctype) { - const struct ra_format *f = ra_find_unorm_format(ra, bytes, n_channels); - if (f) - return f; - return ra_find_uint_format(ra, bytes, n_channels); + switch (ctype) { + case MP_COMPONENT_TYPE_UINT: { + const struct ra_format *f = ra_find_unorm_format(ra, bytes, n_channels); + if (f) + return f; + return ra_find_uint_format(ra, bytes, n_channels); + } + case MP_COMPONENT_TYPE_FLOAT: + return ra_find_float_format(ra, bytes, n_channels); + default: return NULL; + } } // Put a mapping of imgfmt to texture formats into *out. Basically it selects @@ -188,7 +213,8 @@ bool ra_get_imgfmt_desc(struct ra *ra, int imgfmt, struct ra_imgfmt_desc *out) for (int n = 0; n < regfmt.num_planes; n++) { struct mp_regular_imgfmt_plane *plane = ®fmt.planes[n]; res.planes[n] = find_plane_format(ra, regfmt.component_size, - plane->num_components); + plane->num_components, + regfmt.component_type); if (!res.planes[n]) return false; for (int i = 0; i < plane->num_components; i++) -- cgit v1.2.3