1
mirror of https://code.videolan.org/videolan/vlc synced 2024-09-04 09:11:33 +02:00
vlc/modules/video_output/vgl.c
2022-05-25 13:15:40 +00:00

193 lines
6.0 KiB
C

/*****************************************************************************
* vgl.c: virtual LibVLC OpenGL extension
*****************************************************************************
* Copyright (c) 2018 VLC authors and VideoLAN
*
* Authors: Pierre Lamot <pierre@videolabs.io>
*
* 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
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_vout_display.h>
#include <vlc_opengl.h>
#include <vlc/libvlc.h>
#include <vlc/libvlc_picture.h>
#include <vlc/libvlc_media.h>
#include <vlc/libvlc_renderer_discoverer.h>
#include <vlc/libvlc_media_player.h>
#ifndef GL_RGBA
#define GL_RGBA 0x1908
#endif
typedef struct vout_display_sys_t
{
libvlc_video_output_cleanup_cb cleanupCb;
libvlc_video_output_setup_cb setupCb;
libvlc_video_update_output_cb resizeCb;
libvlc_video_swap_cb swapCb;
libvlc_video_makeCurrent_cb makeCurrentCb;
libvlc_video_getProcAddress_cb getProcAddressCb;
void* opaque;
unsigned width;
unsigned height;
} vout_display_sys_t;
static void *OurGetProcAddress(vlc_gl_t *gl, const char *name)
{
vout_display_sys_t *sys = gl->sys;
return sys->getProcAddressCb(sys->opaque, name);
}
static int MakeCurrent(vlc_gl_t *gl)
{
vout_display_sys_t *sys = gl->sys;
bool success = sys->makeCurrentCb(sys->opaque, true);
return success ? VLC_SUCCESS : VLC_EGENERIC;
}
static void ReleaseCurrent(vlc_gl_t *gl)
{
vout_display_sys_t *sys = gl->sys;
sys->makeCurrentCb(sys->opaque, false);
}
static void VglSwapBuffers(vlc_gl_t *gl)
{
vout_display_sys_t *sys = gl->sys;
MakeCurrent(gl);
sys->swapCb(sys->opaque);
ReleaseCurrent(gl);
}
static void Resize(vlc_gl_t * gl, unsigned w, unsigned h)
{
vout_display_sys_t *sys = gl->sys;
if( sys->width == w && sys->height == h )
return;
MakeCurrent(gl);
libvlc_video_render_cfg_t output_cfg = {
w, h, 8, true,
libvlc_video_colorspace_BT709, libvlc_video_primaries_BT709,
libvlc_video_transfer_func_SRGB, NULL,
};
libvlc_video_output_cfg_t render_cfg;
sys->resizeCb(sys->opaque, &output_cfg, &render_cfg);
ReleaseCurrent(gl);
assert(render_cfg.opengl_format == GL_RGBA);
assert(render_cfg.full_range == true);
assert(render_cfg.colorspace == libvlc_video_colorspace_BT709);
assert(render_cfg.primaries == libvlc_video_primaries_BT709);
assert(render_cfg.transfer == libvlc_video_transfer_func_SRGB);
assert(render_cfg.orientation == libvlc_video_orient_top_left);
sys->width = w;
sys->height = h;
}
static void Close(vlc_gl_t *gl)
{
vout_display_sys_t *sys = gl->sys;
if( sys->cleanupCb )
sys->cleanupCb(sys->opaque);
}
#define SET_CALLBACK_ADDR(var, varname) \
do { \
var = var_InheritAddress(gl, varname); \
if( !var ) { \
msg_Err( gl, "%s address is missing", varname ); \
return VLC_EGENERIC; \
} \
} while( 0 )
static int Open(vlc_gl_t *gl, unsigned width, unsigned height)
{
vout_display_sys_t * sys;
libvlc_video_engine_t engineType = var_InheritInteger( gl, "vout-cb-type" );
if ( engineType != libvlc_video_engine_opengl &&
engineType != libvlc_video_engine_gles2 )
return VLC_ENOTSUP;
/* Allocate structure */
gl->sys = sys = vlc_obj_calloc(VLC_OBJECT(gl), 1, sizeof(*sys));
if( !sys )
return VLC_ENOMEM;
sys->opaque = var_InheritAddress(gl, "vout-cb-opaque");
sys->setupCb = var_InheritAddress(gl, "vout-cb-setup");
sys->cleanupCb = var_InheritAddress(gl, "vout-cb-cleanup");
SET_CALLBACK_ADDR(sys->resizeCb, "vout-cb-update-output");
SET_CALLBACK_ADDR(sys->swapCb, "vout-cb-swap");
SET_CALLBACK_ADDR(sys->makeCurrentCb, "vout-cb-make-current");
SET_CALLBACK_ADDR(sys->getProcAddressCb, "vout-cb-get-proc-address");
if( sys->setupCb )
{
libvlc_video_setup_device_cfg_t setup_cfg = {};
libvlc_video_setup_device_info_t configured_cfg;
if( !sys->setupCb(&sys->opaque, &setup_cfg, &configured_cfg) )
{
msg_Err( gl, "user setup failed" );
return VLC_EGENERIC;
}
}
Resize(gl, width, height);
static const struct vlc_gl_operations gl_ops =
{
.make_current = MakeCurrent,
.release_current = ReleaseCurrent,
.resize = Resize,
.swap = VglSwapBuffers,
.get_proc_address = OurGetProcAddress,
.close = Close,
};
gl->ops = &gl_ops;
return VLC_SUCCESS;
}
#undef SET_CALLBACK_ADDR
/*****************************************************************************
* Module descriptor
*****************************************************************************/
vlc_module_begin()
set_shortname("GL texture")
set_description("GL texture output")
set_subcategory(SUBCAT_VIDEO_VOUT)
set_capability("opengl", 0)
set_callback(Open)
add_shortcut("vglmem")
add_submodule()
set_capability("opengl es2", 0)
set_callback(Open)
add_shortcut("vglmem")
vlc_module_end()