[vlc-commits] [Git][videolan/vlc][master] 8 commits: opengl: forward format to sampler

Hugo Beauzée-Luyssen (@chouquette) gitlab at videolan.org
Fri Apr 15 09:02:20 UTC 2022



Hugo Beauzée-Luyssen pushed to branch master at VideoLAN / VLC


Commits:
9a22bbd9 by Romain Vimont at 2022-04-15T08:43:55+00:00
opengl: forward format to sampler

The interop determines the format (currently based on the chroma and the
existence of the extension "GL_ARB_texture_rg").

Store this format in the vlc_gl_format, so that the sampler doesn't have
to guess by performing the same checks.

- - - - -
a4b20be0 by Romain Vimont at 2022-04-15T08:43:55+00:00
opengl: expose GetTexFormatSize() in interop

This will allow to call this function from interop modules.

This function is currently called from opengl_interop_init_impl() (the
init function pointer), which will be removed (so this narrows the scope
of helpers code exposed to modules).

In the future, more work will be needed to also remove this function
pointer.

- - - - -
c344522f by Romain Vimont at 2022-04-15T08:43:55+00:00
opengl: init textures properties from modules

All interop modules reused the util function opengl_interop_init()
(written for the software interop) to initialize the textures properties
from the chroma.

However, the actual texture format may not always be deduced from the
chroma: only the interop implementations have the full knowledge of the
texture details.

Therefore, initialize texture properties directly from each interop
implementation.

Fixes #26735
Fixes #26769

- - - - -
a22a08af by Romain Vimont at 2022-04-15T08:43:55+00:00
opengl: fix leak on error

Free the private instance on error.

- - - - -
b813327e by Romain Vimont at 2022-04-15T08:43:55+00:00
opengl: reorder initialization

This prepares further commits.

- - - - -
4bc8c7c8 by Romain Vimont at 2022-04-15T08:43:55+00:00
opengl: remove init() callback from interop

The function opengl_interop_init() is now used only by interop_sw().

Move its implementation and remove the init() callback.

- - - - -
1607231e by Romain Vimont at 2022-04-15T08:43:55+00:00
opengl: expose OpenGL version major

Extract version check to a separate static inline function.

- - - - -
d6cfada7 by Romain Vimont at 2022-04-15T08:43:55+00:00
opengl: use texture_rg when available

GL_RED and GL_RG are available since OpenGL 3.0 and OpenGL ES 3.0, or
via OpenGL extensions.

- - - - -


14 changed files:

- include/vlc_opengl_interop.h
- modules/hw/nvdec/nvdec_gl.c
- modules/video_output/opengl/gl_util.h
- modules/video_output/opengl/importer.c
- modules/video_output/opengl/interop.c
- modules/video_output/opengl/interop.h
- modules/video_output/opengl/interop_android.c
- modules/video_output/opengl/interop_cvpx.m
- modules/video_output/opengl/interop_dxva2.c
- modules/video_output/opengl/interop_sw.c
- modules/video_output/opengl/interop_vaapi.c
- modules/video_output/opengl/interop_vdpau.c
- modules/video_output/opengl/picture.h
- modules/video_output/opengl/sampler.c


Changes:

=====================================
include/vlc_opengl_interop.h
=====================================
@@ -150,12 +150,19 @@ struct vlc_gl_interop {
     void *priv;
     const struct vlc_gl_interop_ops *ops;
 
-    /* Set by the caller to opengl_interop_init_impl().
-     * This avoids each module to link against opengl_interop_init_impl()
-     * directly. */
+    /* This avoids each module to link against GetTexFormatSize() directly. */
     int
-    (*init)(struct vlc_gl_interop *interop, uint32_t tex_target,
-            vlc_fourcc_t chroma, video_color_space_t yuv_space);
+    (*get_tex_format_size)(struct vlc_gl_interop *interop, uint32_t target,
+                           uint32_t format, int32_t internal, uint32_t type);
 };
 
+static inline int
+vlc_gl_interop_GetTexFormatSize(struct vlc_gl_interop *interop, uint32_t target,
+                                uint32_t format, int32_t internal,
+                                uint32_t type)
+{
+    return interop->get_tex_format_size(interop, target, format, internal,
+                                        type);
+}
+
 #endif


=====================================
modules/hw/nvdec/nvdec_gl.c
=====================================
@@ -224,13 +224,74 @@ static int Open(vlc_object_t *obj)
         default:                         render_chroma = VLC_CODEC_NV12; break;
     }
 
-    int ret = opengl_interop_init(interop, GL_TEXTURE_2D, render_chroma, interop->fmt_in.space);
-    if (ret != VLC_SUCCESS)
+    switch (render_chroma)
     {
-        vlc_decoder_device_Release(device);
-        return ret;
+        case VLC_CODEC_P010:
+        case VLC_CODEC_P016:
+            interop->tex_count = 2;
+            interop->texs[0] = (struct vlc_gl_tex_cfg) {
+                .w = {1, 1},
+                .h = {1, 1},
+                .internal = GL_R16,
+                .format = GL_RED,
+                .type = GL_UNSIGNED_BYTE,
+            };
+            interop->texs[1] = (struct vlc_gl_tex_cfg) {
+                .w = {1, 1},
+                .h = {1, 2},
+                .internal = GL_RG16,
+                .format = GL_RG,
+                .type = GL_UNSIGNED_BYTE,
+            };
+
+            break;
+        case VLC_CODEC_I444:
+            interop->tex_count = 3;
+            interop->texs[0] = interop->texs[1] = interop->texs[2] =
+                (struct vlc_gl_tex_cfg) {
+                    .w = {1, 1},
+                    .h = {1, 1},
+                    .internal = GL_RED,
+                    .format = GL_RED,
+                    .type = GL_UNSIGNED_BYTE,
+                };
+
+            break;
+        case VLC_CODEC_I444_16L:
+            interop->tex_count = 3;
+            interop->texs[0] = interop->texs[1] = interop->texs[2] =
+                (struct vlc_gl_tex_cfg) {
+                    .w = {1, 1},
+                    .h = {1, 1},
+                    .internal = GL_R16,
+                    .format = GL_RED,
+                    .type = GL_UNSIGNED_BYTE,
+                };
+
+            break;
+        case VLC_CODEC_NV12:
+            interop->tex_count = 2;
+            interop->texs[0] = (struct vlc_gl_tex_cfg) {
+                .w = {1, 1},
+                .h = {1, 1},
+                .internal = GL_RED,
+                .format = GL_RED,
+                .type = GL_UNSIGNED_BYTE,
+            };
+            interop->texs[1] = (struct vlc_gl_tex_cfg) {
+                .w = {1, 2},
+                .h = {1, 2},
+                .internal = GL_RG,
+                .format = GL_RG,
+                .type = GL_UNSIGNED_BYTE,
+            };
+
+            break;
     }
 
+    interop->fmt_out.i_chroma = render_chroma;
+    interop->fmt_out.space = interop->fmt_in.space;
+
     static const struct vlc_gl_interop_ops ops = {
         .allocate_textures = tc_nvdec_gl_allocate_texture,
         .update_textures = tc_nvdec_gl_update,


=====================================
modules/video_output/opengl/gl_util.h
=====================================
@@ -97,14 +97,9 @@ struct vlc_gl_extension_vt {
     PFNGLGETERRORPROC       GetError;
 };
 
-static inline void
-vlc_gl_LoadExtensionFunctions(vlc_gl_t *gl, struct vlc_gl_extension_vt *vt)
+static inline unsigned
+vlc_gl_GetVersionMajor(struct vlc_gl_extension_vt *vt)
 {
-    vt->GetString = vlc_gl_GetProcAddress(gl, "glGetString");
-    vt->GetIntegerv = vlc_gl_GetProcAddress(gl, "glGetIntegerv");
-    vt->GetError = vlc_gl_GetProcAddress(gl, "glGetError");
-    vt->GetStringi = NULL;
-
     GLint version;
     vt->GetIntegerv(GL_MAJOR_VERSION, &version);
     uint32_t error = vt->GetError();
@@ -116,6 +111,20 @@ vlc_gl_LoadExtensionFunctions(vlc_gl_t *gl, struct vlc_gl_extension_vt *vt)
     while (error != GL_NO_ERROR)
         error = vt->GetError();
 
+    return version;
+}
+
+
+static inline void
+vlc_gl_LoadExtensionFunctions(vlc_gl_t *gl, struct vlc_gl_extension_vt *vt)
+{
+    vt->GetString = vlc_gl_GetProcAddress(gl, "glGetString");
+    vt->GetIntegerv = vlc_gl_GetProcAddress(gl, "glGetIntegerv");
+    vt->GetError = vlc_gl_GetProcAddress(gl, "glGetError");
+    vt->GetStringi = NULL;
+
+    unsigned version = vlc_gl_GetVersionMajor(vt);
+
     /* glGetStringi is available in OpenGL>=3 and GLES>=3.
      * https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetString.xhtml
      * https://www.khronos.org/registry/OpenGL-Refpages/es3/html/glGetString.xhtml


=====================================
modules/video_output/opengl/importer.c
=====================================
@@ -253,6 +253,8 @@ vlc_gl_importer_New(struct vlc_gl_interop *interop)
             glfmt->tex_widths[j]  = vlc_align_pot(w);
             glfmt->tex_heights[j] = vlc_align_pot(h);
         }
+
+        glfmt->formats[j] = interop->texs[j].format;
     }
 
     if (!interop->handle_texs_gen)


=====================================
modules/video_output/opengl/interop.c
=====================================
@@ -49,8 +49,6 @@ struct vlc_gl_interop_private
 #define DECLARE_SYMBOL(type, name) type name;
         OPENGL_VTABLE_F(DECLARE_SYMBOL)
     } gl;
-
-    struct vlc_gl_extension_vt extension_vt;
 };
 
 int
@@ -102,8 +100,8 @@ vlc_gl_interop_DeleteTextures(const struct vlc_gl_interop *interop,
     memset(textures, 0, interop->tex_count * sizeof(GLuint));
 }
 
-static int GetTexFormatSize(struct vlc_gl_interop *interop, int target,
-                            int tex_format, int tex_internal, int tex_type)
+static int GetTexFormatSize(struct vlc_gl_interop *interop, GLenum target,
+                            GLenum tex_format, GLint tex_internal, GLenum tex_type)
 {
     struct vlc_gl_interop_private *priv =
         container_of(interop, struct vlc_gl_interop_private, interop);
@@ -150,224 +148,6 @@ static int GetTexFormatSize(struct vlc_gl_interop *interop, int target,
     return size > 0 ? size * mul : size;
 }
 
-static inline void
-DivideRationalByTwo(vlc_rational_t *r) {
-    if (r->num % 2 == 0)
-        r->num /= 2;
-    else
-        r->den *= 2;
-}
-
-static int
-interop_yuv_base_init(struct vlc_gl_interop *interop, GLenum tex_target,
-                      vlc_fourcc_t chroma,
-                      const vlc_chroma_description_t *desc)
-{
-    struct vlc_gl_interop_private *priv =
-        container_of(interop, struct vlc_gl_interop_private, interop);
-
-    (void) chroma;
-
-    GLint oneplane_texfmt, oneplane16_texfmt,
-          twoplanes_texfmt, twoplanes16_texfmt;
-
-    if (vlc_gl_HasExtension(&priv->extension_vt, "GL_ARB_texture_rg"))
-    {
-        oneplane_texfmt = GL_RED;
-        oneplane16_texfmt = GL_R16;
-        twoplanes_texfmt = GL_RG;
-        twoplanes16_texfmt = GL_RG16;
-    }
-    else
-    {
-        oneplane_texfmt = GL_LUMINANCE;
-        oneplane16_texfmt = GL_LUMINANCE16;
-        twoplanes_texfmt = GL_LUMINANCE_ALPHA;
-        twoplanes16_texfmt = 0;
-    }
-
-    if (desc->pixel_size == 2)
-    {
-        if (GetTexFormatSize(interop, tex_target, oneplane_texfmt,
-                             oneplane16_texfmt, GL_UNSIGNED_SHORT) != 16)
-            return VLC_EGENERIC;
-    }
-
-    if (desc->plane_count == 3)
-    {
-        GLint internal = 0;
-        GLenum type = 0;
-
-        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;
-
-        assert(internal != 0 && type != 0);
-
-        interop->tex_count = 3;
-        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
-            };
-        }
-    }
-    else if (desc->plane_count == 2)
-    {
-        interop->tex_count = 2;
-
-        if (desc->pixel_size == 1)
-        {
-            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
-             || 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;
-
-        /*
-         * If plane_count == 2, then the chroma is semiplanar: the U and V
-         * planes are packed in the second plane. As a consequence, the
-         * horizontal scaling, as reported in the vlc_chroma_description_t, is
-         * doubled.
-         *
-         * But once imported as an OpenGL texture, both components are stored
-         * in a single texel (the two first components of the vec4).
-         * Therefore, from OpenGL, the width is not doubled, so the horizontal
-         * scaling must be divided by 2 to compensate.
-         */
-         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;
-}
-
-static int
-interop_rgb_base_init(struct vlc_gl_interop *interop, GLenum tex_target,
-                      vlc_fourcc_t chroma)
-{
-    (void) tex_target;
-
-    switch (chroma)
-    {
-        case VLC_CODEC_RGB24:
-            interop->texs[0] = (struct vlc_gl_tex_cfg) {
-                { 1, 1 }, { 1, 1 }, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE
-            };
-            break;
-
-        case VLC_CODEC_RGB32:
-        case VLC_CODEC_RGBA:
-            interop->texs[0] = (struct vlc_gl_tex_cfg) {
-                { 1, 1 }, { 1, 1 }, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE
-            };
-            break;
-        case VLC_CODEC_BGRA: {
-            if (GetTexFormatSize(interop, tex_target, GL_BGRA, GL_RGBA,
-                                 GL_UNSIGNED_BYTE) != 32)
-                return VLC_EGENERIC;
-            interop->texs[0] = (struct vlc_gl_tex_cfg) {
-                { 1, 1 }, { 1, 1 }, GL_RGBA, GL_BGRA, GL_UNSIGNED_BYTE
-            };
-            break;
-        }
-        default:
-            return VLC_EGENERIC;
-    }
-    interop->tex_count = 1;
-    return VLC_SUCCESS;
-}
-
-static void
-interop_xyz12_init(struct vlc_gl_interop *interop)
-{
-    interop->tex_count = 1;
-    interop->tex_target = GL_TEXTURE_2D;
-    interop->texs[0] = (struct vlc_gl_tex_cfg) {
-        { 1, 1 }, { 1, 1 }, GL_RGB, GL_RGB, GL_UNSIGNED_SHORT
-    };
-}
-
-static int
-opengl_interop_init_impl(struct vlc_gl_interop *interop, GLenum tex_target,
-                         vlc_fourcc_t chroma, video_color_space_t yuv_space)
-{
-    bool is_yuv = vlc_fourcc_IsYUV(chroma);
-    const vlc_chroma_description_t *desc =
-        vlc_fourcc_GetChromaDescription(chroma);
-    if (!desc)
-        return VLC_EGENERIC;
-
-    assert(!interop->fmt_out.p_palette);
-    interop->fmt_out.i_chroma = chroma;
-    interop->fmt_out.space = yuv_space;
-    interop->tex_target = tex_target;
-
-    if (chroma == VLC_CODEC_XYZ12)
-    {
-        interop_xyz12_init(interop);
-        return VLC_SUCCESS;
-    }
-
-    if (is_yuv)
-        return interop_yuv_base_init(interop, tex_target, chroma, desc);
-
-    return interop_rgb_base_init(interop, tex_target, chroma);
-}
-
 struct vlc_gl_interop *
 vlc_gl_interop_New(struct vlc_gl_t *gl, vlc_video_context *context,
                    const video_format_t *fmt)
@@ -378,7 +158,7 @@ vlc_gl_interop_New(struct vlc_gl_t *gl, vlc_video_context *context,
 
     struct vlc_gl_interop *interop = &priv->interop;
 
-    interop->init = opengl_interop_init_impl;
+    interop->get_tex_format_size = GetTexFormatSize;
     interop->ops = NULL;
     interop->fmt_out = interop->fmt_in = *fmt;
     interop->gl = gl;
@@ -399,8 +179,6 @@ vlc_gl_interop_New(struct vlc_gl_t *gl, vlc_video_context *context,
     OPENGL_VTABLE_F(LOAD_SYMBOL);
 #undef LOAD_SYMBOL
 
-    vlc_gl_LoadExtensionFunctions(interop->gl, &priv->extension_vt);
-
     if (desc->plane_count == 0)
     {
         /* Opaque chroma: load a module to handle it */
@@ -433,7 +211,6 @@ vlc_gl_interop_NewForSubpictures(struct vlc_gl_t *gl)
         return NULL;
 
     struct vlc_gl_interop *interop = &priv->interop;
-    interop->init = opengl_interop_init_impl;
     interop->ops = NULL;
     interop->gl = gl;
 


=====================================
modules/video_output/opengl/interop.h
=====================================
@@ -48,11 +48,4 @@ void
 vlc_gl_interop_DeleteTextures(const struct vlc_gl_interop *interop,
                               GLuint *textures);
 
-static inline int
-opengl_interop_init(struct vlc_gl_interop *interop, GLenum tex_target,
-                    vlc_fourcc_t chroma, video_color_space_t yuv_space)
-{
-    return interop->init(interop, tex_target, chroma, yuv_space);
-}
-
 #endif


=====================================
modules/video_output/opengl/interop_android.c
=====================================
@@ -240,15 +240,18 @@ Open(vlc_object_t *obj)
     };
     interop->ops = &ops;
 
-    int ret = opengl_interop_init(interop, GL_TEXTURE_EXTERNAL_OES,
-                                  VLC_CODEC_RGB32,
-                                  COLOR_SPACE_UNDEF);
-
-    if (ret != VLC_SUCCESS)
-    {
-        free(priv);
-        return VLC_EGENERIC;
-    }
+    interop->tex_target = GL_TEXTURE_EXTERNAL_OES;
+    interop->fmt_out.i_chroma = VLC_CODEC_RGB32;
+    interop->fmt_out.space = COLOR_SPACE_UNDEF;
+
+    interop->tex_count = 1;
+    interop->texs[0] = (struct vlc_gl_tex_cfg) {
+        .w = {1, 1},
+        .h = {1, 1},
+        .internal = GL_RGBA,
+        .format = GL_RGBA,
+        .type = GL_UNSIGNED_BYTE,
+    };
 
     return VLC_SUCCESS;
 }


=====================================
modules/video_output/opengl/interop_cvpx.m
=====================================
@@ -24,6 +24,7 @@
 
 #include <vlc_common.h>
 #include <vlc_plugin.h>
+#include "gl_util.h"
 #include "interop.h"
 #include "../../codec/vt_utils.h"
 
@@ -234,7 +235,18 @@ Open(vlc_object_t *obj)
     }
 #endif
 
-    int ret;
+    struct vlc_gl_extension_vt extension_vt;
+    vlc_gl_LoadExtensionFunctions(interop->gl, &extension_vt);
+
+    /* RG textures are available natively since OpenGL 3.0 and OpenGL ES 3.0 */
+    bool has_texture_rg = vlc_gl_GetVersionMajor(&extension_vt) >= 3
+        || (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"));
+
+    interop->tex_target = tex_target;
+
     switch (interop->fmt_in.i_chroma)
     {
         case VLC_CODEC_CVPX_UYVY:
@@ -244,53 +256,108 @@ Open(vlc_object_t *obj)
              * and red color channels, respectively. cf. APPLE_rgb_422 khronos
              * extension. */
 
-            ret = opengl_interop_init(interop, tex_target, VLC_CODEC_VYUY,
-                                      interop->fmt_in.space);
-            if (ret != VLC_SUCCESS)
-                goto error;
+            interop->fmt_out.i_chroma = VLC_CODEC_VYUY;
+            interop->fmt_out.space = interop->fmt_in.space;
+
+            interop->tex_count = 1;
+            interop->texs[0] = (struct vlc_gl_tex_cfg) {
+                .w = {1, 1},
+                .h = {1, 1},
+                .internal = GL_RGB,
+                .format = GL_RGB_422_APPLE,
+                .type = GL_UNSIGNED_SHORT_8_8_APPLE,
+            };
 
-            interop->texs[0].internal = GL_RGB;
-            interop->texs[0].format = GL_RGB_422_APPLE;
-            interop->texs[0].type = GL_UNSIGNED_SHORT_8_8_APPLE;
-            interop->texs[0].w = interop->texs[0].h = (vlc_rational_t) { 1, 1 };
             break;
         case VLC_CODEC_CVPX_NV12:
         {
-            ret = opengl_interop_init(interop, tex_target, VLC_CODEC_NV12,
-                                      interop->fmt_in.space);
-            if (ret != VLC_SUCCESS)
-                goto error;
+            interop->fmt_out.i_chroma = VLC_CODEC_NV12;
+            interop->fmt_out.space = interop->fmt_in.space;
+
+            interop->tex_count = 2;
+            interop->texs[0] = (struct vlc_gl_tex_cfg) {
+                .w = {1, 1},
+                .h = {1, 1},
+                .internal = has_texture_rg ? GL_RED : GL_LUMINANCE,
+                .format = has_texture_rg ? GL_RED : GL_LUMINANCE,
+                .type = GL_UNSIGNED_BYTE,
+            };
+            interop->texs[1] = (struct vlc_gl_tex_cfg) {
+                .w = {1, 2},
+                .h = {1, 2},
+                .internal = has_texture_rg ? GL_RG : GL_LUMINANCE_ALPHA,
+                .format = has_texture_rg ? GL_RG : GL_LUMINANCE_ALPHA,
+                .type = GL_UNSIGNED_BYTE,
+            };
+
             break;
         }
         case VLC_CODEC_CVPX_P010:
         {
-            ret = opengl_interop_init(interop, tex_target, VLC_CODEC_P010,
-                                      interop->fmt_in.space);
-            if (ret != VLC_SUCCESS)
+            if (!has_texture_rg
+             || vlc_gl_interop_GetTexFormatSize(interop, tex_target, GL_RG,
+                                                GL_RG16, GL_UNSIGNED_SHORT) != 16)
                 goto error;
 
+            interop->fmt_out.i_chroma = VLC_CODEC_P010;
+            interop->fmt_out.space = interop->fmt_in.space;
+
+            interop->tex_count = 2;
+            interop->texs[0] = (struct vlc_gl_tex_cfg) {
+                .w = {1, 1},
+                .h = {1, 1},
+                .internal = GL_R16,
+                .format = GL_RED,
+                .type = GL_UNSIGNED_BYTE,
+            };
+            interop->texs[1] = (struct vlc_gl_tex_cfg) {
+                .w = {1, 1},
+                .h = {1, 2},
+                .internal = GL_RG16,
+                .format = GL_RG,
+                .type = GL_UNSIGNED_BYTE,
+            };
+
             break;
         }
         case VLC_CODEC_CVPX_I420:
-            ret = opengl_interop_init(interop, tex_target, VLC_CODEC_I420,
-                                      interop->fmt_in.space);
-            if (ret != VLC_SUCCESS)
-                goto error;
+            interop->fmt_out.i_chroma = VLC_CODEC_I420;
+            interop->fmt_out.space = interop->fmt_in.space;
+
+            interop->tex_count = 3;
+            interop->texs[0] = (struct vlc_gl_tex_cfg) {
+                .w = {1, 1},
+                .h = {1, 1},
+                .internal = has_texture_rg ? GL_RED : GL_LUMINANCE,
+                .format = has_texture_rg ? GL_RED : GL_LUMINANCE,
+                .type = GL_UNSIGNED_BYTE,
+            };
+            interop->texs[1] = interop->texs[2] = (struct vlc_gl_tex_cfg) {
+                .w = {1, 2},
+                .h = {1, 2},
+                .internal = has_texture_rg ? GL_RED : GL_LUMINANCE,
+                .format = has_texture_rg ? GL_RED : GL_LUMINANCE,
+                .type = GL_UNSIGNED_BYTE,
+            };
 
             break;
         case VLC_CODEC_CVPX_BGRA:
-            ret = opengl_interop_init(interop, tex_target, VLC_CODEC_RGB32,
-                                      COLOR_SPACE_UNDEF);
-            if (ret != VLC_SUCCESS)
-                goto error;
-
-            interop->texs[0].internal = GL_RGBA;
-            interop->texs[0].format = GL_BGRA;
+            interop->fmt_out.i_chroma = VLC_CODEC_RGB32;
+            interop->fmt_out.space = COLOR_SPACE_UNDEF;
+
+            interop->tex_count = 1;
+            interop->texs[0] = (struct vlc_gl_tex_cfg) {
+                .w = {1, 1},
+                .h = {1, 1},
+                .internal = GL_RGBA,
+                .format = GL_BGRA,
 #if TARGET_OS_IPHONE
-            interop->texs[0].type = GL_UNSIGNED_BYTE;
+                .type = GL_UNSIGNED_BYTE,
 #else
-            interop->texs[0].type = GL_UNSIGNED_INT_8_8_8_8_REV;
+                .type = GL_UNSIGNED_INT_8_8_8_8_REV,
 #endif
+            };
+
             break;
         default:
             vlc_assert_unreachable();


=====================================
modules/video_output/opengl/interop_dxva2.c
=====================================
@@ -530,10 +530,18 @@ GLConvOpen(vlc_object_t *obj)
     /* The pictures are uploaded upside-down */
     video_format_TransformBy(&interop->fmt_out, TRANSFORM_VFLIP);
 
-    int ret = opengl_interop_init(interop, GL_TEXTURE_2D, VLC_CODEC_RGB32,
-                                  COLOR_SPACE_UNDEF);
-    if (ret != VLC_SUCCESS)
-        goto error;
+    interop->tex_target = GL_TEXTURE_2D;
+    interop->fmt_out.i_chroma = VLC_CODEC_RGB32;
+    interop->fmt_out.space = COLOR_SPACE_UNDEF;
+
+    interop->tex_count = 1;
+    interop->texs[0] = (struct vlc_gl_tex_cfg) {
+        .w = {1, 1},
+        .h = {1, 1},
+        .internal = GL_RGBA,
+        .format = GL_RGBA,
+        .type = GL_UNSIGNED_BYTE,
+    };
 
     return VLC_SUCCESS;
 


=====================================
modules/video_output/opengl/interop_sw.c
=====================================
@@ -41,6 +41,7 @@ typedef struct
 
 struct priv
 {
+    bool   has_texture_rg;
     bool   has_unpack_subimage;
     void * texture_temp_buf;
     size_t texture_temp_buf_size;
@@ -336,6 +337,222 @@ tc_common_update(const struct vlc_gl_interop *interop, uint32_t textures[],
     return ret;
 }
 
+static inline void
+DivideRationalByTwo(vlc_rational_t *r) {
+    if (r->num % 2 == 0)
+        r->num /= 2;
+    else
+        r->den *= 2;
+}
+
+static int
+interop_yuv_base_init(struct vlc_gl_interop *interop, GLenum tex_target,
+                      vlc_fourcc_t chroma, const vlc_chroma_description_t *desc)
+{
+    struct priv *priv = interop->priv;
+
+    (void) chroma;
+
+    GLint oneplane_texfmt, oneplane16_texfmt,
+          twoplanes_texfmt, twoplanes16_texfmt;
+
+    if (priv->has_texture_rg)
+    {
+        oneplane_texfmt = GL_RED;
+        oneplane16_texfmt = GL_R16;
+        twoplanes_texfmt = GL_RG;
+        twoplanes16_texfmt = GL_RG16;
+    }
+    else
+    {
+        oneplane_texfmt = GL_LUMINANCE;
+        oneplane16_texfmt = GL_LUMINANCE16;
+        twoplanes_texfmt = GL_LUMINANCE_ALPHA;
+        twoplanes16_texfmt = 0;
+    }
+
+    if (desc->pixel_size == 2)
+    {
+        if (vlc_gl_interop_GetTexFormatSize(interop, tex_target, oneplane_texfmt,
+                                            oneplane16_texfmt, GL_UNSIGNED_SHORT) != 16)
+            return VLC_EGENERIC;
+    }
+
+    if (desc->plane_count == 3)
+    {
+        GLint internal = 0;
+        GLenum type = 0;
+
+        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;
+
+        assert(internal != 0 && type != 0);
+
+        interop->tex_count = 3;
+        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
+            };
+        }
+    }
+    else if (desc->plane_count == 2)
+    {
+        interop->tex_count = 2;
+
+        if (desc->pixel_size == 1)
+        {
+            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;
+
+        /*
+         * If plane_count == 2, then the chroma is semiplanar: the U and V
+         * planes are packed in the second plane. As a consequence, the
+         * horizontal scaling, as reported in the vlc_chroma_description_t, is
+         * doubled.
+         *
+         * But once imported as an OpenGL texture, both components are stored
+         * in a single texel (the two first components of the vec4).
+         * Therefore, from OpenGL, the width is not doubled, so the horizontal
+         * scaling must be divided by 2 to compensate.
+         */
+         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;
+}
+
+static int
+interop_rgb_base_init(struct vlc_gl_interop *interop, GLenum tex_target,
+                      vlc_fourcc_t chroma)
+{
+    (void) tex_target;
+
+    switch (chroma)
+    {
+        case VLC_CODEC_RGB24:
+            interop->texs[0] = (struct vlc_gl_tex_cfg) {
+                { 1, 1 }, { 1, 1 }, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE
+            };
+            break;
+
+        case VLC_CODEC_RGB32:
+        case VLC_CODEC_RGBA:
+            interop->texs[0] = (struct vlc_gl_tex_cfg) {
+                { 1, 1 }, { 1, 1 }, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE
+            };
+            break;
+        case VLC_CODEC_BGRA: {
+            if (vlc_gl_interop_GetTexFormatSize(interop, tex_target, GL_BGRA, GL_RGBA,
+                                                GL_UNSIGNED_BYTE) != 32)
+                return VLC_EGENERIC;
+            interop->texs[0] = (struct vlc_gl_tex_cfg) {
+                { 1, 1 }, { 1, 1 }, GL_RGBA, GL_BGRA, GL_UNSIGNED_BYTE
+            };
+            break;
+        }
+        default:
+            return VLC_EGENERIC;
+    }
+    interop->tex_count = 1;
+    return VLC_SUCCESS;
+}
+
+static void
+interop_xyz12_init(struct vlc_gl_interop *interop)
+{
+    interop->tex_count = 1;
+    interop->tex_target = GL_TEXTURE_2D;
+    interop->texs[0] = (struct vlc_gl_tex_cfg) {
+        { 1, 1 }, { 1, 1 }, GL_RGB, GL_RGB, GL_UNSIGNED_SHORT
+    };
+}
+
+static int
+opengl_interop_init(struct vlc_gl_interop *interop, GLenum tex_target,
+                    vlc_fourcc_t chroma, video_color_space_t yuv_space)
+{
+    bool is_yuv = vlc_fourcc_IsYUV(chroma);
+    const vlc_chroma_description_t *desc =
+        vlc_fourcc_GetChromaDescription(chroma);
+    if (!desc)
+        return VLC_EGENERIC;
+
+    assert(!interop->fmt_out.p_palette);
+    interop->fmt_out.i_chroma = chroma;
+    interop->fmt_out.space = yuv_space;
+    interop->tex_target = tex_target;
+
+    if (chroma == VLC_CODEC_XYZ12)
+    {
+        interop_xyz12_init(interop);
+        return VLC_SUCCESS;
+    }
+
+    if (is_yuv)
+        return interop_yuv_base_init(interop, tex_target, chroma, desc);
+
+    return interop_rgb_base_init(interop, tex_target, chroma);
+}
+
 void
 opengl_interop_generic_deinit(struct vlc_gl_interop *interop)
 {
@@ -354,12 +571,28 @@ opengl_interop_generic_init(struct vlc_gl_interop *interop, bool allow_dr)
     if (unlikely(priv == NULL))
         return VLC_ENOMEM;
 
+    interop->priv = priv;
+
 #define LOAD_SYMBOL(type, name) \
     priv->gl.name = vlc_gl_GetProcAddress(interop->gl, "gl" # name); \
     assert(priv->gl.name != NULL);
 
     OPENGL_VTABLE_F(LOAD_SYMBOL);
 
+    struct vlc_gl_extension_vt extension_vt;
+    vlc_gl_LoadExtensionFunctions(interop->gl, &extension_vt);
+
+    /* OpenGL or OpenGL ES2 with GL_EXT_unpack_subimage ext */
+    priv->has_unpack_subimage = interop->gl->api_type == VLC_OPENGL
+        || 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
+            && 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"));
+
     video_color_space_t space;
     const vlc_fourcc_t *list;
 
@@ -368,7 +601,7 @@ opengl_interop_generic_init(struct vlc_gl_interop *interop, bool allow_dr)
         GLint max_texture_units = 0;
         priv->gl.GetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_texture_units);
         if (max_texture_units < 3)
-            return VLC_EGENERIC;
+            goto error;
 
         list = vlc_fourcc_GetYUVFallback(interop->fmt_in.i_chroma);
         space = interop->fmt_in.space;
@@ -406,7 +639,7 @@ opengl_interop_generic_init(struct vlc_gl_interop *interop, bool allow_dr)
         list++;
     }
 
-    return VLC_EGENERIC;
+    goto error;
 
 interop_init:
     /* We found a chroma with matching parameters for OpenGL. The interop can
@@ -432,17 +665,9 @@ interop_init:
         .update_textures = tc_common_update,
         .close = opengl_interop_generic_deinit,
     };
-    interop->priv = priv;
     interop->ops = &ops;
     interop->fmt_in.i_chroma = i_chroma;
 
-    struct vlc_gl_extension_vt extension_vt;
-    vlc_gl_LoadExtensionFunctions(interop->gl, &extension_vt);
-
-    /* OpenGL or OpenGL ES2 with GL_EXT_unpack_subimage ext */
-    priv->has_unpack_subimage = interop->gl->api_type == VLC_OPENGL
-        || vlc_gl_HasExtension(&extension_vt, "GL_EXT_unpack_subimage");
-
     if (allow_dr && priv->has_unpack_subimage)
     {
         /* Ensure we do direct rendering / PBO with OpenGL 3.0 or higher. */
@@ -468,4 +693,9 @@ interop_init:
     }
 
     return VLC_SUCCESS;
+
+error:
+    free(priv);
+    interop->priv = NULL;
+    return VLC_EGENERIC;
 }


=====================================
modules/video_output/opengl/interop_vaapi.c
=====================================
@@ -464,10 +464,48 @@ Open(vlc_object_t *obj)
         case VLC_CODEC_VAAPI_420:
             va_fourcc = VA_FOURCC_NV12;
             vlc_sw_chroma = VLC_CODEC_NV12;
+
+            interop->tex_count = 2;
+            interop->texs[0] = (struct vlc_gl_tex_cfg) {
+                .w = {1, 1},
+                .h = {1, 1},
+                .internal = GL_RED,
+                .format = GL_RED,
+                .type = GL_UNSIGNED_BYTE,
+            };
+            interop->texs[1] = (struct vlc_gl_tex_cfg) {
+                .w = {1, 2},
+                .h = {1, 2},
+                .internal = GL_RG,
+                .format = GL_RG,
+                .type = GL_UNSIGNED_BYTE,
+            };
+
             break;
         case VLC_CODEC_VAAPI_420_10BPP:
             va_fourcc = VA_FOURCC_P010;
             vlc_sw_chroma = VLC_CODEC_P010;
+
+            if (vlc_gl_interop_GetTexFormatSize(interop, GL_TEXTURE_2D, GL_RG,
+                                                GL_RG16, GL_UNSIGNED_SHORT) != 16)
+                goto error;
+
+            interop->tex_count = 2;
+            interop->texs[0] = (struct vlc_gl_tex_cfg) {
+                .w = {1, 1},
+                .h = {1, 1},
+                .internal = GL_R16,
+                .format = GL_RED,
+                .type = GL_UNSIGNED_BYTE,
+            };
+            interop->texs[1] = (struct vlc_gl_tex_cfg) {
+                .w = {1, 1},
+                .h = {1, 2},
+                .internal = GL_RG16,
+                .format = GL_RG,
+                .type = GL_UNSIGNED_BYTE,
+            };
+
             break;
         default:
             vlc_assert_unreachable();
@@ -525,10 +563,9 @@ Open(vlc_object_t *obj)
     /* The pictures are uploaded upside-down */
     video_format_TransformBy(&interop->fmt_out, TRANSFORM_VFLIP);
 
-    int ret = opengl_interop_init(interop, GL_TEXTURE_2D, vlc_sw_chroma,
-                                  interop->fmt_in.space);
-    if (ret != VLC_SUCCESS)
-        goto error;
+    interop->tex_target = GL_TEXTURE_2D;
+    interop->fmt_out.i_chroma = vlc_sw_chroma;
+    interop->fmt_out.space = interop->fmt_in.space;
 
     static const struct vlc_gl_interop_ops ops = {
         .update_textures = tc_vaegl_update,


=====================================
modules/video_output/opengl/interop_vdpau.c
=====================================
@@ -191,13 +191,18 @@ Open(vlc_object_t *obj)
     /* The pictures are uploaded upside-down */
     video_format_TransformBy(&interop->fmt_out, TRANSFORM_VFLIP);
 
-    int ret = opengl_interop_init(interop, GL_TEXTURE_2D, VLC_CODEC_RGB32,
-                                  COLOR_SPACE_UNDEF);
-    if (ret != VLC_SUCCESS)
-    {
-        Close(interop);
-        return VLC_EGENERIC;
-    }
+    interop->tex_target = GL_TEXTURE_2D;
+    interop->fmt_out.i_chroma = VLC_CODEC_RGB32;
+    interop->fmt_out.space = COLOR_SPACE_UNDEF;
+
+    interop->tex_count = 1;
+    interop->texs[0] = (struct vlc_gl_tex_cfg) {
+        .w = {1, 1},
+        .h = {1, 1},
+        .internal = GL_RGBA,
+        .format = GL_RGBA,
+        .type = GL_UNSIGNED_BYTE,
+    };
 
     static const struct vlc_gl_interop_ops ops = {
         .update_textures = tc_vdpau_gl_update,


=====================================
modules/video_output/opengl/picture.h
=====================================
@@ -43,6 +43,8 @@ struct vlc_gl_format {
 
     GLsizei visible_widths[PICTURE_PLANE_MAX];
     GLsizei visible_heights[PICTURE_PLANE_MAX];
+
+    uint32_t formats[PICTURE_PLANE_MAX];
 };
 
 /**


=====================================
modules/video_output/opengl/sampler.c
=====================================
@@ -423,20 +423,12 @@ opengl_init_swizzle(struct vlc_gl_sampler *sampler,
                     vlc_fourcc_t chroma,
                     const vlc_chroma_description_t *desc)
 {
-    struct vlc_gl_sampler_priv *priv = PRIV(sampler);
-
-    GLint oneplane_texfmt;
-    if (vlc_gl_HasExtension(&priv->extension_vt, "GL_ARB_texture_rg"))
-        oneplane_texfmt = GL_RED;
-    else
-        oneplane_texfmt = GL_LUMINANCE;
-
     if (desc->plane_count == 3)
         swizzle_per_tex[0] = swizzle_per_tex[1] = swizzle_per_tex[2] = "r";
     else if (desc->plane_count == 2)
     {
         swizzle_per_tex[0] = "r";
-        if (oneplane_texfmt == GL_RED)
+        if (sampler->glfmt.formats[1] == GL_RG)
             swizzle_per_tex[1] = "rg";
         else
             swizzle_per_tex[1] = "ra";



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/93626af8239e99a2d513ff1c5a26130783494b21...d6cfada7d417869832d44750e921cca59f74cb7b

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/93626af8239e99a2d513ff1c5a26130783494b21...d6cfada7d417869832d44750e921cca59f74cb7b
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