Commit fc4114f4 authored by Thomas Guillem's avatar Thomas Guillem

gl: fix incorrect plugin dependencies

The GL/GLES2 plugins doesn't depends anymore on X11, WAYLAND, VAAPI or other
hardware libs.

Move all converters (that were built in GL plugins) in separate plugins, with a
"glconv" plugin capability. This new type of module will be loaded by GL
plugins when a video format is opaque. Otherwise, the built-in software
converter (that handle RGB,YUV,YXZ12) will be used.

Each new converters plugins depends only on hardware libs like VAAPI-X11,
VAAPI-WL. These news plugins don't depend on Open GL / GLES2. Therefore, one
glconv plugin can be used by a GL and a GLES2 plugin.

Fixes #18575
parent 144206d2
......@@ -162,6 +162,11 @@ $Id$
* gaussianblur: gaussian blur video filter
* gestures: mouse gestures control plugin
* gl: OpenGL video output using the generic OpenGL provider
* glconv_android: Android SurfaceTexture OpenGL hardware converter
* glconv_cvpx: Apple CVPX OpenGL hardware converter (for iOS and macOS)
* glconv_vaapi_drm: VA-API OpenGL hardware converter for DRM
* glconv_vaapi_wl: VA-API OpenGL hardware converter for Wayland
* glconv_vaapi_x11: VA-API OpenGL hardware converter for X11
* gles2: OpenGL ES2 video output using the generic OpenGL provider
* glspectrum: 3D OpenGL spectrum visualization
* glwin32: a opengl provider using DirectX OpenGL
......
......@@ -3,53 +3,10 @@ vout_LTLIBRARIES =
EXTRA_DIST += video_output/README
OPENGL_COMMONCFLAGS =
OPENGL_COMMONLDFLAGS =
OPENGL_COMMONLIBS =
OPENGL_COMMONSOURCES = video_output/opengl/vout_helper.c \
video_output/opengl/vout_helper.h video_output/opengl/converter.h \
video_output/opengl/converters.c
if HAVE_ANDROID
OPENGL_COMMONSOURCES += video_output/opengl/converter_android.c
endif
if HAVE_OSX
OPENGL_COMMONSOURCES += video_output/opengl/converter_cvpx.c \
codec/vt_utils.c codec/vt_utils.h
OPENGL_COMMONCFLAGS += -DVLCGL_CONV_CVPX
OPENGL_COMMONLDFLAGS += -Wl,-framework,IOSurface -Wl,-framework,CoreVideo
endif
if HAVE_IOS
OPENGL_COMMONSOURCES += video_output/opengl/converter_cvpx.c
OPENGL_COMMONCFLAGS += -DVLCGL_CONV_CVPX
endif
if HAVE_TVOS
OPENGL_COMMONSOURCES += video_output/opengl/converter_cvpx.c
OPENGL_COMMONCFLAGS += -DVLCGL_CONV_CVPX
endif
if HAVE_EGL
if HAVE_VAAPI
OPENGL_COMMONLIBS += $(LIBVA_LIBS) $(LIBVA_EGL_LIBS)
OPENGL_COMMONSOURCES += video_output/opengl/converter_vaapi.c \
hw/vaapi/vlc_vaapi.c hw/vaapi/vlc_vaapi.h
OPENGL_COMMONCFLAGS += -DVLCGL_CONV_VA
if HAVE_WAYLAND_EGL
if HAVE_VAAPI_WL
OPENGL_COMMONLIBS += $(LIBVA_WL_LIBS)
OPENGL_COMMONCFLAGS += -DHAVE_VA_WL $(LIBVA_WL_CFLAGS)
endif
endif
if HAVE_VAAPI_X11
if HAVE_XCB
OPENGL_COMMONLIBS += $(LIBVA_X11_LIBS) $(X_LIBS) $(X_PRE_LIBS) -lX11
OPENGL_COMMONCFLAGS += -DHAVE_VA_X11
endif
endif
if HAVE_VAAPI_DRM
OPENGL_COMMONLIBS += $(LIBVA_DRM_LIBS)
OPENGL_COMMONCFLAGS += -DHAVE_VA_DRM
endif
endif
endif
video_output/opengl/internal.h video_output/opengl/fragment_shaders.c \
video_output/opengl/converter_sw.c
if HAVE_DECKLINK
libdecklinkoutput_plugin_la_SOURCES = video_output/decklink.cpp
......@@ -58,27 +15,32 @@ libdecklinkoutput_plugin_la_LIBADD = $(LIBS_decklink) $(LIBDL) -lpthread
vout_LTLIBRARIES += libdecklinkoutput_plugin.la
endif
libglconv_cvpx_plugin_la_SOURCES = video_output/opengl/converter_cvpx.c \
video_output/opengl/converter.h
if HAVE_OSX
libvout_macosx_plugin_la_SOURCES = video_output/macosx.m $(OPENGL_COMMONSOURCES)
libvout_macosx_plugin_la_CFLAGS = $(AM_CFLAGS) $(OPENGL_COMMONCFLAGS)
libvout_macosx_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(voutdir)' \
-Wl,-framework,OpenGL,-framework,Cocoa $(OPENGL_COMMONLDFLAGS)
-Wl,-framework,OpenGL,-framework,Cocoa
libcaopengllayer_plugin_la_SOURCES = video_output/caopengllayer.m $(OPENGL_COMMONSOURCES)
libcaopengllayer_plugin_la_CFLAGS = $(AM_CFLAGS) $(OPENGL_COMMONCFLAGS)
libcaopengllayer_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(voutdir)' \
-Wl,-framework,OpenGL,-framework,Cocoa,-framework,QuartzCore \
$(OPENGL_COMMONLDFLAGS)
vout_LTLIBRARIES += libvout_macosx_plugin.la libcaopengllayer_plugin.la
-Wl,-framework,OpenGL,-framework,Cocoa,-framework,QuartzCore
libglconv_cvpx_plugin_la_SOURCES += codec/vt_utils.c codec/vt_utils.h
libglconv_cvpx_plugin_la_LDFLAGS = -Wl,-framework,IOSurface -Wl,-framework,CoreVideo
vout_LTLIBRARIES += libvout_macosx_plugin.la libcaopengllayer_plugin.la \
libglconv_cvpx_plugin.la
endif
if HAVE_IOS
libglconv_cvpx_plugin_la_CFLAGS = $(AM_CFLAGS) -DUSE_OPENGL_ES2
endif
libvout_ios_plugin_la_SOURCES = video_output/ios.m $(OPENGL_COMMONSOURCES)
libvout_ios_plugin_la_CFLAGS = $(AM_CFLAGS) $(OPENGL_COMMONCFLAGS)
libvout_ios_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(voutdir)' \
-Wl,-framework,OpenGLES,-framework,QuartzCore,-framework,UIKit \
$(OPENGL_COMMONLDFLAGS)
-Wl,-framework,OpenGLES,-framework,QuartzCore,-framework,UIKit
if HAVE_IOS
vout_LTLIBRARIES += libvout_ios_plugin.la
vout_LTLIBRARIES += libvout_ios_plugin.la libglconv_cvpx_plugin.la
endif
if HAVE_TVOS
vout_LTLIBRARIES += libvout_ios_plugin.la
......@@ -86,22 +48,54 @@ endif
### OpenGL ###
libgles2_plugin_la_SOURCES = $(OPENGL_COMMONSOURCES) video_output/opengl/display.c
libgles2_plugin_la_CFLAGS = $(AM_CFLAGS) $(GLES2_CFLAGS) -DUSE_OPENGL_ES2 \
$(OPENGL_COMMONCFLAGS)
libgles2_plugin_la_LIBADD = $(GLES2_LIBS) $(LIBM) $(OPENGL_COMMONLIBS)
libgles2_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(voutdir)' $(OPENGL_COMMONLDFLAGS)
libgles2_plugin_la_CFLAGS = $(AM_CFLAGS) $(GLES2_CFLAGS) -DUSE_OPENGL_ES2
libgles2_plugin_la_LIBADD = $(GLES2_LIBS) $(LIBM)
libgles2_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(voutdir)'
EXTRA_LTLIBRARIES += libgles2_plugin.la
vout_LTLIBRARIES += $(LTLIBgles2)
libgl_plugin_la_SOURCES = $(OPENGL_COMMONSOURCES) video_output/opengl/display.c
libgl_plugin_la_CFLAGS = $(AM_CFLAGS) $(GL_CFLAGS) $(OPENGL_COMMONCFLAGS)
libgl_plugin_la_LIBADD = $(GL_LIBS) $(LIBM) $(OPENGL_COMMONLIBS)
libgl_plugin_la_LDFLAGS = $(AM_LDFLAGS) $(OPENGL_COMMONLDFLAGS)
libgl_plugin_la_CFLAGS = $(AM_CFLAGS) $(GL_CFLAGS)
libgl_plugin_la_LIBADD = $(GL_LIBS) $(LIBM)
libglconv_vaapi_wl_plugin_la_SOURCES = video_output/opengl/converter_vaapi.c \
video_output/opengl/converter.h \
hw/vaapi/vlc_vaapi.c hw/vaapi/vlc_vaapi.h
libglconv_vaapi_wl_plugin_la_CFLAGS = $(AM_CFLAGS) $(GL_CFLAGS) -DHAVE_VA_WL $(LIBVA_WL_CFLAGS)
libglconv_vaapi_wl_plugin_la_LIBADD = $(LIBVA_LIBS) $(LIBVA_EGL_LIBS) \
$(LIBVA_WL_LIBS)
libglconv_vaapi_x11_plugin_la_SOURCES = $(libglconv_vaapi_wl_plugin_la_SOURCES)
libglconv_vaapi_x11_plugin_la_CFLAGS = $(AM_CFLAGS) -DHAVE_VA_X11
libglconv_vaapi_x11_plugin_la_LIBADD = $(LIBVA_LIBS) $(LIBVA_EGL_LIBS) \
$(LIBVA_X11_LIBS) $(X_LIBS) $(X_PRE_LIBS) -lX11
libglconv_vaapi_drm_plugin_la_SOURCES = $(libglconv_vaapi_wl_plugin_la_SOURCES)
libglconv_vaapi_drm_plugin_la_CFLAGS = $(AM_CFLAGS) -DHAVE_VA_DRM
libglconv_vaapi_drm_plugin_la_LIBADD = $(LIBVA_LIBS) $(LIBVA_EGL_LIBS) \
$(LIBVA_DRM_LIBS)
if HAVE_GL
vout_LTLIBRARIES += libgl_plugin.la
if HAVE_EGL
if HAVE_VAAPI
if HAVE_WAYLAND_EGL
if HAVE_VAAPI_WL
vout_LTLIBRARIES += libglconv_vaapi_wl_plugin.la
endif
endif
if HAVE_XCB
if HAVE_VAAPI_X11
vout_LTLIBRARIES += libglconv_vaapi_x11_plugin.la
endif
endif
if HAVE_VAAPI_DRM
vout_LTLIBRARIES += libglconv_vaapi_drm_plugin.la
endif
endif
endif # HAVE_EGL
endif # HAVE_GL
### XCB ###
libvlc_xcb_events_la_SOURCES = \
......@@ -318,14 +312,12 @@ libglwin32_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) \
-DMODULE_NAME_IS_glwin32
libwgl_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) \
-DMODULE_NAME_IS_wgl
libglwin32_plugin_la_CFLAGS = $(AM_CFLAGS) $(OPENGL_COMMONCFLAGS)
libwgl_plugin_la_CFLAGS = $(AM_CFLAGS) $(OPENGL_COMMONCFLAGS)
libglwin32_plugin_la_LIBADD = -lopengl32 -lgdi32 $(LIBCOM) -luuid $(OPENGL_COMMONLIBS)
libwgl_plugin_la_LIBADD = -lopengl32 -lgdi32 $(OPENGL_COMMONLIBS)
libglwin32_plugin_la_LIBADD = -lopengl32 -lgdi32 $(LIBCOM) -luuid
libwgl_plugin_la_LIBADD = -lopengl32 -lgdi32
libglwin32_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(voutdir)' $(OPENGL_COMMONLDFLAGS)
libwgl_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(voutdir)' $(OPENGL_COMMONLDFLAGS)
libglwin32_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(voutdir)'
libwgl_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(voutdir)'
if HAVE_WIN32_DESKTOP
vout_LTLIBRARIES += $(LTLIBglwin32) $(LTLIBwgl)
......@@ -389,10 +381,14 @@ libandroid_display_plugin_la_SOURCES = video_output/android/display.c \
libandroid_display_plugin_la_CFLAGS = $(AM_CFLAGS)
libandroid_display_plugin_la_LIBADD = $(LIBDL)
libglconv_android_plugin_la_SOURCES = video_output/opengl/converter_android.c \
video_output/opengl/converter.h
libglconv_android_plugin_la_CFLAGS = $(AM_CFLAGS) -DUSE_OPENGL_ES2
if HAVE_ANDROID
vout_LTLIBRARIES += libandroid_window_plugin.la libandroid_display_plugin.la
if HAVE_EGL
vout_LTLIBRARIES += libegl_android_plugin.la
vout_LTLIBRARIES += libegl_android_plugin.la libglconv_android_plugin.la
endif
endif
......
......@@ -49,6 +49,10 @@
#include <vlc_dialog.h>
#include "opengl/vout_helper.h"
#define GLHW_TEXT N_("GL/GLES hw converter")
#define GLHW_LONGTEXT N_( \
"Force an \"gl hw converter\" module.")
/**
* Forward declarations
*/
......@@ -77,6 +81,8 @@ vlc_module_begin ()
set_subcategory (SUBCAT_VIDEO_VOUT)
set_capability ("vout display", 300)
set_callbacks (Open, Close)
add_module ("glhw", NULL, NULL,
GLHW_TEXT, GLHW_LONGTEXT, true)
add_shortcut ("macosx", "vout_macosx")
vlc_module_end ()
......
......@@ -22,6 +22,7 @@
#define VLC_OPENGL_CONVERTER_H
#include "vout_helper.h"
#include <vlc_plugin.h>
#define VLCGL_PICTURE_MAX 128
......@@ -163,32 +164,29 @@ typedef struct {
PFNGLCLIENTWAITSYNCPROC ClientWaitSync; /* can be NULL */
} opengl_vtable_t;
typedef struct opengl_tex_converter_t opengl_tex_converter_t;
/*
* Callback to initialize an opengl_tex_converter_t struct
*
* The implementation should initialize every members of the struct in regards
* of the video format.
*
* \param fmt video format, fmt->i_chroma can be modified in order to match a
* shader
* \param fc OpenGL tex converter that needs to be filled on success
* \return VLC_SUCCESS or a VLC error
*/
typedef int (*opengl_tex_converter_init_cb)(opengl_tex_converter_t *fc);
/*
* Structure that is filled by an opengl_tex_converter_init_cb function
* Structure that is filled by "glhw converter" module probe function
* The implementation should initialize every members of the struct that are
* not set by the caller
*/
typedef struct opengl_tex_converter_t opengl_tex_converter_t;
struct opengl_tex_converter_t
{
/* Pointer to object gl, set by the caller of the init cb */
VLC_COMMON_MEMBERS
module_t *p_module;
/* Pointer to object gl, set by the caller */
vlc_gl_t *gl;
/* Function pointers to OpenGL functions, set by the caller */
const opengl_vtable_t *vt;
/* Function pointer to the shader init command, set by the caller, see
* opengl_fragment_shader_init() documentation. */
GLuint (*pf_fragment_shader_init)(opengl_tex_converter_t *, GLenum,
vlc_fourcc_t, video_color_space_t);
/* Available gl extensions (from GL_EXTENSIONS) */
const char *glexts;
......@@ -317,14 +315,6 @@ struct opengl_tex_converter_t
void (*pf_prepare_shader)(const opengl_tex_converter_t *fc,
const GLsizei *tex_width, const GLsizei *tex_height,
float alpha);
/*
* Callback to release the private context
*
* This function pointer can be NULL.
* \param fc OpenGL tex converter
*/
void (*pf_release)(const opengl_tex_converter_t *fc);
};
/*
......@@ -334,38 +324,20 @@ struct opengl_tex_converter_t
* generic fragment shader. It will compile a fragment shader generated from
* the chroma and the tex target. This will initialize all elements of the
* opengl_tex_converter_t struct except for priv, pf_allocate_texture,
* pf_get_pool, pf_update, and pf_release.
* pf_get_pool, pf_update
*
* \param tc OpenGL tex converter
* \param tex_target GL_TEXTURE_2D or GL_TEXTURE_RECTANGLE
* \param chroma chroma used to generate the fragment shader
* \param yuv_space if not COLOR_SPACE_UNDEF, YUV planes will be converted to
* RGB according to the color space
* \param if not COLOR_SPACE_UNDEF, YUV planes will be converted to RGB
* according to the color space
* \return the compiled fragment shader or 0 in case of error
*/
GLuint
static inline GLuint
opengl_fragment_shader_init(opengl_tex_converter_t *tc, GLenum tex_target,
vlc_fourcc_t chroma, video_color_space_t yuv_space);
int
opengl_tex_converter_subpictures_init(opengl_tex_converter_t *);
int
opengl_tex_converter_generic_init(opengl_tex_converter_t *);
#ifdef __ANDROID__
int
opengl_tex_converter_anop_init(opengl_tex_converter_t *);
#endif
#ifdef VLCGL_CONV_CVPX
int
opengl_tex_converter_cvpx_init(opengl_tex_converter_t *tc);
#endif
#ifdef VLCGL_CONV_VA
int
opengl_tex_converter_vaapi_init(opengl_tex_converter_t *tc);
#endif
vlc_fourcc_t chroma, video_color_space_t yuv_space)
{
return tc->pf_fragment_shader_init(tc, tex_target, chroma, yuv_space);
}
#endif /* include-guard */
......@@ -181,8 +181,9 @@ tc_anop_prepare_shader(const opengl_tex_converter_t *tc,
}
static void
tc_anop_release(const opengl_tex_converter_t *tc)
Close(vlc_object_t *obj)
{
opengl_tex_converter_t *tc = (void *)obj;
struct priv *priv = tc->priv;
if (priv->stex_attached)
......@@ -191,9 +192,11 @@ tc_anop_release(const opengl_tex_converter_t *tc)
free(priv);
}
int
opengl_tex_converter_anop_init(opengl_tex_converter_t *tc)
static int
Open(vlc_object_t *obj)
{
opengl_tex_converter_t *tc = (void *) obj;
if (tc->fmt.i_chroma != VLC_CODEC_ANDROID_OPAQUE
|| !tc->gl->surface->handle.anativewindow)
return VLC_EGENERIC;
......@@ -212,10 +215,9 @@ opengl_tex_converter_anop_init(opengl_tex_converter_t *tc)
tc->pf_update = tc_anop_update;
tc->pf_fetch_locations = tc_anop_fetch_locations;
tc->pf_prepare_shader = tc_anop_prepare_shader;
tc->pf_release = tc_anop_release;
tc->tex_count = 1;
tc->texs[0] = (struct opengl_tex_cfg) { { 1, 1 }, { 1, 1 } };
tc->texs[0] = (struct opengl_tex_cfg) { { 1, 1 }, { 1, 1 }, 0, 0, 0 };
tc->tex_target = GL_TEXTURE_EXTERNAL_OES;
......@@ -273,3 +275,11 @@ opengl_tex_converter_anop_init(opengl_tex_converter_t *tc)
return VLC_SUCCESS;
}
vlc_module_begin ()
set_description("Android OpenGL SurfaceTexture converter")
set_capability("glconv", 1)
set_callbacks(Open, Close)
set_category(CAT_VIDEO)
set_subcategory(SUBCAT_VIDEO_VOUT)
vlc_module_end ()
......@@ -143,8 +143,9 @@ tc_cvpx_update(const opengl_tex_converter_t *tc, GLuint *textures,
#endif
static void
tc_cvpx_release(const opengl_tex_converter_t *tc)
Close(vlc_object_t *obj)
{
opengl_tex_converter_t *tc = (void *)obj;
struct priv *priv = tc->priv;
if (priv->last_pic != NULL)
......@@ -155,9 +156,10 @@ tc_cvpx_release(const opengl_tex_converter_t *tc)
free(tc->priv);
}
int
opengl_tex_converter_cvpx_init(opengl_tex_converter_t *tc)
static int
Open(vlc_object_t *obj)
{
opengl_tex_converter_t *tc = (void *) obj;
if (tc->fmt.i_chroma != VLC_CODEC_CVPX_UYVY
&& tc->fmt.i_chroma != VLC_CODEC_CVPX_NV12
&& tc->fmt.i_chroma != VLC_CODEC_CVPX_I420
......@@ -242,8 +244,15 @@ opengl_tex_converter_cvpx_init(opengl_tex_converter_t *tc)
tc->priv = priv;
tc->pf_update = tc_cvpx_update;
tc->pf_release = tc_cvpx_release;
tc->fshader = fragment_shader;
return VLC_SUCCESS;
}
vlc_module_begin ()
set_description("Apple OpenGL CVPX converter")
set_capability("glconv", 1)
set_callbacks(Open, Close)
set_category(CAT_VIDEO)
set_subcategory(SUBCAT_VIDEO_VOUT)
vlc_module_end ()
/*****************************************************************************
* converters.c: OpenGL converters for common video formats
* converter_sw.c: OpenGL converters for software video formats
*****************************************************************************
* Copyright (C) 2016 VLC authors and VideoLAN
* Copyright (C) 2016,2017 VLC authors and VideoLAN
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
......@@ -28,27 +28,7 @@
#include <vlc_common.h>
#include <vlc_memory.h>
#include <vlc_memstream.h>
#include "converter.h"
#ifndef GL_RED
# define GL_RED 0x1903
#endif
#ifndef GL_RG
# define GL_RG 0x8227
#endif
#ifndef GL_R16
# define GL_R16 0x822A
#endif
#ifndef GL_LUMINANCE16
# define GL_LUMINANCE16 0x8042
#endif
#ifndef GL_TEXTURE_RED_SIZE
# define GL_TEXTURE_RED_SIZE 0x805C
#endif
#ifndef GL_TEXTURE_LUMINANCE_SIZE
# define GL_TEXTURE_LUMINANCE_SIZE 0x8060
#endif
#include "internal.h"
#ifndef GL_UNPACK_ROW_LENGTH
# define GL_UNPACK_ROW_LENGTH 0x0CF2
......@@ -113,493 +93,6 @@ struct priv
} persistent;
};
static int GetTexFormatSize(opengl_tex_converter_t *tc, int target,
int tex_format, int tex_internal, int tex_type)
{
GLint tex_param_size;
switch (tex_format)
{
case GL_RED:
tex_param_size = GL_TEXTURE_RED_SIZE;
break;
case GL_LUMINANCE:
tex_param_size = GL_TEXTURE_LUMINANCE_SIZE;
break;
default:
return -1;
}
GLuint texture;
tc->vt->GenTextures(1, &texture);
tc->vt->BindTexture(target, texture);
tc->vt->TexImage2D(target, 0, tex_internal, 64, 64, 0, tex_format, tex_type, NULL);
GLint size = 0;
tc->vt->GetTexLevelParameteriv(target, 0, tex_param_size, &size);
tc->vt->DeleteTextures(1, &texture);
return size;
}
static int
tc_yuv_base_init(opengl_tex_converter_t *tc, GLenum tex_target,
vlc_fourcc_t chroma, video_color_space_t yuv_space,
bool *swap_uv, const char *swizzle_per_tex[])
{
const vlc_chroma_description_t *desc = vlc_fourcc_GetChromaDescription(chroma);
if (desc == NULL)
return VLC_EGENERIC;
GLint oneplane_texfmt, oneplane16_texfmt, twoplanes_texfmt;
if (HasExtension(tc->glexts, "GL_ARB_texture_rg"))
{
oneplane_texfmt = GL_RED;
oneplane16_texfmt = GL_R16;
twoplanes_texfmt = GL_RG;
}
else
{
oneplane_texfmt = GL_LUMINANCE;
oneplane16_texfmt = GL_LUMINANCE16;
twoplanes_texfmt = GL_LUMINANCE_ALPHA;
}
float yuv_range_correction = 1.0;
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)
{
if (oneplane16_texfmt == 0
|| GetTexFormatSize(tc, tex_target, oneplane_texfmt,
oneplane16_texfmt, GL_UNSIGNED_SHORT) != 16)
return VLC_EGENERIC;
internal = oneplane16_texfmt;
type = GL_UNSIGNED_SHORT;
yuv_range_correction = (float)((1 << 16) - 1)
/ ((1 << desc->pixel_bits) - 1);
}
else
return VLC_EGENERIC;
assert(internal != 0 && type != 0);
tc->tex_count = 3;
for (unsigned i = 0; i < tc->tex_count; ++i )
{
tc->texs[i] = (struct opengl_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
};
}
if (oneplane_texfmt == GL_RED)
swizzle_per_tex[0] = swizzle_per_tex[1] = swizzle_per_tex[2] = "r";
}
else if (desc->plane_count == 2)
{
if (desc->pixel_size != 1)
return VLC_EGENERIC;
tc->tex_count = 2;
tc->texs[0] = (struct opengl_tex_cfg) {
{ 1, 1 }, { 1, 1 }, oneplane_texfmt, oneplane_texfmt, GL_UNSIGNED_BYTE
};
tc->texs[1] = (struct opengl_tex_cfg) {
{ 1, 2 }, { 1, 2 }, twoplanes_texfmt, twoplanes_texfmt, GL_UNSIGNED_BYTE
};
if (oneplane_texfmt == GL_RED)
{
swizzle_per_tex[0] = "r";
swizzle_per_tex[1] = "rg";
}
else
{
swizzle_per_tex[0] = NULL;
swizzle_per_tex[1] = "xa";
}
}
else if (desc->plane_count == 1)
{
/* Y1 U Y2 V fits in R G B A */
tc->tex_count = 1;
tc->texs[0] = (struct opengl_tex_cfg) {
{ 1, 2 }, { 1, 2 }, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE
};
/*
* Set swizzling in Y1 U V order
* R G B A
* U Y1 V Y2 => GRB
* Y1 U Y2 V => RGA
* V Y1 U Y2 => GBR
* Y1 V Y2 U => RAG
*/
switch (chroma)
{
case VLC_CODEC_UYVY:
swizzle_per_tex[0] = "grb";
break;
case VLC_CODEC_YUYV:
swizzle_per_tex[0] = "rga";
break;
case VLC_CODEC_VYUY:
swizzle_per_tex[0] = "gbr";
break;
case VLC_CODEC_YVYU:
swizzle_per_tex[0] = "rag";
break;
default:
assert(!"missing chroma");
return VLC_EGENERIC;
}
}
else
return VLC_EGENERIC;
/* [R/G/B][Y U V O] from TV range to full range
* XXX we could also do hue/brightness/constrast/gamma
* by simply changing the coefficients
*/
static const float matrix_bt601_tv2full[12] = {
1.164383561643836, 0.0000, 1.596026785714286, -0.874202217873451 ,
1.164383561643836, -0.391762290094914, -0.812967647237771, 0.531667823499146 ,
1.164383561643836, 2.017232142857142, 0.0000, -1.085630789302022 ,
};
static const float matrix_bt709_tv2full[12] = {
1.164383561643836, 0.0000, 1.792741071428571, -0.972945075016308 ,
1.164383561643836, -0.21324861427373, -0.532909328559444, 0.301482665475862 ,
1.164383561643836, 2.112401785714286, 0.0000, -1.133402217873451 ,
};
const float *matrix;
switch (yuv_space)
{
case COLOR_SPACE_BT601:
matrix = matrix_bt601_tv2full;
break;
default:
matrix = matrix_bt709_tv2full;
};
for (int i = 0; i < 4; i++) {
float correction = i < 3 ? yuv_range_correction : 1.f;
/* We place coefficient values for coefficient[4] in one array from
* matrix values. Notice that we fill values from top down instead
* of left to right.*/
for (int j = 0; j < 4; j++)
tc->yuv_coefficients[i*4+j] = j < 3 ? correction * matrix[j*4+i] : 0.f;
}
tc->yuv_color = true;
*swap_uv = chroma == VLC_CODEC_YV12 || chroma == VLC_CODEC_YV9 ||
chroma == VLC_CODEC_NV21;
return VLC_SUCCESS;
}
static int
tc_rgb_base_init(opengl_tex_converter_t *tc, GLenum tex_target,
vlc_fourcc_t chroma)
{
(void) tex_target;
if (chroma != VLC_CODEC_RGB32)
return VLC_EGENERIC;
tc->tex_count = 1;
tc->texs[0] = (struct opengl_tex_cfg) {
{ 1, 1 }, { 1, 1 }, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE
};
return VLC_SUCCESS;
}
static int
tc_base_fetch_locations(opengl_tex_converter_t *tc, GLuint program)
{
if (tc->yuv_color)
{
tc->uloc.Coefficients = tc->vt->GetUniformLocation(program,
"Coefficients");
if (tc->uloc.Coefficients == -1)
return VLC_EGENERIC;
}
for (unsigned int i = 0; i < tc->tex_count; ++i)
{
char name[sizeof("TextureX")];
snprintf(name, sizeof(name), "Texture%1u", i);
tc->uloc.Texture[i] = tc->vt->GetUniformLocation(program, name);
if (tc->uloc.Texture[i] == -1)
return VLC_EGENERIC;
if (tc->tex_target == GL_TEXTURE_RECTANGLE)
{
snprintf(name, sizeof(name), "TexSize%1u", i);
tc->uloc.TexSize[i] = tc->vt->GetUniformLocation(program, name);
if (tc->uloc.TexSize[i] == -1)
return VLC_EGENERIC;
}
}
tc->uloc.FillColor = tc->vt->GetUniformLocation(program, "FillColor");
if (tc->uloc.FillColor == -1)
return VLC_EGENERIC;
return VLC_SUCCESS;
}
static void
tc_base_prepare_shader(const opengl_tex_converter_t *tc,
const GLsizei *tex_width, const GLsizei *tex_height,
float alpha)
{
(void) tex_width; (void) tex_height;
if (tc->yuv_color)
tc->vt->Uniform4fv(tc->uloc.Coefficients, 4, tc->yuv_coefficients);