Browse Source

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.
pull/134/head
Romain Vimont 4 years ago
committed by Hugo Beauzée-Luyssen
parent
commit
4bc8c7c84e
  1. 7
      include/vlc_opengl_interop.h
  2. 224
      modules/video_output/opengl/interop.c
  3. 7
      modules/video_output/opengl/interop.h
  4. 220
      modules/video_output/opengl/interop_sw.c

7
include/vlc_opengl_interop.h

@ -150,13 +150,6 @@ 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. */
int
(*init)(struct vlc_gl_interop *interop, uint32_t tex_target,
vlc_fourcc_t chroma, video_color_space_t yuv_space);
/* This avoids each module to link against GetTexFormatSize() directly. */
int
(*get_tex_format_size)(struct vlc_gl_interop *interop, uint32_t target,

224
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
@ -150,224 +148,6 @@ static int GetTexFormatSize(struct vlc_gl_interop *interop, GLenum 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,6 @@ 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;
@ -400,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 */
@ -434,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;

7
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

220
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)
{
@ -369,6 +586,9 @@ opengl_interop_generic_init(struct vlc_gl_interop *interop, bool allow_dr)
priv->has_unpack_subimage = interop->gl->api_type == VLC_OPENGL
|| vlc_gl_HasExtension(&extension_vt, "GL_EXT_unpack_subimage");
priv->has_texture_rg =
vlc_gl_HasExtension(&extension_vt, "GL_ARB_texture_rg");
video_color_space_t space;
const vlc_fourcc_t *list;

Loading…
Cancel
Save