summaryrefslogtreecommitdiffstats
path: root/pica-client/vaapix11widget.h
diff options
context:
space:
mode:
authorAnton <anton@picapica.im>2026-08-16 03:28:51 +0400
committerAnton <anton@picapica.im>2026-08-16 03:28:51 +0400
commit1b7b9d46c84c38cbf2df293113a687481e205585 (patch)
tree59f95bc2900e5e12141d40777e332ce4e2ee91d6 /pica-client/vaapix11widget.h
parentad95ec8759777c4b8df0dcd66fd8200d24e912b1 (diff)
downloadpica-pica-1b7b9d46c84c38cbf2df293113a687481e205585.tar.gz
pica-pica-1b7b9d46c84c38cbf2df293113a687481e205585.zip
pica-client: VAAPI on X11, two codepaths
Diffstat (limited to 'pica-client/vaapix11widget.h')
-rw-r--r--pica-client/vaapix11widget.h97
1 files changed, 97 insertions, 0 deletions
diff --git a/pica-client/vaapix11widget.h b/pica-client/vaapix11widget.h
new file mode 100644
index 0000000..53b6135
--- /dev/null
+++ b/pica-client/vaapix11widget.h
@@ -0,0 +1,97 @@
+/*
+ (c) Copyright 2012 - 2026 Anton Sviridenko
+ https://picapica.im
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, version 3.
+
+ 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
+#ifndef VAAPIX11WIDGET_H
+#define VAAPIX11WIDGET_H
+
+#ifdef HAVE_VAAPI_X11
+
+#include "vaapi.h"
+
+#include <QWidget>
+#include <QString>
+
+// Draws decoded frames by handing the surface to the driver with the widget's
+// own X window as the target - vaPutSurface() - rather than going through
+// OpenGL at all. The picture never leaves the GPU; the driver does the colour
+// conversion and the scaling.
+//
+// This is the path for an X11 session, where Qt's OpenGL contexts come from
+// GLX and cannot import the DMA-BUF handles a surface is exported as. Since it
+// touches no OpenGL, it does not care which of the two Qt picked.
+//
+// The cost of drawing outside Qt is that Qt must be kept away from this
+// widget's area: it is given a native window of its own, Qt is told not to
+// paint or clear it (WA_PaintOnScreen, WA_NoSystemBackground, a null paint
+// engine), and anything drawn over it - a menu, a tooltip - will fight with
+// the video underneath.
+class VaapiX11Widget : public QWidget, public VaapiRenderWidget
+{
+ Q_OBJECT
+public:
+ explicit VaapiX11Widget(QWidget *parent = nullptr);
+ ~VaapiX11Widget() override;
+
+ virtual QWidget *widget() override { return this; }
+ virtual bool isWorking() const override { return m_working; }
+
+public slots:
+ virtual void setFrame(AVFramePtr frame) override;
+ virtual void clearFrame() override;
+
+signals:
+ // Raised once if a frame cannot be put on screen, carrying the reason.
+ // The widget stops trying after that.
+ void renderingFailed(QString message);
+
+protected:
+ // Nothing about this widget is painted by Qt, so it has no paint engine to
+ // offer. Returning one would have Qt draw over the video.
+ QPaintEngine *paintEngine() const override { return nullptr; }
+
+ void paintEvent(QPaintEvent *event) override;
+ void resizeEvent(QResizeEvent *event) override;
+ void showEvent(QShowEvent *event) override;
+
+private:
+ // Puts the current frame on the window, letterboxed to keep its aspect
+ // ratio. Returns false if the driver would not draw it.
+ bool putFrame();
+
+ // Paints the whole window black, so that the bars beside a letterboxed
+ // picture are not left holding whatever was there before.
+ void clearWindow();
+
+ void reportFailure(const QString &message);
+
+ AVFramePtr m_frame;
+ bool m_working;
+ bool m_reportedFailure;
+ bool m_describedSurface;
+ bool m_everDrew;
+
+ // Putting a surface on a window can fail for reasons that pass - the
+ // window not being mapped yet at the moment the first frame arrives, most
+ // obviously - so unlike an EGL import, which either works or never will,
+ // this one is worth retrying. Only a long run of failures means the path
+ // is really unusable.
+ int m_failuresInARow;
+ static const int kMaxFailuresInARow = 30;
+};
+
+#endif // HAVE_VAAPI_X11
+
+#endif // VAAPIX11WIDGET_H