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
  • abdsaber000/vlc
  • falbrechtskirchinger/vlc
  • b.sullender/vlc
  • hulxv/vlc
  • zyad-ayad/vlc
  • shocknovaa/vlc
  • gremlinflat/vlc
  • Pratham24D/vlc
411 results
Show changes
Commits on Source (4)
......@@ -202,12 +202,13 @@ void CompositorVideo::commonSetupVoutWindow(vlc_window_t* p_wnd, VoutDestroyCb d
// These need to be connected here, since the compositor might not be ready when
// these signals are emitted. VOut window might not be set, or worse, compositor's
// internal preparations might not be completed yet:
constexpr auto connType = static_cast<Qt::ConnectionType>(Qt::UniqueConnection | Qt::DirectConnection);
connect(m_videoSurfaceProvider.get(), &VideoSurfaceProvider::surfacePositionChanged,
this, &CompositorVideo::onSurfacePositionChanged, Qt::UniqueConnection);
this, &CompositorVideo::onSurfacePositionChanged, connType);
connect(m_videoSurfaceProvider.get(), &VideoSurfaceProvider::surfaceSizeChanged,
this, &CompositorVideo::onSurfaceSizeChanged, Qt::UniqueConnection);
this, &CompositorVideo::onSurfaceSizeChanged, connType);
connect(m_videoSurfaceProvider.get(), &VideoSurfaceProvider::surfaceScaleChanged,
this, &CompositorVideo::onSurfaceScaleChanged, Qt::UniqueConnection);
this, &CompositorVideo::onSurfaceScaleChanged, connType);
}
void CompositorVideo::windowDestroy()
......@@ -268,7 +269,7 @@ bool CompositorVideo::commonGUICreateImpl(QWindow* window, CompositorVideo::Flag
assert(m_mainCtx);
assert(window);
m_videoSurfaceProvider = std::make_unique<VideoSurfaceProvider>();
m_videoSurfaceProvider = std::make_unique<VideoSurfaceProvider>(canDoThreadedSurfaceUpdates());
m_mainCtx->setVideoSurfaceProvider(m_videoSurfaceProvider.get());
const bool backendIsOpenVg = QQuickWindow::sceneGraphBackend() == QLatin1String("openvg");
if (!backendIsOpenVg && (flags & CompositorVideo::CAN_SHOW_PIP) && var_InheritBool(m_intf, "qt-pip-mode"))
......
......@@ -137,6 +137,9 @@ public:
virtual void windowUnsetFullscreen();
virtual void windowSetFullscreen(const char *id);
// The following method should return true if surface updates can be threaded:
virtual bool canDoThreadedSurfaceUpdates() const { return false; };
protected:
void commonSetupVoutWindow(vlc_window_t* p_wnd, VoutDestroyCb destroyCb);
void commonWindowEnable();
......
......@@ -69,6 +69,8 @@ public:
bool eventFilter(QObject *watched, QEvent *event) override;
bool canDoThreadedSurfaceUpdates() const override { return true; };
private slots:
void onSurfacePositionChanged(const QPointF& position) override;
void onSurfaceSizeChanged(const QSizeF& size) override;
......
......@@ -78,6 +78,8 @@ public:
int windowEnable(const vlc_window_cfg_t *) override;
void windowDisable() override;
bool canDoThreadedSurfaceUpdates() const override { return true; };
protected slots:
void onSurfacePositionChanged(const QPointF&) override;
void onSurfaceSizeChanged(const QSizeF&) override;
......
......@@ -103,19 +103,19 @@ static void SetSize(struct qtwayland_t* obj, size_t width, size_t height)
sys->height = height;
}
static void CommitSize(struct qtwayland_t* obj)
static bool CommitSize(struct qtwayland_t* obj)
{
#ifdef QT_HAS_WAYLAND_FRACTIONAL_SCALING
assert(obj);
const qtwayland_priv_t* const sys = (qtwayland_priv_t*)obj->p_sys;
assert(sys);
if (!sys->video_surface)
return;
return false;
if (sys->viewport)
{
// Non-positive size (except (-1, -1) pair) causes protocol error:
assert((sys->width > 0 && sys->height > 0) ||
(sys->height == -1 && sys->width == -1));
if (unlikely(!((sys->width > 0 && sys->height > 0) || (sys->height == -1 && sys->width == -1))))
return false;
// width and height here represent the final size, after scaling
// is taken into account. The fractional scaling protocol is not
......@@ -124,8 +124,11 @@ static void CommitSize(struct qtwayland_t* obj)
// to determine the device pixel ratio.
wp_viewport_set_destination(sys->viewport, sys->width, sys->height);
wl_surface_commit(sys->video_surface);
return true;
}
#endif
return false;
}
static void SetScale(struct qtwayland_t* obj, double scale)
......
......@@ -16,7 +16,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include "videosurface.hpp"
#include "maininterface/mainctx.hpp"
#include <QSGRectangleNode>
#include <QThreadPool>
#include <vlc_window.h>
......@@ -26,75 +26,16 @@
# include <QtGui/qpa/qplatformwindow.h>
#endif
WindowResizer::WindowResizer(vlc_window_t* window):
m_requestedWidth(0),
m_requestedHeight(0),
m_currentWidth(0),
m_currentHeight(0),
m_running(false),
m_voutWindow(window)
{
vlc_mutex_init(&m_lock);
vlc_cond_init(&m_cond);
setAutoDelete(false);
}
WindowResizer::~WindowResizer()
{
}
void WindowResizer::run()
{
vlc_mutex_lock(&m_lock);
while (m_requestedWidth != m_currentWidth ||
m_requestedHeight != m_currentHeight)
{
unsigned width = m_requestedWidth;
unsigned height = m_requestedHeight;
vlc_mutex_unlock(&m_lock);
vlc_window_ReportSize(m_voutWindow, width, height);
vlc_mutex_lock(&m_lock);
m_currentWidth = width;
m_currentHeight = height;
}
m_running = false;
vlc_cond_signal(&m_cond);
vlc_mutex_unlock(&m_lock);
}
void WindowResizer::reportSize(float width, float height)
{
if (width < 0 || height < 0)
return;
vlc_mutex_locker locker(&m_lock);
m_requestedWidth = static_cast<unsigned>(width);
m_requestedHeight = static_cast<unsigned>(height);
if (m_running == false)
{
m_running = true;
QThreadPool::globalInstance()->start(this);
}
}
/* Must called under m_voutlock before deletion */
void WindowResizer::waitForCompletion()
{
vlc_mutex_locker locker(&m_lock);
while (m_running)
vlc_cond_wait(&m_cond, &m_lock);
}
#include "maininterface/mainctx.hpp"
VideoSurfaceProvider::VideoSurfaceProvider(QObject* parent)
VideoSurfaceProvider::VideoSurfaceProvider(bool threadedSurfaceUpdates, QObject* parent)
: QObject(parent)
, m_threadedSurfaceUpdates(threadedSurfaceUpdates)
{
}
bool VideoSurfaceProvider::isEnabled()
{
QMutexLocker lock(&m_voutlock);
return m_voutWindow != nullptr;
}
......@@ -106,27 +47,14 @@ bool VideoSurfaceProvider::hasVideoEmbed() const
void VideoSurfaceProvider::enable(vlc_window_t* voutWindow)
{
assert(voutWindow);
{
QMutexLocker lock(&m_voutlock);
m_voutWindow = voutWindow;
m_resizer = new (std::nothrow) WindowResizer(voutWindow);
}
m_voutWindow = voutWindow;
emit videoEnabledChanged(true);
}
void VideoSurfaceProvider::disable()
{
setVideoEmbed(false);
{
QMutexLocker lock(&m_voutlock);
if (m_resizer != nullptr)
{
m_resizer->waitForCompletion();
delete m_resizer;
m_resizer = nullptr;
}
m_voutWindow = nullptr;
}
m_voutWindow = nullptr;
emit videoEnabledChanged(false);
}
......@@ -138,44 +66,36 @@ void VideoSurfaceProvider::setVideoEmbed(bool embed)
void VideoSurfaceProvider::onWindowClosed()
{
QMutexLocker lock(&m_voutlock);
if (m_resizer != nullptr)
m_resizer->waitForCompletion();
if (m_voutWindow)
vlc_window_ReportClose(m_voutWindow);
}
void VideoSurfaceProvider::onMousePressed(int vlcButton)
{
QMutexLocker lock(&m_voutlock);
if (m_voutWindow)
vlc_window_ReportMousePressed(m_voutWindow, vlcButton);
}
void VideoSurfaceProvider::onMouseReleased(int vlcButton)
{
QMutexLocker lock(&m_voutlock);
if (m_voutWindow)
vlc_window_ReportMouseReleased(m_voutWindow, vlcButton);
}
void VideoSurfaceProvider::onMouseDoubleClick(int vlcButton)
{
QMutexLocker lock(&m_voutlock);
if (m_voutWindow)
vlc_window_ReportMouseDoubleClick(m_voutWindow, vlcButton);
}
void VideoSurfaceProvider::onMouseMoved(float x, float y)
{
QMutexLocker lock(&m_voutlock);
if (m_voutWindow)
vlc_window_ReportMouseMoved(m_voutWindow, x, y);
}
void VideoSurfaceProvider::onMouseWheeled(int vlcButton)
{
QMutexLocker lock(&m_voutlock);
if (m_voutWindow)
vlc_window_ReportKeyPress(m_voutWindow, vlcButton);
}
......@@ -184,19 +104,14 @@ void VideoSurfaceProvider::onKeyPressed(int key, Qt::KeyboardModifiers modifiers
{
QKeyEvent event(QEvent::KeyPress, key, modifiers);
int vlckey = qtEventToVLCKey(&event);
QMutexLocker lock(&m_voutlock);
if (m_voutWindow)
vlc_window_ReportKeyPress(m_voutWindow, vlckey);
}
void VideoSurfaceProvider::onSurfaceSizeChanged(QSizeF size)
{
emit surfaceSizeChanged(size);
QMutexLocker lock(&m_voutlock);
if (m_resizer)
m_resizer->reportSize(std::ceil(size.width()), std::ceil(size.height()));
else if (m_voutWindow)
if (m_voutWindow)
vlc_window_ReportSize(m_voutWindow, std::ceil(size.width()), std::ceil(size.height()));
}
......@@ -207,17 +122,6 @@ VideoSurface::VideoSurface(QQuickItem* parent)
setAcceptHoverEvents(true);
setAcceptedMouseButtons(Qt::AllButtons);
setFlag(ItemAcceptsInputMethod, true);
{
connect(this, &QQuickItem::widthChanged, this, &VideoSurface::updateSurfaceSize);
connect(this, &QQuickItem::heightChanged, this, &VideoSurface::updateSurfaceSize);
connect(this, &QQuickItem::xChanged, this, &VideoSurface::updateSurfacePosition);
connect(this, &QQuickItem::yChanged, this, &VideoSurface::updateSurfacePosition);
// This is for the case when the item's parent-relative position stays the same, but ancestors change position:
connect(this, &ViewBlockingRectangle::scenePositionHasChanged, this, &VideoSurface::updateSurfacePosition, Qt::QueuedConnection);
}
}
int VideoSurface::qtMouseButton2VLC( Qt::MouseButton qtButton )
......@@ -321,30 +225,50 @@ void VideoSurface::setCursorShape(Qt::CursorShape shape)
setCursor(shape);
}
void VideoSurface::updatePolish()
void VideoSurface::synchronize()
{
QQuickItem::updatePolish();
// This may be called from the rendering thread, not necessarily
// during synchronization (GUI thread is not blocked). Try to
// be very careful.
assert(window());
QSizeF size;
QPointF position;
if (m_sizeDirty && !size().isEmpty())
if (QThread::currentThread() == thread())
{
emit surfaceSizeChanged(size() * window()->effectiveDevicePixelRatio());
m_sizeDirty = false;
// Item's thread (GUI thread):
size = this->size();
position = this->mapToScene(QPointF(0,0));
}
else
{
// Render thread:
size = renderSize();
position = renderPosition();
}
if (m_positionDirty)
if (m_oldRenderSize != size || m_dprDirty)
{
QPointF scenePosition = this->mapToScene(QPointF(0,0));
if (!size.isEmpty())
{
emit surfaceSizeChanged(size * m_dpr);
m_oldRenderSize = size;
}
}
emit surfacePositionChanged(scenePosition * window()->effectiveDevicePixelRatio());
m_positionDirty = false;
if (m_oldRenderPosition != position || m_dprDirty)
{
if (position.x() >= 0.0 && position.y() >= 0.0)
{
emit surfacePositionChanged(position * m_dpr); // render position is relative to scene/viewport
m_oldRenderPosition = position;
}
}
if (m_scaleDirty)
if (m_dprDirty)
{
emit surfaceScaleChanged(window()->effectiveDevicePixelRatio());
m_scaleDirty = false;
emit surfaceScaleChanged(m_dpr);
m_dprDirty = false;
}
}
......@@ -352,37 +276,14 @@ void VideoSurface::itemChange(ItemChange change, const ItemChangeData &value)
{
if (change == ItemDevicePixelRatioHasChanged || change == ItemSceneChange)
{
updateSurfaceScale();
m_dprChanged = true;
// Request update, so that `updatePaintNode()` gets called which updates the DPR for `::synchronize()`:
update();
}
QQuickItem::itemChange(change, value);
}
void VideoSurface::updateSurfacePosition()
{
m_positionDirty = true;
polish();
}
void VideoSurface::updateSurfaceSize()
{
m_sizeDirty = true;
polish();
}
void VideoSurface::updateSurfaceScale()
{
m_scaleDirty = true;
polish();
}
void VideoSurface::updateSurface()
{
updateSurfacePosition();
updateSurfaceSize();
updateSurfaceScale();
}
void VideoSurface::setVideoSurfaceProvider(VideoSurfaceProvider *newVideoSurfaceProvider)
{
if (m_provider == newVideoSurfaceProvider)
......@@ -404,15 +305,13 @@ void VideoSurface::setVideoSurfaceProvider(VideoSurfaceProvider *newVideoSurface
connect(this, &VideoSurface::mouseDblClicked, m_provider, &VideoSurfaceProvider::onMouseDoubleClick);
connect(this, &VideoSurface::mouseReleased, m_provider, &VideoSurfaceProvider::onMouseReleased);
connect(this, &VideoSurface::keyPressed, m_provider, &VideoSurfaceProvider::onKeyPressed);
connect(this, &VideoSurface::surfaceSizeChanged, m_provider, &VideoSurfaceProvider::onSurfaceSizeChanged);
connect(this, &VideoSurface::surfacePositionChanged, m_provider, &VideoSurfaceProvider::surfacePositionChanged);
connect(this, &VideoSurface::surfaceScaleChanged, m_provider, &VideoSurfaceProvider::surfaceScaleChanged);
connect(this, &VideoSurface::surfaceSizeChanged, m_provider, &VideoSurfaceProvider::onSurfaceSizeChanged, Qt::DirectConnection);
connect(this, &VideoSurface::surfacePositionChanged, m_provider, &VideoSurfaceProvider::surfacePositionChanged, Qt::DirectConnection);
connect(this, &VideoSurface::surfaceScaleChanged, m_provider, &VideoSurfaceProvider::surfaceScaleChanged, Qt::DirectConnection);
connect(&m_wheelEventConverter, &WheelToVLCConverter::vlcWheelKey, m_provider, &VideoSurfaceProvider::onMouseWheeled);
connect(m_provider, &VideoSurfaceProvider::videoEnabledChanged, this, &VideoSurface::updateSurface);
setFlag(ItemHasContents, true);
updateSurface(); // Polish is queued anyway, updatePolish() should be called when the initial size is set.
}
else
{
......@@ -421,3 +320,48 @@ void VideoSurface::setVideoSurfaceProvider(VideoSurfaceProvider *newVideoSurface
emit videoSurfaceProviderChanged();
}
QSGNode *VideoSurface::updatePaintNode(QSGNode *node, UpdatePaintNodeData *data)
{
// This is called from the render thread, but during synchronization.
// So the GUI thread is blocked here. This makes it safer to access the window
// to get the effective DPR, rather than doing it outside the synchronization
// stage.
const auto w = window();
assert (w);
if (Q_UNLIKELY(!m_provider))
return node;
if (w != m_oldWindow)
{
if (m_oldWindow)
disconnect(m_oldWindow, &QQuickWindow::afterRendering, this, &VideoSurface::synchronize);
m_oldWindow = w;
if (w)
{
// This is constant:
if (m_provider->supportsThreadedSurfaceUpdates())
{
// Synchronize just before swapping the frame for better synchronization:
connect(w, &QQuickWindow::afterRendering, this, &VideoSurface::synchronize, Qt::DirectConnection);
}
else
{
connect(w, &QQuickWindow::afterAnimating, this, &VideoSurface::synchronize);
}
}
}
if (m_dprChanged)
{
m_dpr = w->effectiveDevicePixelRatio();
m_dprDirty = true;
m_dprChanged = false;
}
return ViewBlockingRectangle::updatePaintNode(node, data);
}
......@@ -35,33 +35,11 @@ Q_MOC_INCLUDE( "maininterface/mainctx.hpp")
class MainCtx;
class WindowResizer :
public QRunnable
{
public:
WindowResizer(vlc_window_t* window);
virtual ~WindowResizer();
void run() override;
void reportSize(float width, float height);
void waitForCompletion();
private:
vlc_mutex_t m_lock;
vlc_cond_t m_cond;
unsigned m_requestedWidth;
unsigned m_requestedHeight;
unsigned m_currentWidth;
unsigned m_currentHeight;
bool m_running;
vlc_window_t* m_voutWindow;
};
class VideoSurfaceProvider : public QObject
{
Q_OBJECT
public:
VideoSurfaceProvider(QObject* parent = nullptr);
VideoSurfaceProvider(bool threadedSurfaceUpdates = false, QObject* parent = nullptr);
virtual ~VideoSurfaceProvider() {}
void enable(vlc_window_t* voutWindow);
......@@ -71,6 +49,8 @@ public:
void setVideoEmbed(bool embed);
bool hasVideoEmbed() const;
bool supportsThreadedSurfaceUpdates() const { return m_threadedSurfaceUpdates; };
signals:
void ctxChanged(MainCtx*);
bool videoEnabledChanged(bool);
......@@ -90,10 +70,9 @@ public slots:
void onSurfaceSizeChanged(QSizeF size);
protected:
QMutex m_voutlock;
vlc_window_t* m_voutWindow = nullptr;
WindowResizer * m_resizer = nullptr;
bool m_videoEmbed = false;
bool m_threadedSurfaceUpdates = false;
};
......@@ -110,6 +89,8 @@ public:
void setVideoSurfaceProvider(VideoSurfaceProvider *newVideoSurfaceProvider);
protected:
QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) override;
int qtMouseButton2VLC( Qt::MouseButton qtButton );
void mousePressEvent(QMouseEvent *event) override;
......@@ -125,10 +106,7 @@ protected:
Qt::CursorShape getCursorShape() const;
void setCursorShape(Qt::CursorShape);
void updatePolish() override;
void itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value) override;
signals:
void surfaceSizeChanged(QSizeF);
void surfacePositionChanged(QPointF);
......@@ -143,10 +121,7 @@ signals:
void videoSurfaceProviderChanged();
protected slots:
void updateSurfacePosition();
void updateSurfaceSize();
void updateSurfaceScale();
void updateSurface();
void synchronize();
private:
QPointF m_oldHoverPos;
......@@ -155,9 +130,22 @@ private:
QPointer<VideoSurfaceProvider> m_provider;
bool m_sizeDirty = false;
bool m_positionDirty = false;
bool m_scaleDirty = false;
QPointer<QQuickWindow> m_oldWindow;
// This is updated and read from different threads, but during synchronization stage so explicit synchronization
// such as atomic boolean or locking is not necessary:
bool m_dprChanged = false; // itemChange() <-> updatePaintNode() (different threads, but GUI thread is blocked)
// These are updated and read from either the item/GUI thread or the render thread:
QSizeF m_oldRenderSize;
QPointF m_oldRenderPosition {-1., -1.};
// m_dpr and m_dprDirty are updated in render thread when the GUI thread is blocked (updatePaintNode()).
// m_dprDirty may be updated in GUI thread when threaded updates is not possible. Since m_dprDirty can
// not be updated both in render thread and GUI thread concurrently (as GUI thread is blocked during
// updatePaintNode() call), data synchronization should not be necessary:
qreal m_dpr = 1.0;
bool m_dprDirty = false;
};
#endif // VIDEOSURFACE_HPP
......@@ -30,10 +30,6 @@ T.Control {
width: Math.round(VLCStyle.dp(320, VLCStyle.scale))
height: Math.round(VLCStyle.dp(180, VLCStyle.scale))
//VideoSurface x,y won't update
onXChanged: videoSurface.updateSurfacePosition()
onYChanged: videoSurface.updateSurfacePosition()
objectName: "pip window"
property real dragXMin: 0
......
......@@ -122,12 +122,19 @@ QSGNode *ViewBlockingRectangle::updatePaintNode(QSGNode *oldNode, UpdatePaintNod
if (!oldNode)
{
const auto observerNode = new MatrixChangeObserverNode([p = QPointer(this)]() {
const auto observerNode = new MatrixChangeObserverNode([p = QPointer(this)](const QMatrix4x4& matrix) {
if (Q_LIKELY(p))
{
p->m_renderPosition = {matrix.row(0)[3], // Viewport/scene X
matrix.row(1)[3]}; // Viewport/scene y
emit p->scenePositionHasChanged();
}
});
observerNode->setFlag(QSGNode::OwnedByParent);
// Initial position:
m_renderPosition = mapToScene(QPointF(0,0));
if (softwareMode)
{
softwareRenderNode = new SoftwareRenderNode;
......@@ -157,6 +164,8 @@ QSGNode *ViewBlockingRectangle::updatePaintNode(QSGNode *oldNode, UpdatePaintNod
const auto rect = boundingRect();
m_renderSize = rect.size();
if (softwareMode)
{
softwareRenderNode->setRect(rect);
......@@ -185,3 +194,13 @@ QSGNode *ViewBlockingRectangle::updatePaintNode(QSGNode *oldNode, UpdatePaintNod
return rectangleNode;
}
}
QSizeF ViewBlockingRectangle::renderSize() const
{
return m_renderSize;
}
QPointF ViewBlockingRectangle::renderPosition() const
{
return m_renderPosition;
}
......@@ -29,27 +29,35 @@
class MatrixChangeObserverNode : public QSGRenderNode
{
public:
explicit MatrixChangeObserverNode(const std::function<void()>& callback)
explicit MatrixChangeObserverNode(const std::function<void(const QMatrix4x4&)>& callback)
: m_callback(callback) { }
void render(const RenderState *) override
// Use prepare(), because matrix() returns dangling pointer when render() is called from Qt 6.2 to 6.5 (QTBUG-97589):
void prepare() override
{
QSGRenderNode::prepare(); // The documentation says that the default implementation is empty, but still call it just in case.
assert(matrix());
const QMatrix4x4 m = *matrix(); // matrix() is the combined matrix here
if (m_lastCombinedMatrix != m)
{
m_callback();
m_callback(m);
m_lastCombinedMatrix = m;
}
}
void render(const RenderState *) override
{
// We do not render anything in this node.
}
RenderingFlags flags() const override
{
// Enable all optimizations, as we are not actually rendering anything in this node:
return static_cast<RenderingFlags>(BoundedRectRendering | DepthAwareRendering | OpaqueRendering | NoExternalRendering);
}
private:
std::function<void()> m_callback;
std::function<void(const QMatrix4x4& newMatrix)> m_callback;
QMatrix4x4 m_lastCombinedMatrix;
};
......@@ -65,10 +73,20 @@ public:
protected:
QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) override;
// For now these are protected, but can be made public if necessary:
// These methods should only be called from the rendering thread.
QSizeF renderSize() const;
QPointF renderPosition() const;
private:
QColor m_color;
bool m_windowChanged = false;
// Although these members belong to the class instance's thread, they
// are updated in the rendering thread:
QSizeF m_renderSize;
QPointF m_renderPosition {-1., -1.};
signals:
// NOTE: `scenePositionHasChanged()` signal is emitted from the render thread,
// and NOT during synchronization (meaning, GUI thread is not blocked):
......