Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • videolan/vlc
  • chouquette/vlc
  • bakiewicz.marek122/vlc
  • devnexen/vlc
  • rohanrajpal/vlc
  • blurrrb/vlc
  • gsoc/gsoc2019/darkapex/vlc
  • b1ue/vlc
  • fkuehne/vlc
  • magsoft/vlc
  • chub/vlc
  • cramiro9/vlc
  • robUx4/vlc
  • rom1v/vlc
  • akshayaky/vlc
  • tmk907/vlc
  • akymaster/vlc
  • govind.sharma/vlc
  • psilokos/vlc
  • xjbeta/vlc
  • jahan/vlc
  • 1480c1/vlc
  • amanchande/vlc
  • aaqib/vlc
  • rist/vlc
  • apol/vlc
  • mindfreeze/vlc
  • alexandre-janniaux/vlc
  • sandsmark/vlc
  • jagannatharjun/vlc
  • gsoc/gsoc2020/matiaslgonzalez/vlc
  • gsoc/gsoc2020/jagannatharjun/vlc
  • mstorsjo/vlc
  • gsoc/gsoc2020/vedenta/vlc
  • gsoc/gsoc2020/arnav-ishaan/vlc
  • gsoc/gsoc2020/andreduong/vlc
  • fuzun/vlc
  • gsoc/gsoc2020/vatsin/vlc
  • gsoc/gsoc2020/sagid/vlc
  • yaron/vlc
  • Phoenix/vlc
  • Garf/vlc
  • ePiratWorkarounds/vlc
  • tguillem/vlc
  • jnqnfe/vlc
  • mdc/vlc
  • Vedaa/vlc
  • rasa/vlc
  • quink/vlc
  • yealo/vlc
  • aleksey_ak/vlc
  • ePirat/vlc
  • ilya.yanok/vlc
  • asenat/vlc
  • m/vlc
  • bunjee/vlc
  • BLumia/vlc
  • sagudev/vlc
  • hamedmonji30/vlc
  • nullgemm/vlc
  • DivyamAhuja/vlc
  • thesamesam/vlc
  • dag7/vlc
  • snehil101/vlc
  • haasn/vlc
  • jbk/vlc
  • ValZapod/vlc
  • mfkl/vlc
  • WangChuan/vlc
  • core1024/vlc
  • GhostVaibhav/vlc
  • dfuhrmann/vlc
  • davide.prade/vlc
  • tmatth/vlc
  • Courmisch/vlc
  • zouya/vlc
  • hpi/vlc
  • EwoutH/vlc
  • aleung27/vlc
  • hengwu0/vlc
  • saladin/vlc
  • ashuio/vlc
  • richselwood/vlc
  • verma16Ayush/vlc
  • chemicalflash/vlc
  • PoignardAzur/vlc
  • huangjieNT/vlc
  • Blake-Haydon/vlc
  • AnuthaDev/vlc
  • gsoc/gsoc2021/mpd/vlc
  • nicolas_lequec/vlc
  • sambassaly/vlc
  • thresh/vlc
  • bonniegong/vlc
  • myaashish/vlc
  • stavros.vagionitis/vlc
  • ileoo/vlc
  • louis-santucci/vlc
  • cchristiansen/vlc
  • sabyasachi07/vlc
  • AbduAmeen/vlc
  • ashishb0410/vlc
  • urbanhusky/vlc
  • davidepietrasanta/vlc
  • riksleutelstad/vlc
  • jeremyVignelles/vlc
  • komh/vlc
  • iamjithinjohn/vlc
  • JohannesKauffmann/vlc2
  • kunglao/vlc
  • natzberg/vlc
  • jill/vlc
  • cwendling/vlc
  • adufou/vlc
  • ErwanAirone/vlc
  • HasinduDilshan10/vlc
  • vagrantc/vlc
  • rafiv/macos-bigsur-icon
  • Aymeriic/vlc
  • saranshg20/vlc
  • metzlove24/vlc
  • linkfanel/vlc
  • Ds886/vlc
  • metehan-arslan/vlc
  • Skantes/vlc
  • kgsandundananjaya96/vlc
  • mitchcapper/vlc
  • advaitgupta/vlc
  • StefanBruens/vlc
  • ratajs/vlc
  • T.M.F.B.3761/vlc
  • m222059/vlc
  • casemerrick/vlc
  • joshuaword2alt/vlc
  • sjwaddy/vlc
  • dima/vlc
  • Ybalrid/vlc
  • umxprime/vlc
  • eschmidt/vlc
  • vannieuwenhuysenmichelle/vlc
  • badcf00d/vlc
  • wesinator/vlc
  • louis/vlc
  • xqq/vlc
  • EmperorYP7/vlc
  • NicoLiam/vlc
  • loveleen/vlc
  • rofferom/vlc
  • rbultje/vlc
  • TheUnamed/vlc
  • pratiksharma341/vlc
  • Saurab17/vlc
  • purist.coder/vlc
  • Shuicheng/vlc
  • mdrrubel292/vlc
  • silverbleu00/vlc
  • metif12/vlc
  • asher-m/vlc
  • jeffk/vlc
  • Brandonbr1/vlc
  • beautyyuyanli/vlc
  • rego21/vlc
  • muyangren907/vlc
  • collectionbylawrencejason/vlc
  • evelez/vlc
  • GSMgeeth/vlc
  • Oneric/vlc
  • TJ5/vlc
  • XuanTung95/vlc
  • darrenjenny21/vlc
  • Trenly/vlc
  • RockyTDR/vlc
  • mjakubowski/vlc
  • caprica/vlc
  • ForteFrankie/vlc
  • seannamiller19/vlc
  • junlon2006/vlc
  • kiwiren6666/vlc
  • iuseiphonexs/vlc
  • fenngtun/vlc
  • Rajdutt999/vlc
  • typx/vlc
  • leon.vitanos/vlc
  • robertogarci0938/vlc
  • gsoc/gsoc2022/luc65r/vlc-mpd
  • skeller/vlc
  • MCJack123/vlc
  • luc65r/vlc-mpd
  • popov895/vlc
  • claucambra/vlc
  • brad/vlc
  • matthewmurua88/vlc
  • Tomas8874/vlc
  • philenotfound/vlc
  • makita-do3/vlc
  • LZXCorp/vlc
  • mar0x/vlc
  • senojetkennedy0102/vlc
  • shaneb243/vlc
  • ahmadbader/vlc
  • rajduttcse26/vlc-audio-filters
  • Juniorzito8415/vlc
  • achernyakov/vlc
  • lucasjetgroup/vlc
  • pupdoggy666/vlc
  • gmde9363/vlc
  • alexnwayne/vlc
  • bahareebrahimi781/vlc
  • hamad633666/vlc
  • umghof3112/vlc
  • joe0199771874/vlc
  • Octocats66666666/vlc
  • jjm_223/vlc
  • btech10110.19/vlc
  • sunnykfc028/vlc-audio-filters
  • loic/vlc
  • nguyenminhducmx1/vlc
  • JanekKrueger/vlc
  • bstubbington2/vlc
  • rcombs/vlc
  • Ordissimo/vlc
  • king7532/vlc
  • noobsauce101/vlc
  • schong0525/vlc
  • myQwil/vlc
  • apisbg91/vlc
  • geeboy0101017/vlc
  • kim.faughey/vlc
  • nurupo/vlc
  • yyusea/vlc
  • 0711235879.khco/vlc
  • ialo/vlc
  • iloveyeye2/vlc
  • gdtdftdqtd/vlc
  • leandroconsiglio/vlc
  • AndyHTML2012/vlc
  • ncz/vlc
  • lucenticus/vlc
  • knr1931/vlc
  • kjoonlee/vlc
  • chandrakant100/vlc-qt
  • johge42/vlc
  • polter/vlc
  • hexchain/vlc
  • Tushwrld/vlc
  • mztea928/vlc
  • jbelloncastro/vlc
  • alvinhochun/vlc
  • ghostpiratecrow/vlc
  • ujjwaltwitx/vlc
  • alexsonarin06/vlc
  • adrianbon76/vlc
  • altsod/vlc
  • damien.lucas44/vlc
  • dmytrivtaisa/vlc
  • utk202/vlc
  • aaxhrj/vlc
  • thomas.hermes/vlc
  • structurenewworldorder/vlc
  • slomo/vlc
  • wantlamy/vlc
  • musc.o3cminc/vlc
  • thebarshablog/vlc
  • kerrick/vlc
  • kratos142518/vlc
  • leogps/vlc
  • vacantron/vlc
  • luna_koly/vlc
  • Ratio2/vlc
  • anuoshemohammad/vlc
  • apsun/vlc
  • aaa1115910/vlc
  • alimotmoyo/vlc
  • Ambossmann/vlc
  • Sam-LearnsToCode/vlc
  • Chilledheart/vlc
  • Labnann/vlc
  • ktcoooot1/vlc
  • mohit-marathe/vlc
  • johnddx/vlc
  • manstabuk/vlc
  • Omar-ahmed314/vlc
  • vineethkm/vlc
  • 9Enemi86/vlc
  • radoslav.m.panteleev/vlc
  • ashishami2002/vlc
  • Corbax/vlc
  • firnasahmed/vlc
  • pelayarmalam4/vlc
  • c0ff330k/vlc
  • shikhindahikar/vlc
  • l342723951/vlc
  • christianschwandner/vlc
  • douniwan5788/vlc
  • 7damian7/vlc
  • ferdnyc/vlc
  • f.ales1/vlc
  • pandagby/vlc
  • BaaBaa/vlc
  • jewe37/vlc
  • w00drow/vlc
  • russelltg/vlc
  • ironicallygod/vlc
  • soumyaDghosh/vlc
  • linzihao1999/vlc
  • deyayush6/vlc
  • mibi88/vlc
  • newabdallah10/vlc
  • jhorbincolombia/vlc
  • rimvihaqueshupto/vlc
  • andrewkhon98/vlc
  • fab78/vlc
  • lapaz17/vlc
  • amanna13/vlc
  • mdakram28/vlc
  • 07jw1980/vlc
  • sohamgupta/vlc
  • Eson-Jia1/vlc
  • Sumou/vlc
  • vikram-kangotra/vlc
  • chalice191/vlc
  • olivercalder/vlc
  • aaasg4001/vlc
  • zipdox/vlc
  • kwizart/vlc
  • Dragon-S/vlc
  • jdemeule/vlc
  • gabriel_lt/vlc
  • locutusofborg/vlc
  • sammirata/vlc-librist
  • another/vlc
  • Benjamin_Loison/vlc
  • ahmedmoselhi/vlc
  • petergaal/vlc
  • huynhsontung/vlc
  • dariusmihut/vlc
  • tvermaashutosh/vlc
  • buti/vlc
  • Niram7777/vlc
  • rohan-here/vlc
  • balaji-sivasakthi/vlc
  • rlindner81/vlc
  • Kakadus/vlc
  • djain/vlc
  • ABBurmeister/vlc
  • craighuggins/vlc
  • orbea/vlc
  • maxos/vlc
  • aakarshmj/vlc
  • kblaschke/vlc
  • ankitm/vlc
  • advait-0/vlc
  • mohak2003/vlc
  • yselkowitz/vlc
  • AZM999/vlc-azm
  • andrey.turkin/vlc
  • Disha-Baghel/vlc
  • nowrep/vlc
  • Apeng/vlc
  • Choucroute_melba/vlc
  • autra/vlc
  • eclipseo/vlc
  • fhuber/vlc
  • olafhering/vlc
  • sdasda7777/vlc
  • 1div0/vlc
  • skosnits/vlc-extended-playlist-support
  • dnicolson/vlc
  • Timshel/vlc
  • octopols/vlc
  • MangalK/vlc
  • nima64/vlc
  • misawai/vlc
  • Alexander-Wilms/vlc
  • Maxime2/vlc-fork-for-visualizer
  • ww/vlc
  • jeske/vlc
  • sgross-emlix/vlc
  • morenonatural/vlc
  • freakingLovesVLC/vlc
  • borisgolovnev/vlc
  • mpromonet/vlc
  • diogo.simao-marques/vlc
  • masstock/vlc
  • pratikpatel8982/vlc
  • hugok79/vlc
  • longervision/vlc
  • abhiudaysurya/vlc
  • rishabhgarg/vlc
  • tumic/vlc
  • cart/vlc
  • shubham442/vlc
  • Aditya692005/vlc
  • sammirata/vlc4
  • syrykh/vlc
  • Vvorcun/macos-new-icon
  • AyaanshC/vlc
  • nasso/vlc
  • Quark/vlc
  • sebastinas/vlc
  • rhstone/vlc
  • talregev/vlc
  • Managor/vlc
403 results
Show changes
Commits on Source (2)
  • Pierre Lamot's avatar
    opengl: clear to black · 14bb0579
    Pierre Lamot authored and Steve Lhomme's avatar Steve Lhomme committed
    If the framebuffer have an alpha channel, the glClear may clear to a transparent
    color, which results in transparent "black bars"
    14bb0579
  • Pierre Lamot's avatar
    egl: provide GBM backed implementation for wayland · 50d9155a
    Pierre Lamot authored and Steve Lhomme's avatar Steve Lhomme committed
    Using GBM device to provide the EGL display fix scenarios where
    EGL_KHR_display_reference extension isn't available and the display ends up
    being shared with the UI, causing it to be destroyed when the video output is
    closed.
    50d9155a
/*****************************************************************************
* egl_gbm.c
* egl for wayland using GBM allocated buffers
*****************************************************************************
* Copyright (C) 2023 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
* 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 <stdlib.h>
#include <string.h>
#include <assert.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <wayland-egl.h>
#include "video_output/wayland/registry.h"
#include "video_output/wayland/linux-dmabuf-client-protocol.h"
#include <gbm.h>
#include <fcntl.h>
#include <xf86drm.h>
#include "gl_common.h"
#include <vlc_common.h>
#include <vlc_threads.h>
#include <vlc_plugin.h>
#include <vlc_opengl.h>
#include <vlc_window.h>
#include <vlc_fs.h>
static const char *clientExts;
static PFNGLFINISHPROC Finish;
#ifdef EGL_EXT_platform_base
static PFNEGLGETPLATFORMDISPLAYEXTPROC GetPlatformDisplayEXT;
static PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC CreatePlatformWindowSurfaceEXT;
#endif
typedef struct vlc_gl_sys_t
{
struct {
EGLDisplay display;
EGLSurface surface;
EGLContext context;
EGLConfig config;
bool is_current;
} egl;
struct {
struct wl_event_queue* wl_queue;
bool need_roundtrip;
struct zwp_linux_dmabuf_v1* dmabuf;
struct zwp_linux_dmabuf_feedback_v1* feedback;
} wayland;
struct {
struct gbm_device* device;
struct gbm_surface* surface;
struct gbm_bo* bo_prev;
struct gbm_bo* bo_next;
uint32_t format;
} gbm;
} vlc_gl_sys_t;
static bool CheckAPI(EGLDisplay dpy, const char* api)
{
const char* apis = eglQueryString(dpy, EGL_CLIENT_APIS);
return vlc_gl_StrHasToken(apis, api);
}
static bool CheckClientExt(const char* name)
{
return vlc_gl_StrHasToken(clientExts, name);
}
struct gl_api
{
const char name[10];
EGLenum api;
EGLint min_minor;
EGLint render_bit;
EGLint attr[3];
};
static int MakeCurrent (vlc_gl_t* gl)
{
vlc_gl_sys_t* sys = gl->sys;
if (sys->egl.surface == EGL_NO_SURFACE)
{
msg_Err(gl, "no surface to make current");
return VLC_EGENERIC;
}
if (eglMakeCurrent(sys->egl.display, sys->egl.surface, sys->egl.surface,
sys->egl.context) != EGL_TRUE)
{
msg_Err(gl, "failed to make current");
return VLC_EGENERIC;
}
sys->egl.is_current = true;
return VLC_SUCCESS;
}
static void ReleaseCurrent (vlc_gl_t* gl)
{
vlc_gl_sys_t* sys = gl->sys;
eglMakeCurrent(sys->egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
sys->egl.is_current = false;
}
static EGLSurface CreateSurface(vlc_gl_t* gl, unsigned int width, unsigned int height)
{
vlc_gl_sys_t* sys = gl->sys;
sys->gbm.surface = gbm_surface_create(
sys->gbm.device,
width, height,
sys->gbm.format,
GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT);
if (!sys->gbm.surface)
{
msg_Err(gl, "can't create gbm surface");
return EGL_NO_SURFACE;
}
#ifdef EGL_EXT_platform_base
return CreatePlatformWindowSurfaceEXT(sys->egl.display, sys->egl.config, sys->gbm.surface, NULL);
#else
return eglCreateWindowSurface(sys->egl.display, sys->egl.config, (EGLNativeWindowType)sys->gbm.surface, NULL);
#endif
}
static void Resize(vlc_gl_t* gl, unsigned width, unsigned height)
{
vlc_gl_sys_t* sys = gl->sys;
if (sys->egl.surface)
eglDestroySurface(sys->egl.display, sys->egl.surface);
if (sys->gbm.surface)
gbm_surface_destroy(sys->gbm.surface);
sys->egl.surface = CreateSurface(gl, width, height);
}
static void ReleaseBoPrivateData(struct gbm_bo* bo, void* data)
{
VLC_UNUSED(bo);
struct wl_buffer* buffer = (struct wl_buffer*) data;
wl_buffer_destroy(buffer);
}
static void LockNext(vlc_gl_t* gl)
{
vlc_gl_sys_t* sys = gl->sys;
struct gbm_bo* bo = gbm_surface_lock_front_buffer(sys->gbm.surface);
sys->gbm.bo_prev = sys->gbm.bo_next;
sys->gbm.bo_next = bo;
}
static void BindBuffer(vlc_gl_t* gl)
{
vlc_gl_sys_t* sys = gl->sys;
struct gbm_bo* bo = sys->gbm.bo_next;
if (!bo)
return;
uint32_t height = gbm_bo_get_height(bo);
uint32_t width = gbm_bo_get_width(bo);
struct wl_buffer* buffer = (struct wl_buffer*)gbm_bo_get_user_data(bo);
if (!buffer)
{
uint64_t modifier = gbm_bo_get_modifier(bo);
uint32_t format = gbm_bo_get_format(bo);
struct zwp_linux_buffer_params_v1* params = zwp_linux_dmabuf_v1_create_params(sys->wayland.dmabuf);
for (int i = 0; i < gbm_bo_get_plane_count(bo); ++i)
{
int fd = gbm_bo_get_fd_for_plane(bo, i);
uint32_t stride = gbm_bo_get_stride_for_plane(bo, i);
uint32_t offset = gbm_bo_get_offset(bo, i);
if (fd <= 0)
{
msg_Warn(gl, "no fd for plane");
continue;
}
zwp_linux_buffer_params_v1_add(params, fd, i, offset,
stride,
modifier >> 32,
modifier & 0xffffffff);
}
buffer = zwp_linux_buffer_params_v1_create_immed(params, width, height, format, 0);
zwp_linux_buffer_params_v1_destroy(params);
if (buffer)
gbm_bo_set_user_data(bo, buffer, ReleaseBoPrivateData);
}
wl_surface_attach(gl->surface->handle.wl, buffer, 0, 0);
wl_surface_damage(gl->surface->handle.wl, 0, 0, width, height);
wl_surface_commit(gl->surface->handle.wl);
wl_display_roundtrip_queue(gl->surface->display.wl, sys->wayland.wl_queue);
}
static void FreePrev(vlc_gl_t* gl)
{
vlc_gl_sys_t* sys = gl->sys;
if (sys->gbm.bo_prev)
{
gbm_surface_release_buffer(sys->gbm.surface, sys->gbm.bo_prev);
sys->gbm.bo_prev = NULL;
}
}
static void SwapBuffers(vlc_gl_t* gl)
{
vlc_gl_sys_t* sys = gl->sys;
if (!gbm_surface_has_free_buffers(sys->gbm.surface))
{
msg_Warn(gl, "no free buffers");
return;
}
if (!sys->egl.is_current)
{
EGLSurface s_read = eglGetCurrentSurface(EGL_READ);
EGLSurface s_draw = eglGetCurrentSurface(EGL_DRAW);
EGLContext previous_context = eglGetCurrentContext();
eglMakeCurrent(sys->egl.display, sys->egl.surface, sys->egl.surface, sys->egl.context);
eglSwapBuffers(sys->egl.display, sys->egl.surface);
Finish();
eglMakeCurrent(sys->egl.display, s_read, s_draw, previous_context);
}
else
{
eglSwapBuffers(sys->egl.display, sys->egl.surface);
Finish();
}
LockNext(gl);
BindBuffer(gl);
FreePrev(gl);
}
static void DestroySurface(vlc_gl_t* gl)
{
vlc_gl_sys_t* sys = gl->sys;
gbm_surface_destroy(sys->gbm.surface);
}
static EGLConfig MatchEglConfigToGBM(vlc_gl_t* gl, EGLint cfgc, EGLConfig* cfgv, EGLint targetFormat )
{
vlc_gl_sys_t* sys = gl->sys;
for (int i = 0; i < cfgc; ++i) {
EGLint nativeFormat;
if (!eglGetConfigAttrib(sys->egl.display, cfgv[i], EGL_NATIVE_VISUAL_ID, &nativeFormat))
continue;
if (nativeFormat == targetFormat)
return cfgv[i];
}
return EGL_CAST(EGLConfig,0);
}
static bool FindEglConfig(vlc_gl_t* gl, bool need_alpha)
{
vlc_gl_sys_t* sys = gl->sys;
//we require a finer config type
const EGLint conf_attr[] = {
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_BUFFER_SIZE, 32,
EGL_ALPHA_SIZE, need_alpha ? 8 : 0,
EGL_RENDERABLE_TYPE, gl->api_type == VLC_OPENGL_ES2 ? EGL_OPENGL_ES2_BIT : EGL_OPENGL_BIT,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_NONE
};
EGLint cfgc;
if (!eglGetConfigs(sys->egl.display, NULL, 0, &cfgc) || cfgc == 0)
return false;
EGLConfig* cfgv = malloc(cfgc * sizeof(EGLConfig));
if (eglChooseConfig(sys->egl.display, conf_attr, cfgv, cfgc, &cfgc) != EGL_TRUE
|| cfgc == 0)
{
msg_Err (gl, "cannot choose EGL configuration");
return false;
}
static const EGLint rgbaFormats[] = {
GBM_FORMAT_ARGB8888,
0
};
static const EGLint rgbFormats[] = {
GBM_FORMAT_XRGB8888,
GBM_FORMAT_ARGB8888,
0
};
const EGLint* gbmFormat = need_alpha ? rgbaFormats : rgbFormats;
EGLConfig config = 0;
while (*gbmFormat != 0)
{
config = MatchEglConfigToGBM(gl, cfgc, cfgv, *gbmFormat);
if (config != 0)
break;
gbmFormat++;
}
free(cfgv);
if (config == 0)
{
msg_Err(gl, "cannot choose EGL configuration matching gbm format");
return false;
}
sys->gbm.format = *gbmFormat;
sys->egl.config = config;
return true;
}
static bool OpenDrmDevice(vlc_gl_t* gl, drmDevice* device)
{
vlc_gl_sys_t* sys = gl->sys;
drmDevice* devices[64];
char* render_node = NULL;
int n = drmGetDevices2(0, devices, sizeof(devices) / sizeof(devices[0]));
for (int i = 0; i < n; ++i)
{
drmDevice* dev = devices[i];
if (device && !drmDevicesEqual(device, dev))
continue;
if (!(dev->available_nodes & (1 << DRM_NODE_RENDER)))
continue;
render_node = strdup(dev->nodes[DRM_NODE_RENDER]);
break;
}
drmFreeDevices(devices, n);
if (!render_node)
return false;
msg_Dbg(gl, "open drm device %s", render_node);
int fd = vlc_open(render_node, O_RDWR);
free(render_node);
if (fd < 0)
{
msg_Err(gl, "can't open drm device %s", render_node);
return false;
}
sys->gbm.device = gbm_create_device(fd);
return sys->gbm.device != NULL;
}
static void linux_dmabuf_feedback_handle_done(void* data, struct zwp_linux_dmabuf_feedback_v1* feedback)
{
VLC_UNUSED(data);
VLC_UNUSED(feedback);
}
static void linux_dmabuf_feedback_handle_format_table(void* data, struct zwp_linux_dmabuf_feedback_v1* feedback, int32_t fd, uint32_t size)
{
VLC_UNUSED(data);
VLC_UNUSED(feedback);
VLC_UNUSED(fd);
VLC_UNUSED(size);
}
static void linux_dmabuf_feedback_handle_main_device(void* data, struct zwp_linux_dmabuf_feedback_v1* feedback, struct wl_array* device_arr)
{
VLC_UNUSED(feedback);
VLC_UNUSED(device_arr);
vlc_gl_t* gl = data;
vlc_gl_sys_t* sys = gl->sys;
dev_t device;
assert(device_arr->size == sizeof(device));
memcpy(&device, device_arr->data, sizeof(device));
drmDevice* drmDev;
if (drmGetDeviceFromDevId(device, /* flags */ 0, &drmDev) != 0)
{
msg_Warn(gl, "unable to open main device");
return;
}
assert(drmDev);
assert(sys->gbm.device == NULL);
OpenDrmDevice(gl, drmDev);
drmFreeDevice(&drmDev);
}
static void linux_dmabuf_feedback_handle_tranche_done(void* data, struct zwp_linux_dmabuf_feedback_v1* feedback)
{
VLC_UNUSED(data);
VLC_UNUSED(feedback);
}
static void linux_dmabuf_feedback_handle_tranche_target_device(void* data, struct zwp_linux_dmabuf_feedback_v1* feedback, struct wl_array* device_arr)
{
VLC_UNUSED(data);
VLC_UNUSED(feedback);
VLC_UNUSED(device_arr);
}
static void linux_dmabuf_feedback_handle_tranche_formats(void* data, struct zwp_linux_dmabuf_feedback_v1* feedback, struct wl_array* indices)
{
VLC_UNUSED(data);
VLC_UNUSED(feedback);
VLC_UNUSED(indices);
}
static void linux_dmabuf_feedback_handle_tranche_flags(void* data, struct zwp_linux_dmabuf_feedback_v1* feedback, uint32_t flags)
{
VLC_UNUSED(data);
VLC_UNUSED(feedback);
VLC_UNUSED(flags);
}
static const struct zwp_linux_dmabuf_feedback_v1_listener linux_dmabuf_feedback_listener = {
linux_dmabuf_feedback_handle_done,
linux_dmabuf_feedback_handle_format_table,
linux_dmabuf_feedback_handle_main_device,
linux_dmabuf_feedback_handle_tranche_done,
linux_dmabuf_feedback_handle_tranche_target_device,
linux_dmabuf_feedback_handle_tranche_formats,
linux_dmabuf_feedback_handle_tranche_flags,
};
static void registry_global_cb(void* data, struct wl_registry* registry,
uint32_t id, const char* iface, uint32_t version)
{
vlc_gl_t* gl = data;
vlc_gl_sys_t* sys = gl->sys;
if (!strcmp(iface, "zwp_linux_dmabuf_v1"))
{
if (version <= 3)
{
msg_Warn(gl, "unsupported zwp_linux_dmabuf_v1 version");
}
else
{
sys->wayland.dmabuf = wl_registry_bind(registry,
id, &zwp_linux_dmabuf_v1_interface, 4);
sys->wayland.feedback = zwp_linux_dmabuf_v1_get_default_feedback(sys->wayland.dmabuf);
zwp_linux_dmabuf_feedback_v1_add_listener(sys->wayland.feedback,
&linux_dmabuf_feedback_listener,
gl);
sys->wayland.need_roundtrip = true;
}
}
}
static void registry_global_remove_cb(void* data, struct wl_registry* registry, uint32_t id)
{
VLC_UNUSED(data);
VLC_UNUSED(registry);
VLC_UNUSED(id);
}
static const struct wl_registry_listener registry_cbs =
{
registry_global_cb,
registry_global_remove_cb,
};
static bool GetWaylandRegistryInfo(vlc_gl_t* gl)
{
vlc_gl_sys_t* sys = gl->sys;
vlc_window_t* surface = gl->surface;
struct wl_display* display = surface->display.wl;
sys->wayland.wl_queue = wl_display_create_queue(surface->display.wl);
if (sys->wayland.wl_queue == NULL)
return false;
struct wl_display* wrapper = wl_proxy_create_wrapper(display);
wl_proxy_set_queue((struct wl_proxy*)wrapper, sys->wayland.wl_queue);
struct wl_registry* registry = wl_display_get_registry(wrapper);
if (!registry)
return false;
wl_proxy_wrapper_destroy(wrapper);
wl_registry_add_listener(registry, &registry_cbs, gl);
sys->wayland.need_roundtrip = true;
while (sys->wayland.need_roundtrip)
{
sys->wayland.need_roundtrip = false;
wl_display_roundtrip_queue(display, sys->wayland.wl_queue);
}
wl_registry_destroy(registry);
if (!sys->gbm.device)
return false;
return true;
}
static EGLDisplay OpenDisplay(vlc_gl_t* gl)
{
vlc_gl_sys_t* sys = gl->sys;
if (!CheckClientExt("EGL_KHR_platform_gbm"))
return EGL_NO_DISPLAY;
bool ret;
ret = GetWaylandRegistryInfo(gl);
if (!ret) {
msg_Info(gl, "can't find gbm device");
return false;
}
if (!sys->gbm.device)
{
msg_Err(gl, "can't create GBM device");
return EGL_NO_DISPLAY;
}
EGLDisplay display = eglGetPlatformDisplay(EGL_PLATFORM_GBM_KHR, sys->gbm.device,
NULL);
if (display == EGL_NO_DISPLAY)
{
msg_Err(gl, "can't get egl display from gbm device");
if (sys->gbm.device)
{
int fd = gbm_device_get_fd(sys->gbm.device);
gbm_device_destroy(sys->gbm.device);
close(fd);
}
return EGL_NO_DISPLAY;
}
return display;
}
static void ReleaseDisplay(vlc_gl_t* gl)
{
vlc_gl_sys_t* sys = gl->sys;
if (sys->gbm.device)
{
int fd = gbm_device_get_fd(sys->gbm.device);
gbm_device_destroy(sys->gbm.device);
close(fd);
}
if (sys->wayland.wl_queue)
wl_event_queue_destroy(sys->wayland.wl_queue);
}
static void* GetSymbol(vlc_gl_t* gl, const char* procname)
{
VLC_UNUSED(gl);
return (void*)eglGetProcAddress(procname);
}
static void Close(vlc_gl_t* gl)
{
vlc_gl_sys_t* sys = gl->sys;
if (sys->egl.context != EGL_NO_CONTEXT)
eglDestroyContext(sys->egl.display, sys->egl.context);
if (sys->egl.surface != EGL_NO_SURFACE)
{
eglDestroySurface(sys->egl.display, sys->egl.surface);
DestroySurface(gl);
}
eglTerminate(sys->egl.display);
ReleaseDisplay(gl);
free (sys);
}
static void InitEGL(void)
{
static vlc_once_t once = VLC_STATIC_ONCE;
if (unlikely(!vlc_once_begin(&once)))
{
clientExts = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
if (!clientExts)
clientExts = "";
#ifdef EGL_EXT_platform_base
GetPlatformDisplayEXT =
(void*) eglGetProcAddress("eglGetPlatformDisplayEXT");
CreatePlatformWindowSurfaceEXT =
(void*) eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT");
#endif
Finish = eglGetProcAddress("glFinish");
vlc_once_complete(&once);
}
}
/**
* Probe EGL display availability
*/
static int Open(vlc_gl_t* gl, const struct gl_api* api,
unsigned width, unsigned height,
const struct vlc_gl_cfg* gl_cfg)
{
//only wayland surface are supported
if (gl->surface->type != VLC_WINDOW_TYPE_WAYLAND)
return VLC_EGENERIC;
InitEGL();
int ret = VLC_EGENERIC;
vlc_object_t* obj = VLC_OBJECT(gl);
vlc_gl_sys_t* sys = calloc(1, sizeof(*sys));
if (unlikely(sys == NULL))
return VLC_ENOMEM;
msg_Dbg(obj, "EGL client extensions: %s", clientExts);
gl->sys = sys;
sys->egl.display = EGL_NO_DISPLAY;
sys->egl.surface = EGL_NO_SURFACE;
sys->egl.context = EGL_NO_CONTEXT;
sys->egl.is_current = false;
sys->egl.display = OpenDisplay(gl);
if (sys->egl.display == EGL_NO_DISPLAY)
{
free(sys);
return VLC_ENOTSUP;
}
/* Initialize EGL display */
EGLint major, minor;
if (eglInitialize(sys->egl.display, &major, &minor) != EGL_TRUE)
goto error;
msg_Dbg(obj, "EGL version %s by %s",
eglQueryString(sys->egl.display, EGL_VERSION),
eglQueryString(sys->egl.display, EGL_VENDOR));
const char* ext = eglQueryString(sys->egl.display, EGL_EXTENSIONS);
if (*ext)
msg_Dbg(obj, "EGL display extensions: %s", ext);
if (major != 1 || minor < api->min_minor
|| !CheckAPI(sys->egl.display, api->name))
{
msg_Err(obj, "cannot select %s API", api->name);
goto error;
}
ret = FindEglConfig(gl, gl_cfg->need_alpha);
if (!ret)
goto error;
/* Create a drawing surface */
sys->egl.surface = CreateSurface(gl, width, height);
if (sys->egl.surface == EGL_NO_SURFACE)
{
msg_Err(obj, "cannot create EGL window surface");
goto error;
}
if (eglBindAPI(api->api) != EGL_TRUE)
{
msg_Err(obj, "cannot bind EGL API");
goto error;
}
EGLContext ctx = eglCreateContext(sys->egl.display, sys->egl.config, EGL_NO_CONTEXT,
api->attr);
if (ctx == EGL_NO_CONTEXT)
{
msg_Err(obj, "cannot create EGL context");
goto error;
}
sys->egl.context = ctx;
/* Initialize OpenGL callbacks */
static const struct vlc_gl_operations ops = {
.make_current = MakeCurrent,
.release_current = ReleaseCurrent,
.resize = Resize,
.swap = SwapBuffers,
.get_proc_address = GetSymbol,
.close = Close,
};
gl->ops = &ops;
return VLC_SUCCESS;
error:
Close(gl);
return ret;
}
static int OpenGLES2(vlc_gl_t* gl, unsigned width, unsigned height,
const struct vlc_gl_cfg* gl_cfg)
{
static const struct gl_api api = {
"OpenGL_ES", EGL_OPENGL_ES_API, 4, EGL_OPENGL_ES2_BIT,
{ EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE },
};
return Open(gl, &api, width, height, gl_cfg);
}
static int OpenGL(vlc_gl_t* gl, unsigned width, unsigned height,
const struct vlc_gl_cfg* gl_cfg)
{
static const struct gl_api api = {
"OpenGL", EGL_OPENGL_API, 4, EGL_OPENGL_BIT,
{ EGL_NONE },
};
return Open(gl, &api, width, height, gl_cfg);
}
vlc_module_begin ()
set_shortname (N_("EGL GBM Wayland"))
set_description (N_("EGL GBM wayland extension for OpenGL"))
set_subcategory (SUBCAT_VIDEO_VOUT)
set_callback_opengl(OpenGL, 40) //lower priority than egl+wayland
add_shortcut ("egl")
add_submodule ()
set_callback_opengl_es2(OpenGLES2, 40) //lower priority than egl+wayland
add_shortcut ("egl")
vlc_module_end ()
......@@ -733,6 +733,7 @@ Draw(struct vlc_gl_filter *filter, const struct vlc_gl_picture *pic,
const opengl_vtable_t *vt = renderer->vt;
vt->ClearColor(0.f,0.f,0.f,1.f);
vt->Clear(GL_COLOR_BUFFER_BIT);
GL_ASSERT_NOERROR(vt);
......
......@@ -68,11 +68,31 @@ video_output/wayland/xdg-decoration-protocol.c: \
video_output/Makefile.am
$(AM_V_GEN)$(WAYLAND_SCANNER) private-code $< $@
video_output/wayland/linux-dmabuf-client-protocol.h: \
$(WAYLAND_PROTOCOLS)/unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml \
video_output/Makefile.am
$(AM_V_GEN)$(WAYLAND_SCANNER) client-header $< $@
video_output/wayland/linux-dmabuf-protocol.c: \
$(WAYLAND_PROTOCOLS)/unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml \
video_output/Makefile.am
$(AM_V_GEN)$(WAYLAND_SCANNER) private-code $< $@
libegl_wl_plugin_la_SOURCES = video_output/opengl/egl.c
libegl_wl_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -DUSE_PLATFORM_WAYLAND=1
libegl_wl_plugin_la_CFLAGS = $(AM_CFLAGS) $(EGL_CFLAGS) $(WAYLAND_EGL_CFLAGS)
libegl_wl_plugin_la_LIBADD = $(EGL_LIBS) $(WAYLAND_EGL_LIBS)
libegl_gbm_wl_plugin_la_SOURCES = video_output/opengl/egl_gbm.c
nodist_libegl_gbm_wl_plugin_la_SOURCES = \
video_output/wayland/linux-dmabuf-client-protocol.h \
video_output/wayland/linux-dmabuf-protocol.c
libegl_gbm_wl_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) \
-I$(builddir)/video_output/wayland
libegl_gbm_wl_plugin_la_CFLAGS = $(AM_CFLAGS) $(EGL_CFLAGS) $(WAYLAND_EGL_CFLAGS) $(GBM_CFLAGS) $(LIBDRM_CFLAGS)
libegl_gbm_wl_plugin_la_LIBADD = $(EGL_LIBS) $(WAYLAND_EGL_LIBS) $(GBM_LIBS) $(LIBDRM_LIBS)
CLEANFILES += $(nodist_libegl_gbm_wl_plugin_la_SOURCES)
libvk_wl_plugin_la_SOURCES = \
video_output/vulkan/platform.h \
video_output/wayland/vulkan.c
......@@ -89,6 +109,13 @@ BUILT_SOURCES += $(nodist_libxdg_shell_plugin_la_SOURCES)
vout_LTLIBRARIES += libxdg_shell_plugin.la
if HAVE_EGL
vout_LTLIBRARIES += libegl_wl_plugin.la
BUILT_SOURCES += $(nodist_libegl_wl_plugin_la_SOURCES)
if HAVE_GBM
if HAVE_LIBDRM
vout_LTLIBRARIES += libegl_gbm_wl_plugin.la
BUILT_SOURCES += $(nodist_libegl_gbm_wl_plugin_la_SOURCES)
endif
endif
endif
if HAVE_VULKAN
vout_LTLIBRARIES += libvk_wl_plugin.la
......