From 1df2edda3a1ae400a09244f3d7e6c7d69e3a43ac Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 28 Mar 2013 20:48:53 +0100 Subject: gl_video: make it possible for planes to have different formats Preparation for NV12 support. Also adds support for IMGFMT_YA8. --- video/out/gl_video.c | 94 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 56 insertions(+), 38 deletions(-) (limited to 'video') diff --git a/video/out/gl_video.c b/video/out/gl_video.c index 2cdf1f597a..ee2cdffe6f 100644 --- a/video/out/gl_video.c +++ b/video/out/gl_video.c @@ -93,6 +93,9 @@ struct vertex { struct texplane { int w, h; int tex_w, tex_h; + GLint gl_internal_format; + GLenum gl_format; + GLenum gl_type; GLuint gl_texture; int gl_buffer; int buffer_size; @@ -161,10 +164,6 @@ struct gl_video { int plane_bits; int plane_count; - GLint gl_internal_format; - GLenum gl_format; - GLenum gl_type; - struct video_image image; struct fbotex indirect_fbo; // RGB target @@ -194,6 +193,9 @@ struct fmt_entry { }; static const struct fmt_entry mp_to_gl_formats[] = { + {IMGFMT_Y8, GL_RED, GL_RED, GL_UNSIGNED_BYTE}, + {IMGFMT_Y16, GL_R16, GL_RED, GL_UNSIGNED_SHORT}, + {IMGFMT_YA8, GL_RG, GL_RG, GL_UNSIGNED_BYTE}, {IMGFMT_RGB48, GL_RGB16, GL_RGB, GL_UNSIGNED_SHORT}, {IMGFMT_RGB24, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE}, {IMGFMT_RGBA, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE}, @@ -206,6 +208,9 @@ static const struct fmt_entry mp_to_gl_formats[] = { {0}, }; +static const int byte_formats[3] = + {0, IMGFMT_Y8, IMGFMT_Y16}; + static const char *osd_shaders[SUBBITMAP_COUNT] = { [SUBBITMAP_LIBASS] = "frag_osd_libass", [SUBBITMAP_RGBA] = "frag_osd_rgba", @@ -1020,7 +1025,7 @@ static void init_video(struct gl_video *p) if (!p->is_yuv && (p->opts.srgb || p->use_lut_3d)) { p->is_linear_rgb = true; - p->gl_internal_format = GL_SRGB; + p->image.planes[0].gl_internal_format = GL_SRGB; } int eq_caps = MP_CSP_EQ_CAPS_GAMMA; @@ -1048,9 +1053,10 @@ static void init_video(struct gl_video *p) gl->GenTextures(1, &plane->gl_texture); gl->BindTexture(GL_TEXTURE_2D, plane->gl_texture); - gl->TexImage2D(GL_TEXTURE_2D, 0, p->gl_internal_format, - plane->tex_w, plane->tex_h, 0, - p->gl_format, p->gl_type, NULL); + gl->TexImage2D(GL_TEXTURE_2D, 0, plane->gl_internal_format, + plane->tex_w, plane->tex_h, 0, + plane->gl_format, plane->gl_type, NULL); + default_tex_params(gl, GL_TEXTURE_2D, GL_LINEAR); } gl->ActiveTexture(GL_TEXTURE0); @@ -1332,8 +1338,8 @@ void gl_video_upload_image(struct gl_video *p, struct mp_image *mpi) } gl->ActiveTexture(GL_TEXTURE0 + n); gl->BindTexture(GL_TEXTURE_2D, plane->gl_texture); - glUploadTex(gl, GL_TEXTURE_2D, p->gl_format, p->gl_type, plane_ptr, - mpi->stride[n], 0, 0, plane->w, plane->h, 0); + glUploadTex(gl, GL_TEXTURE_2D, plane->gl_format, plane->gl_type, + plane_ptr, mpi->stride[n], 0, 0, plane->w, plane->h, 0); } gl->ActiveTexture(GL_TEXTURE0); gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); @@ -1359,9 +1365,10 @@ struct mp_image *gl_video_download_image(struct gl_video *p) // screenshot. (If not, code should be added to make it fully opaque.) for (int n = 0; n < p->plane_count; n++) { + struct texplane *plane = &vimg->planes[n]; gl->ActiveTexture(GL_TEXTURE0 + n); - gl->BindTexture(GL_TEXTURE_2D, vimg->planes[n].gl_texture); - glDownloadTex(gl, GL_TEXTURE_2D, p->gl_format, p->gl_type, + gl->BindTexture(GL_TEXTURE_2D, plane->gl_texture); + glDownloadTex(gl, GL_TEXTURE_2D, plane->gl_format, plane->gl_type, image->planes[n], image->stride[n]); } gl->ActiveTexture(GL_TEXTURE0); @@ -1578,52 +1585,63 @@ static bool init_format(int fmt, struct gl_video *init) if (!desc.id) return false; - init->image_format = fmt; - init->plane_bits = desc.plane_bits; + if (desc.num_planes > 4) + return false; - // RGB/packed formats - for (const struct fmt_entry *e = mp_to_gl_formats; e->mp_format; e++) { - if (e->mp_format == fmt) { - supported = true; - init->plane_bits = desc.bpp[0]; - init->gl_format = e->format; - init->gl_internal_format = e->internal_format; - init->gl_type = e->type; - break; - } - } + int plane_format[4] = {0}; + + init->image_format = fmt; + init->plane_bits = desc.bpp[0]; // YUV/planar formats if (!supported && (desc.flags & MP_IMGFLAG_YUV_P)) { - init->gl_format = GL_RED; - if (init->plane_bits == 8) { - supported = true; - init->gl_internal_format = GL_RED; - init->gl_type = GL_UNSIGNED_BYTE; - } else if (init->plane_bits <= 16 && (desc.flags & MP_IMGFLAG_NE)) { + int bits = desc.plane_bits; + if ((desc.flags & MP_IMGFLAG_NE) && bits >= 8 && bits <= 16) { supported = true; - init->gl_internal_format = GL_R16; - init->gl_type = GL_UNSIGNED_SHORT; + init->plane_bits = bits; + plane_format[0] = byte_formats[(bits + 7) / 8]; } } // RGB/planar if (!supported && fmt == IMGFMT_GBRP) { supported = true; - init->plane_bits = 8; - init->gl_format = GL_RED; - init->gl_internal_format = GL_RED; - init->gl_type = GL_UNSIGNED_BYTE; + plane_format[0] = byte_formats[1]; + } + + // All formats in mp_to_gl_formats[] are supported + // If it's not in the table, it will be rejected below. + // Includes packed RGB and YUV formats + if (!supported && desc.num_planes == 1) { + supported = true; + plane_format[0] = fmt; } if (!supported) return false; + for (int p = 0; p < desc.num_planes; p++) { + struct texplane *plane = &init->image.planes[p]; + if (p > 0 && !plane_format[p]) + plane_format[p] = plane_format[0]; + for (const struct fmt_entry *e = mp_to_gl_formats; e->mp_format; e++) { + if (e->mp_format == plane_format[p]) { + plane->gl_format = e->format; + plane->gl_internal_format = e->internal_format; + plane->gl_type = e->type; + goto found; + } + } + return false; // not found + found: ; + } + init->is_yuv = desc.flags & MP_IMGFLAG_YUV; init->is_linear_rgb = false; // NOTE: we throw away the additional alpha plane, if one exists. - init->plane_count = desc.num_planes > 2 ? 3 : 1; + // (2 plane formats with a 2nd alpha plane don't exist) + init->plane_count = FFMIN(desc.num_planes, 3); assert(desc.num_planes >= init->plane_count); assert(desc.num_planes <= init->plane_count + 1); -- cgit v1.2.3