diff options
| author | Anton <anton@picapica.im> | 2026-08-16 03:28:51 +0400 |
|---|---|---|
| committer | Anton <anton@picapica.im> | 2026-08-16 03:28:51 +0400 |
| commit | 1b7b9d46c84c38cbf2df293113a687481e205585 (patch) | |
| tree | 59f95bc2900e5e12141d40777e332ce4e2ee91d6 /pica-client/vaapix11widget.h | |
| parent | ad95ec8759777c4b8df0dcd66fd8200d24e912b1 (diff) | |
| download | pica-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.h | 97 |
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 |
