[vlc-commits] [Git][videolan/vlc][master] 7 commits: opengl: common: Add more format compat values

Jean-Baptiste Kempf (@jbk) gitlab at videolan.org
Sat Feb 25 08:57:41 UTC 2023



Jean-Baptiste Kempf pushed to branch master at VideoLAN / VLC


Commits:
61d29225 by Hugo Beauzée-Luyssen at 2023-02-25T08:43:29+00:00
opengl: common: Add more format compat values

- - - - -
d7f38080 by Hugo Beauzée-Luyssen at 2023-02-25T08:43:29+00:00
opengl: interop sw: Refactor initialization to simplify format selection

This now use a table and a format index to explicitly provide format &
internal format for both planes.
Some formats have been updated to abide by GLES specs

- - - - -
67bddf90 by Pierre Lamot at 2023-02-25T08:43:29+00:00
opengl: interop sw: Use format combinations that comply with GL & GLES

Some combinations weren't strictly valid for GLES and were causing some
failures when used in WebGL or older GLES implementations

Co-authored-by: Hugo Beauzée-Luyssen <hugo at beauzee.fr>

- - - - -
a7f088cb by Pierre Lamot at 2023-02-25T08:43:29+00:00
opengl: sampler: support 4 planes textures while sampling

For formats such as YUVA

- - - - -
ef0b62ff by Pierre Lamot at 2023-02-25T08:43:29+00:00
opengl: interop sw: Allow 4 panes YUV textures

they behave like 3 planes textures

- - - - -
11f91085 by Pierre Lamot at 2023-02-25T08:43:29+00:00
opengl: interop sw: support packed VUYA format

- - - - -
fd98c13d by Pierre Lamot at 2023-02-25T08:43:29+00:00
opengl: interop sw: fix UV plane uploading

UV planes are reported like having a pixel size of 1 but they should be read by
pair

- - - - -


3 changed files:

- modules/video_output/opengl/gl_common.h
- modules/video_output/opengl/interop_sw.c
- modules/video_output/opengl/sampler.c


Changes:

=====================================
modules/video_output/opengl/gl_common.h
=====================================
@@ -72,6 +72,9 @@
 #ifndef GL_R16
 # define GL_R16 0x822A
 #endif
+#ifndef GL_R16UI
+# define GL_R16UI 0x8234
+#endif
 #ifndef GL_BGRA
 # define GL_BGRA 0x80E1
 #endif
@@ -84,6 +87,24 @@
 #ifndef GL_LUMINANCE16
 # define GL_LUMINANCE16 0x8042
 #endif
+#ifndef GL_LUMINANCE16_ALPHA16
+# define GL_LUMINANCE16_ALPHA16 0x8048
+#endif
+#ifndef GL_R8
+# define GL_R8 0x8229
+#endif
+#ifndef GL_RG8
+# define GL_RG8 0x822B
+#endif
+#ifndef GL_RG_INTEGER
+# define GL_RG_INTEGER 0x8228
+#endif
+#ifndef GL_RED_INTEGER
+# define GL_RED_INTEGER 0x8D94
+#endif
+#ifndef GL_RG16UI
+# define GL_RG16UI 0x823A
+#endif
 #ifndef GL_TEXTURE_RED_SIZE
 # define GL_TEXTURE_RED_SIZE 0x805C
 #endif
@@ -93,7 +114,6 @@
 #ifndef GL_TEXTURE_WRAP_R
 # define GL_TEXTURE_WRAP_R 0x8072
 #endif
-
 #ifndef GL_CLAMP_TO_EDGE
 # define GL_CLAMP_TO_EDGE 0x812F
 #endif


=====================================
modules/video_output/opengl/interop_sw.c
=====================================
@@ -44,6 +44,7 @@ typedef struct
 
 struct priv
 {
+    bool   has_gl_3;
     bool   has_texture_rg;
     bool   has_unpack_subimage;
     void * texture_temp_buf;
@@ -204,7 +205,11 @@ tc_pbo_update(const struct vlc_gl_interop *interop, uint32_t textures[],
         priv->gl.ActiveTexture(GL_TEXTURE0 + i);
         priv->gl.BindTexture(interop->tex_target, textures[i]);
 
-        priv->gl.PixelStorei(GL_UNPACK_ROW_LENGTH, pic->p[i].i_pitch / pic->p[i].i_pixel_pitch);
+        //for YUV with interleaved UV, pixel pitch is reported as 1
+        if (pic->i_planes == 2 && interop->tex_count == 2 && i == 1)
+            priv->gl.PixelStorei(GL_UNPACK_ROW_LENGTH, pic->p[i].i_pitch / (pic->p[i].i_pixel_pitch * 2));
+        else
+            priv->gl.PixelStorei(GL_UNPACK_ROW_LENGTH, pic->p[i].i_pitch / pic->p[i].i_pixel_pitch);
 
         priv->gl.TexSubImage2D(interop->tex_target, 0, 0, 0, tex_width[i], tex_height[i],
                                    interop->texs[i].format, interop->texs[i].type, NULL);
@@ -221,6 +226,7 @@ tc_pbo_update(const struct vlc_gl_interop *interop, uint32_t textures[],
                                interop->texs[1].format, interop->texs[1].type, NULL);
         priv->gl.PixelStorei(GL_UNPACK_ROW_LENGTH, 0);
     }
+    GL_ASSERT_NOERROR(&priv->gl);
 
     /* turn off pbo */
     priv->gl.BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
@@ -239,6 +245,7 @@ tc_common_allocate_textures(const struct vlc_gl_interop *interop, uint32_t textu
         priv->gl.TexImage2D(interop->tex_target, 0, interop->texs[i].internal,
                                 tex_width[i], tex_height[i], 0, interop->texs[i].format,
                                 interop->texs[i].type, NULL);
+        GL_ASSERT_NOERROR(&priv->gl);
     }
     return VLC_SUCCESS;
 }
@@ -246,7 +253,7 @@ tc_common_allocate_textures(const struct vlc_gl_interop *interop, uint32_t textu
 static int
 upload_plane(const struct vlc_gl_interop *interop, unsigned tex_idx,
              int32_t width, int32_t height, size_t pitch, size_t pixel_size,
-             const void *pixels)
+             const void *pixels, unsigned pixel_pack)
 {
     struct priv *priv = interop->priv;
     GLenum tex_format = interop->texs[tex_idx].format;
@@ -261,7 +268,7 @@ upload_plane(const struct vlc_gl_interop *interop, unsigned tex_idx,
     assert(pitch % pixel_size == 0);
     assert((size_t) width * pixel_size <= pitch);
 
-    size_t width_bytes = width * pixel_size;
+    size_t width_bytes = width * pixel_size * pixel_pack;
 
     if (!priv->has_unpack_subimage)
     {
@@ -301,11 +308,15 @@ upload_plane(const struct vlc_gl_interop *interop, unsigned tex_idx,
     }
     else
     {
-        priv->gl.PixelStorei(GL_UNPACK_ROW_LENGTH, pitch / pixel_size);
+        priv->gl.PixelStorei(GL_UNPACK_ROW_LENGTH, pitch / (pixel_size * pixel_pack ));
+
         priv->gl.TexSubImage2D(interop->tex_target, 0, 0, 0, width, height,
                                tex_format, tex_type, pixels);
         priv->gl.PixelStorei(GL_UNPACK_ROW_LENGTH, 0);
     }
+
+    GL_ASSERT_NOERROR(&priv->gl);
+
     return VLC_SUCCESS;
 }
 
@@ -325,8 +336,10 @@ tc_common_update(const struct vlc_gl_interop *interop, uint32_t textures[],
                              &pic->p[i].p_pixels[plane_offset[i]] :
                              pic->p[i].p_pixels;
 
+        //are we uploading packed UV plane
+        unsigned pixel_pack = (pic->i_planes == 2 && i == 1) ? 2 : 1;
         ret = upload_plane(interop, i, tex_width[i], tex_height[i],
-                           pic->p[i].i_pitch, pic->p[i].i_pixel_pitch, pixels);
+                           pic->p[i].i_pitch, pic->p[i].i_pixel_pitch, pixels, pixel_pack);
     }
 
     if (pic->i_planes == 1 && interop->tex_count == 2)
@@ -340,7 +353,7 @@ tc_common_update(const struct vlc_gl_interop *interop, uint32_t textures[],
                              pic->p[0].p_pixels;
 
         ret = upload_plane(interop, 1, tex_width[1], tex_height[1],
-                           pic->p[0].i_pitch, pic->p[0].i_pixel_pitch, pixels);
+                           pic->p[0].i_pitch, pic->p[0].i_pixel_pitch, pixels, 2);
     }
 
     return ret;
@@ -354,6 +367,70 @@ DivideRationalByTwo(vlc_rational_t *r) {
         r->den *= 2;
 }
 
+static bool fixGLFormat(struct vlc_gl_interop *interop, GLint* intfmt, GLint* fmt)
+{
+    struct priv *priv = interop->priv;
+    if (*intfmt == 0)
+        return true;
+
+    //GLES 3.0, OpenGL 3.0 and OpenGL with GL_ARB_texture_rg
+    //don't need transformations
+    if (priv->has_gl_3
+        || (priv->has_texture_rg && interop->gl->api_type == VLC_OPENGL))
+        return true;
+
+    //for GLES2 GL_EXT_texture_rg we need to use GL_RED/GL_RG as internal format
+    if (priv->has_texture_rg)
+    {
+        switch (*intfmt) {
+        case GL_R8:
+            *intfmt = GL_RED;
+            *fmt = GL_RED;
+            break;
+        case GL_RG8:
+            *intfmt = GL_RG;
+            *fmt = GL_RG;
+            break;
+        case GL_R16UI:
+        case GL_RG16UI:
+            return false;
+        default:
+            vlc_assert_unreachable();
+        }
+
+        return true;
+    }
+
+    //fallback to GL_LUMINANCE / GL_LUMINANCE_ALPHA
+    switch (*intfmt) {
+    case GL_R8:
+        *intfmt = GL_LUMINANCE;
+        *fmt = GL_LUMINANCE;
+        break;
+    case GL_R16UI:
+        if (interop->gl->api_type == VLC_OPENGL_ES2)
+            return false;
+
+        *intfmt = GL_LUMINANCE16;
+        *fmt = GL_LUMINANCE;
+        break;
+    case GL_RG8:
+        *intfmt = GL_LUMINANCE_ALPHA;
+        *fmt = GL_LUMINANCE_ALPHA;
+        break;
+    case GL_RG16UI:
+        if (interop->gl->api_type == VLC_OPENGL_ES2)
+            return false;
+
+        *intfmt = GL_LUMINANCE16_ALPHA16;
+        *fmt = GL_LUMINANCE_ALPHA;
+        break;
+    default:
+        vlc_assert_unreachable();
+    }
+    return true;
+}
+
 static int
 interop_yuv_base_init(struct vlc_gl_interop *interop, GLenum tex_target,
                       vlc_fourcc_t chroma, const vlc_chroma_description_t *desc)
@@ -362,58 +439,128 @@ interop_yuv_base_init(struct vlc_gl_interop *interop, GLenum tex_target,
 
     (void) chroma;
 
-    GLint oneplane_texfmt, oneplane16_texfmt,
-          twoplanes_texfmt, twoplanes16_texfmt;
+    struct interop_formats
+    {
+        GLint intfmt;
+        GLint fmt;
+        GLint plane2_intfmt;
+        GLint plane2_fmt;
+        GLint type;
+        GLint plane2_type;
+    } formats[] = {
+        // 3 and 4 planes
+            // 8 bits pixels
+            { GL_R8, GL_RED, 0, 0, GL_UNSIGNED_BYTE, 0 },
+            // 16 bits pixels
+            { GL_R16UI, GL_RED, 0, 0, GL_UNSIGNED_SHORT, 0 },
+        // 2 planes
+            // 8 bits pixels
+            { GL_R8, GL_RED, GL_RG8, GL_RG, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE },
+            // 16 bits pixels
+            { GL_R16UI, GL_RED, GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_SHORT },
+        // 1 plane is a special case that will be handled explicitly
+    };
 
-    if (priv->has_texture_rg)
+    if (desc->plane_count == 1)
     {
-        oneplane_texfmt = GL_RED;
-        oneplane16_texfmt = GL_R16;
-        twoplanes_texfmt = GL_RG;
-        twoplanes16_texfmt = GL_RG16;
+        if (chroma == VLC_CODEC_VUYA)
+        {
+            interop->tex_count = 2;
+            interop->texs[0] = (struct vlc_gl_tex_cfg) {
+                { 1, 1 }, { 1, 1 },
+                GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE
+            };
+            return VLC_SUCCESS;
+        }
+        else if (desc->pixel_size != 2)
+        {
+            msg_Warn(interop->gl, "unsupported chroma %.4s", (char*)&chroma);
+            return VLC_EGENERIC;
+        }
+
+        /* Only YUV 4:2:2 formats */
+        /* The pictures have only 1 plane, but it is uploaded twice, once to
+         * access the Y components, once to access the UV components. See
+         * #26712. */
+        GLint intfmt = GL_RG8;
+        GLint fmt = GL_RG;
+        if (!fixGLFormat(interop, &intfmt, &fmt))
+            return VLC_EGENERIC;
+
+        interop->tex_count = 2;
+        interop->texs[0] = (struct vlc_gl_tex_cfg) {
+            { 1, 1 }, { 1, 1 },
+            intfmt, fmt, GL_UNSIGNED_BYTE
+        };
+        interop->texs[1] = (struct vlc_gl_tex_cfg) {
+            { 1, 2 }, { 1, 1 },
+            GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE
+        };
+        return VLC_SUCCESS;
     }
-    else
+
+    uint8_t format_index = 0;
+    switch (desc->plane_count)
     {
-        oneplane_texfmt = GL_LUMINANCE;
-        oneplane16_texfmt = GL_LUMINANCE16;
-        twoplanes_texfmt = GL_LUMINANCE_ALPHA;
-        twoplanes16_texfmt = 0;
+    case 4:
+    case 3:
+        break;
+    case 2:
+        format_index += 2;
+        break;
+    default:
+        vlc_assert_unreachable();
+        break;
     }
 
-    if (desc->pixel_size == 2)
+    switch (desc->pixel_size)
     {
-        if (vlc_gl_interop_GetTexFormatSize(interop, tex_target, oneplane_texfmt,
-                                            oneplane16_texfmt, GL_UNSIGNED_SHORT) != 16)
-            return VLC_EGENERIC;
+    case 1:
+        break;
+    case 2:
+        format_index += 1;
+        break;
+    default:
+        return VLC_EGENERIC;
     }
 
-    if (desc->plane_count == 3)
-    {
-        GLint internal = 0;
-        GLenum type = 0;
+    assert(format_index < ARRAY_SIZE(formats));
 
-        if (desc->pixel_size == 1)
-        {
-            internal = oneplane_texfmt;
-            type = GL_UNSIGNED_BYTE;
-        }
-        else if (desc->pixel_size == 2)
-        {
-            internal = oneplane16_texfmt;
-            type = GL_UNSIGNED_SHORT;
-        }
-        else
-            return VLC_EGENERIC;
+    struct interop_formats* format = &formats[format_index];
 
-        assert(internal != 0 && type != 0);
+    GLint plane1_intfmt = format->intfmt;
+    GLint plane1_fmt = format->fmt;
+    if (!fixGLFormat(interop, &plane1_intfmt, &plane1_fmt))
+        return VLC_EGENERIC;
+
+    GLint plane2_intfmt = format->plane2_intfmt;
+    GLint plane2_fmt = format->plane2_fmt;
+    if (!fixGLFormat(interop, &plane2_intfmt, &plane2_fmt))
+        return VLC_EGENERIC;
+
+    msg_Dbg(interop, "Using format at index %u", format_index);
+    msg_Dbg(interop, "Plane1: fmt=%#x intfmt=%#x type=%#x", plane1_fmt,
+            plane1_intfmt, format->type);
+    msg_Dbg(interop, "Plane2: fmt=%#x intfmt=%#x type=%#x", plane2_fmt,
+            plane2_intfmt, format->plane2_type);
+
+
+    if (desc->pixel_size == 2)
+    {
+        if (vlc_gl_interop_GetTexFormatSize(interop, tex_target, format->fmt,
+                                            format->intfmt, GL_UNSIGNED_SHORT) != 16)
+            return VLC_EGENERIC;
+    }
 
-        interop->tex_count = 3;
+    if (desc->plane_count >= 3)
+    {
+        interop->tex_count = desc->plane_count;
         for (unsigned i = 0; i < interop->tex_count; ++i )
         {
             interop->texs[i] = (struct vlc_gl_tex_cfg) {
                 { desc->p[i].w.num, desc->p[i].w.den },
                 { desc->p[i].h.num, desc->p[i].h.den },
-                internal, oneplane_texfmt, type
+                plane1_intfmt, plane1_fmt, format->type
             };
         }
     }
@@ -421,38 +568,23 @@ interop_yuv_base_init(struct vlc_gl_interop *interop, GLenum tex_target,
     {
         interop->tex_count = 2;
 
-        if (desc->pixel_size == 1)
+        if (desc->pixel_size == 2 &&
+            vlc_gl_interop_GetTexFormatSize(interop, tex_target, format->plane2_fmt,
+                format->plane2_intfmt, format->plane2_type) != 16)
         {
-            interop->texs[0] = (struct vlc_gl_tex_cfg) {
-                { desc->p[0].w.num, desc->p[0].w.den },
-                { desc->p[0].h.num, desc->p[0].h.den },
-                oneplane_texfmt, oneplane_texfmt, GL_UNSIGNED_BYTE
-            };
-            interop->texs[1] = (struct vlc_gl_tex_cfg) {
-                { desc->p[1].w.num, desc->p[1].w.den },
-                { desc->p[1].h.num, desc->p[1].h.den },
-                twoplanes_texfmt, twoplanes_texfmt, GL_UNSIGNED_BYTE
-            };
-        }
-        else if (desc->pixel_size == 2)
-        {
-            if (twoplanes16_texfmt == 0
-             || vlc_gl_interop_GetTexFormatSize(interop, tex_target, twoplanes_texfmt,
-                                                twoplanes16_texfmt, GL_UNSIGNED_SHORT) != 16)
-                return VLC_EGENERIC;
-            interop->texs[0] = (struct vlc_gl_tex_cfg) {
-                { desc->p[0].w.num, desc->p[0].w.den },
-                { desc->p[0].h.num, desc->p[0].h.den },
-                oneplane16_texfmt, oneplane_texfmt, GL_UNSIGNED_SHORT
-            };
-            interop->texs[1] = (struct vlc_gl_tex_cfg) {
-                { desc->p[1].w.num, desc->p[1].w.den },
-                { desc->p[1].h.num, desc->p[1].h.den },
-                twoplanes16_texfmt, twoplanes_texfmt, GL_UNSIGNED_SHORT
-            };
-        }
-        else
             return VLC_EGENERIC;
+        }
+
+        interop->texs[0] = (struct vlc_gl_tex_cfg) {
+            { desc->p[0].w.num, desc->p[0].w.den },
+            { desc->p[0].h.num, desc->p[0].h.den },
+            plane1_intfmt, plane1_fmt, format->type
+        };
+        interop->texs[1] = (struct vlc_gl_tex_cfg) {
+            { desc->p[1].w.num, desc->p[1].w.den },
+            { desc->p[1].h.num, desc->p[1].h.den },
+            plane2_intfmt, plane2_fmt, format->plane2_type
+        };
 
         /*
          * If plane_count == 2, then the chroma is semiplanar: the U and V
@@ -467,24 +599,6 @@ interop_yuv_base_init(struct vlc_gl_interop *interop, GLenum tex_target,
          */
          DivideRationalByTwo(&interop->texs[1].w);
     }
-    else if (desc->plane_count == 1)
-    {
-        /* Only YUV 4:2:2 formats */
-        /* The pictures have only 1 plane, but it is uploaded twice, once to
-         * access the Y components, once to access the UV components. See
-         * #26712. */
-        interop->tex_count = 2;
-        interop->texs[0] = (struct vlc_gl_tex_cfg) {
-            { 1, 1 }, { 1, 1 },
-            twoplanes_texfmt, twoplanes_texfmt, GL_UNSIGNED_BYTE
-        };
-        interop->texs[1] = (struct vlc_gl_tex_cfg) {
-            { 1, 2 }, { 1, 1 },
-            GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE
-        };
-    }
-    else
-        return VLC_EGENERIC;
 
     return VLC_SUCCESS;
 }
@@ -596,8 +710,10 @@ opengl_interop_generic_init(struct vlc_gl_interop *interop, bool allow_dr)
         || vlc_gl_HasExtension(&extension_vt, "GL_EXT_unpack_subimage");
 
     /* RG textures are available natively since OpenGL 3.0 and OpenGL ES 3.0 */
-    priv->has_texture_rg = vlc_gl_GetVersionMajor(&extension_vt) >= 3
-        || (interop->gl->api_type == VLC_OPENGL
+    priv->has_gl_3 = vlc_gl_GetVersionMajor(&extension_vt) >= 3;
+
+    priv->has_texture_rg =
+        (interop->gl->api_type == VLC_OPENGL
             && vlc_gl_HasExtension(&extension_vt, "GL_ARB_texture_rg"))
         || (interop->gl->api_type == VLC_OPENGL_ES2
             && vlc_gl_HasExtension(&extension_vt, "GL_EXT_texture_rg"));


=====================================
modules/video_output/opengl/sampler.c
=====================================
@@ -468,7 +468,9 @@ opengl_init_swizzle(struct vlc_gl_sampler *sampler,
                     vlc_fourcc_t chroma,
                     const vlc_chroma_description_t *desc)
 {
-    if (desc->plane_count == 3)
+    if (desc->plane_count == 4)
+        swizzle_per_tex[0] = swizzle_per_tex[1] = swizzle_per_tex[2] = swizzle_per_tex[3] = "r";
+    else if (desc->plane_count == 3)
         swizzle_per_tex[0] = swizzle_per_tex[1] = swizzle_per_tex[2] = "r";
     else if (desc->plane_count == 2)
     {
@@ -858,17 +860,22 @@ opengl_fragment_shader_init(struct vlc_gl_sampler *sampler, bool expose_planes)
             assert(swizzle);
             color_count += strlen(swizzle);
             assert(color_count < PICTURE_PLANE_MAX);
+            if (i > 0)
+                ADD("  ,");
             if (tex_target == GL_TEXTURE_RECTANGLE)
             {
                 /* The coordinates are in texels values, not normalized */
-                ADDF("  %s(Textures[%u], TexSizes[%u] * tex_coords).%s,\n", lookup, i, i, swizzle);
+                ADDF("  %s(Textures[%u], TexSizes[%u] * tex_coords).%s\n", lookup, i, i, swizzle);
             }
             else
             {
-                ADDF("  %s(Textures[%u], tex_coords).%s,\n", lookup, i, swizzle);
+                ADDF("  %s(Textures[%u], tex_coords).%s\n", lookup, i, swizzle);
             }
         }
-        ADD("  1.0);\n");
+        if (color_count == 3)
+            ADD("  ,  1.0);\n");
+        else
+            ADD(");\n");
         ADD(" vec4 result = ConvMatrix * pixel;\n");
     }
     else
@@ -879,7 +886,7 @@ opengl_fragment_shader_init(struct vlc_gl_sampler *sampler, bool expose_planes)
         ADDF(" vec4 result = %s(Textures[0], tex_coords);\n", lookup);
         color_count = 1;
     }
-    assert(yuv_space == COLOR_SPACE_UNDEF || color_count == 3);
+    assert(yuv_space == COLOR_SPACE_UNDEF || color_count == 3 || color_count == 4);
 
 #ifdef HAVE_LIBPLACEBO_GL
     if (priv->pl_sh_res) {



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/2f3f2253adfd612a507410755c64a13e437ec602...fd98c13dfc6db4b02dab48ffe9bbe3cd4197cc40

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/2f3f2253adfd612a507410755c64a13e437ec602...fd98c13dfc6db4b02dab48ffe9bbe3cd4197cc40
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list