diff options
Diffstat (limited to 'video/out')
-rw-r--r-- | video/out/opengl/formats.c | 108 | ||||
-rw-r--r-- | video/out/opengl/formats.h | 20 | ||||
-rw-r--r-- | video/out/opengl/hwdec.h | 1 | ||||
-rw-r--r-- | video/out/opengl/hwdec_ios.m | 3 | ||||
-rw-r--r-- | video/out/opengl/hwdec_osx.c | 3 | ||||
-rw-r--r-- | video/out/opengl/hwdec_vaegl.c | 2 | ||||
-rw-r--r-- | video/out/opengl/video.c | 99 |
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(®fmt, 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 = ®fmt.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; |