feat: add vaapi path for video wallpapers on generic gpus
C++ / fmt (pull_request) Failing after 6s
C++ / build (pull_request) Failing after 10s
C++ / clang-tidy (pull_request) Failing after 11s
JS/TS / fmt (pull_request) Successful in 10s
JS/TS / lint (pull_request) Successful in 8s
Python / static (pull_request) Failing after 32s
Rust / build (pull_request) Successful in 52s
Python / verify (pull_request) Failing after 1m23s
Rust / fmt (pull_request) Successful in 51s
Rust / clippy (pull_request) Successful in 1m2s
C++ / fmt (pull_request) Failing after 6s
C++ / build (pull_request) Failing after 10s
C++ / clang-tidy (pull_request) Failing after 11s
JS/TS / fmt (pull_request) Successful in 10s
JS/TS / lint (pull_request) Successful in 8s
Python / static (pull_request) Failing after 32s
Rust / build (pull_request) Successful in 52s
Python / verify (pull_request) Failing after 1m23s
Rust / fmt (pull_request) Successful in 51s
Rust / clippy (pull_request) Successful in 1m2s
This commit is contained in:
@@ -1,384 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <EGL/egl.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include <QImage>
|
||||
#include <QHash>
|
||||
#include <QList>
|
||||
#include <QElapsedTimer>
|
||||
#include <QRectF>
|
||||
#include <QSize>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QVariantMap>
|
||||
#include <QVector>
|
||||
#include <QtQml/qqml.h>
|
||||
#include <qtmetamacros.h>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
|
||||
#ifdef ZHAVE_VIDEO
|
||||
#include "videoplayer.hpp"
|
||||
#endif
|
||||
|
||||
#include <qwayland-wlr-layer-shell-unstable-v1.h>
|
||||
#include <wayland-client-protocol.h>
|
||||
|
||||
#include "wallpapersurface.hpp"
|
||||
#include "config/enums.hpp"
|
||||
|
||||
struct mpv_handle;
|
||||
struct mpv_render_context;
|
||||
|
||||
class QProcess;
|
||||
|
||||
namespace ZShell::internal {
|
||||
|
||||
class WallpaperSurface;
|
||||
|
||||
class WallpaperService : public QObject {
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
|
||||
Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged REQUIRED)
|
||||
Q_PROPERTY(QVariantMap crops READ crops WRITE setCrops NOTIFY cropsChanged)
|
||||
Q_PROPERTY(QString dbPath READ dbPath WRITE setDbPath NOTIFY dbPathChanged)
|
||||
Q_PROPERTY(
|
||||
QSize largestBufferSize READ largestBufferSize NOTIFY
|
||||
largestBufferSizeChanged)
|
||||
|
||||
public:
|
||||
explicit WallpaperService(QObject* parent = nullptr);
|
||||
~WallpaperService() override;
|
||||
|
||||
[[nodiscard]] QString path() const;
|
||||
void setPath(const QString& path);
|
||||
|
||||
[[nodiscard]] QSize largestBufferSize() const;
|
||||
|
||||
[[nodiscard]] QString dbPath() const;
|
||||
void setDbPath(const QString& path);
|
||||
|
||||
void addScreen(const QString& screen);
|
||||
void removeScreen(const QString& screen);
|
||||
|
||||
[[nodiscard]] const QVariantMap& crops() const;
|
||||
void setCrops(const QVariantMap& crops);
|
||||
|
||||
Q_INVOKABLE void redraw();
|
||||
|
||||
Q_INVOKABLE void setCrop(const QString& screen, const QVariantMap& crop);
|
||||
|
||||
Q_INVOKABLE void invalidateCache();
|
||||
|
||||
signals:
|
||||
void pathChanged();
|
||||
void cropsChanged();
|
||||
void dbPathChanged();
|
||||
void largestBufferSizeChanged();
|
||||
|
||||
private:
|
||||
friend class WallpaperSurface;
|
||||
|
||||
static bool isVideoPath(const QString& path);
|
||||
|
||||
static bool isHardwareCodec(const QString& codec);
|
||||
|
||||
[[nodiscard]] QString codecName(const QString& path) const;
|
||||
[[nodiscard]] QString cacheDir() const;
|
||||
[[nodiscard]] QString transcodeTarget(const QString& path) const;
|
||||
[[nodiscard]] bool needsTranscode(const QString& path) const;
|
||||
void transcodeVideo(const QString& src, const QString& dst);
|
||||
|
||||
void applyPath(const QString& path);
|
||||
|
||||
void startVideo(const QString& path);
|
||||
void teardownMpv();
|
||||
|
||||
void initMpvRender();
|
||||
void renderMpvToSurface(const QSize& size);
|
||||
void pumpMpvEvents();
|
||||
|
||||
static void* getMpvProcAddress(void* ctx, const char* name);
|
||||
static void mpvUpdate(void* ctx);
|
||||
|
||||
#ifdef ZHAVE_VIDEO
|
||||
bool startPlayerVideo(const QString& path);
|
||||
void stopPlayerVideo();
|
||||
[[nodiscard]] uint32_t createVideoProgram();
|
||||
void drawVideoTexture(
|
||||
uint32_t lumaTex,
|
||||
uint32_t chromaTex,
|
||||
int matrix,
|
||||
int range,
|
||||
const QRectF& rect,
|
||||
float sizeW,
|
||||
float sizeH,
|
||||
float srcW,
|
||||
float srcH,
|
||||
float alpha);
|
||||
#endif
|
||||
|
||||
void bindGlobals();
|
||||
static void registryGlobal(
|
||||
void* data,
|
||||
struct wl_registry* registry,
|
||||
uint32_t name,
|
||||
const char* interface,
|
||||
uint32_t version);
|
||||
|
||||
void storeGlobal(const char* interface, void* proxy);
|
||||
|
||||
struct TransProgram {
|
||||
uint32_t id = 0;
|
||||
int size = -1;
|
||||
int progress = -1;
|
||||
int from = -1;
|
||||
int to = -1;
|
||||
int fromCrop = -1;
|
||||
int toCrop = -1;
|
||||
int fromFlip = -1;
|
||||
int toFlip = -1;
|
||||
};
|
||||
|
||||
[[nodiscard]] bool setupGl();
|
||||
[[nodiscard]] uint32_t createProgram();
|
||||
[[nodiscard]] TransProgram createTransitionProgram(const QString& file);
|
||||
[[nodiscard]] TransProgram programFor(const QString& file);
|
||||
bool ensureTransitionProgram();
|
||||
QString transitionFileFor(ZShell::config::WallpaperTransition::Enum value);
|
||||
[[nodiscard]] QString randomTransitionFile();
|
||||
|
||||
void ensureCapture(const QSize& size);
|
||||
uint32_t renderVideoIntoTexture(const QSize& size);
|
||||
|
||||
void drawSurfaceTransition(WallpaperSurface* surface);
|
||||
|
||||
struct TransitionLayer {
|
||||
uint32_t tex = 0; // frozen image target (older layers)
|
||||
QImage image; // CPU copy for crops/sizing (image layers)
|
||||
QVariantMap crops; // crop map captured when the layer was pushed
|
||||
QString transitionFile; // this layer's own transition shader
|
||||
bool isVideo = false; // only the newest layer may be video
|
||||
bool ready = false; // target is sampleable
|
||||
bool started = false; // its own clock has begun
|
||||
QElapsedTimer timer;
|
||||
qreal progress = 0.0;
|
||||
};
|
||||
|
||||
void ensureBaseFbo();
|
||||
void ensureAccum(const QSize& size);
|
||||
void bindRtt(uint32_t fbo, uint32_t tex, const QSize& size);
|
||||
void drawTransitionPair(
|
||||
const TransProgram& program,
|
||||
uint32_t fromTex,
|
||||
float fromFlip,
|
||||
const QRectF& fromCrop,
|
||||
uint32_t toTex,
|
||||
float toFlip,
|
||||
const QRectF& toCrop,
|
||||
qreal progress,
|
||||
const QSize& size);
|
||||
uint32_t targetTexFor(const TransitionLayer& layer, int index) const;
|
||||
QRectF cropForLayer(
|
||||
const TransitionLayer& layer,
|
||||
const QString& screen,
|
||||
const QSize& size) const;
|
||||
void captureBase(
|
||||
const QSize& size,
|
||||
const QString& screen,
|
||||
uint32_t oldTex,
|
||||
float oldFlip,
|
||||
const QRectF& oldCrop);
|
||||
void renderComposite(
|
||||
const QSize& size,
|
||||
const QString& screen,
|
||||
uint32_t outFbo,
|
||||
uint32_t outTex,
|
||||
int first,
|
||||
int last,
|
||||
uint32_t videoTex,
|
||||
uint32_t posterTex);
|
||||
|
||||
void uploadTexture(uint32_t& texture, const QImage& image);
|
||||
void uploadImage();
|
||||
void createBlackTexture(uint32_t& texture);
|
||||
|
||||
void drawTexture(
|
||||
uint32_t texture,
|
||||
const QRectF& rect,
|
||||
float sizeW,
|
||||
float sizeH,
|
||||
float alpha);
|
||||
|
||||
[[nodiscard]] QImage decodeImage(
|
||||
const QString& path, const QSize& decodeSize) const;
|
||||
|
||||
[[nodiscard]] QByteArray cachedBlob(const QString& path) const;
|
||||
|
||||
[[nodiscard]] QByteArray posterBlob(const QString& path) const;
|
||||
|
||||
[[nodiscard]] QVariantMap cropsForPath(const QString& path) const;
|
||||
|
||||
void ensureImage();
|
||||
|
||||
void ensurePoster();
|
||||
|
||||
void notifyBufferSizes();
|
||||
|
||||
void queue(WallpaperSurface* surface);
|
||||
void queueAll();
|
||||
|
||||
void loop();
|
||||
|
||||
void present();
|
||||
|
||||
void drawSurface(WallpaperSurface* surface);
|
||||
|
||||
void wake();
|
||||
|
||||
[[nodiscard]] wl_event_queue* eventQueue() const { return m_queue; }
|
||||
|
||||
[[nodiscard]] QRectF sourceRect(
|
||||
const QVariantMap& crops,
|
||||
const QString& screen,
|
||||
const QSize& size,
|
||||
const QSize& image) const;
|
||||
|
||||
void start();
|
||||
|
||||
void addSurfaces();
|
||||
void addSurface(const QString& screen);
|
||||
|
||||
QString m_path;
|
||||
QString m_dbPath;
|
||||
QStringList m_screens;
|
||||
QVariantMap m_crops;
|
||||
|
||||
QImage m_image;
|
||||
|
||||
bool m_isVideo = false;
|
||||
bool m_videoReload = false;
|
||||
mpv_handle* m_mpv = nullptr;
|
||||
mpv_render_context* m_mpvRender = nullptr;
|
||||
uint32_t m_blackTex = 0;
|
||||
std::atomic<bool> m_mpvFrameReady{false};
|
||||
std::atomic<bool> m_videoReady{false};
|
||||
std::atomic<bool> m_videoLoaded{false};
|
||||
|
||||
QProcess* m_transcode = nullptr;
|
||||
|
||||
QSize m_decodeSize;
|
||||
|
||||
QImage m_stagedImage;
|
||||
QString m_stagedPath;
|
||||
bool m_stagedReady = false;
|
||||
bool m_decoding = false;
|
||||
QString m_decodePath;
|
||||
bool m_replacementReady = false;
|
||||
|
||||
wl_display* m_display = nullptr;
|
||||
wl_registry* m_registry = nullptr;
|
||||
wl_compositor* m_compositor = nullptr;
|
||||
QtWayland::zwlr_layer_shell_v1* m_layerShell = nullptr;
|
||||
QtWayland::wp_viewporter* m_viewporter = nullptr;
|
||||
QtWayland::wp_fractional_scale_manager_v1* m_scaleManager = nullptr;
|
||||
|
||||
EGLDisplay m_eglDisplay = EGL_NO_DISPLAY;
|
||||
EGLConfig m_config = nullptr;
|
||||
EGLContext m_context = EGL_NO_CONTEXT;
|
||||
uint32_t m_texture = 0;
|
||||
uint32_t m_program = 0;
|
||||
int m_sizeUniform = -1;
|
||||
int m_cropUniform = -1;
|
||||
int m_alphaUniform = -1;
|
||||
int m_sourceUniform = -1;
|
||||
|
||||
bool m_randomTransition = false; // wallTransition == Random
|
||||
QString m_transitionFile; // the transition stamped onto new layers
|
||||
bool m_transitionDirty = false;
|
||||
QHash<QString, TransProgram>
|
||||
m_transPrograms; // compiled programs, keyed by shader
|
||||
TransProgram
|
||||
m_neutralProgram; // fade program for identity copies (seed/base/final)
|
||||
QVector<int>
|
||||
m_transitionUses; // usage counts, parallel to the transition list
|
||||
QString m_lastTransition; // last random pick, so it is never repeated
|
||||
|
||||
uint32_t m_captureFbo = 0;
|
||||
uint32_t m_captureTex = 0;
|
||||
QSize m_captureSize;
|
||||
|
||||
uint32_t m_baseFbo = 0;
|
||||
uint32_t m_baseTex = 0;
|
||||
QSize m_baseSize;
|
||||
bool m_baseReady = false;
|
||||
|
||||
uint32_t m_accumFbo = 0;
|
||||
uint32_t m_accumA = 0;
|
||||
uint32_t m_accumB = 0;
|
||||
QSize m_accumSize;
|
||||
|
||||
std::vector<TransitionLayer> m_transitions; // oldest .. newest
|
||||
|
||||
bool m_needCaptureBase = false;
|
||||
QImage m_baseImage; // old settled image, for the base capture crop
|
||||
QVariantMap m_baseCrops; // old settled crop map, for the base capture crop
|
||||
bool m_baseIsVideo = false; // old settled frame was a live video
|
||||
bool m_baseIsBlack = false; // shell start / first load: fade in from black
|
||||
bool m_collapseVideo =
|
||||
false; // video pushed mid-stack: bake older into base
|
||||
bool m_promoteOldest = false; // stack over the cap: promote oldest to base
|
||||
bool m_newestDone = false; // newest layer finished: settle into base
|
||||
|
||||
static constexpr int kMaxTransitions = 4;
|
||||
|
||||
uint32_t m_videoProgram = 0;
|
||||
uint32_t m_vao = 0;
|
||||
int m_videoSizeUniform = -1;
|
||||
int m_videoSrcSizeUniform = -1;
|
||||
int m_videoCropUniform = -1;
|
||||
int m_videoAlphaUniform = -1;
|
||||
int m_videoLumaUniform = -1;
|
||||
int m_videoChromaUniform = -1;
|
||||
int m_videoMatrixUniform = -1;
|
||||
int m_videoRangeUniform = -1;
|
||||
int m_videoChromaOffUniform = -1;
|
||||
|
||||
#ifdef ZHAVE_VIDEO
|
||||
std::unique_ptr<VideoPlayer> m_player;
|
||||
bool m_usePlayer = true;
|
||||
#endif
|
||||
|
||||
std::vector<uint32_t> m_orphanTextures;
|
||||
|
||||
QList<WallpaperSurface*> m_surfaces;
|
||||
|
||||
std::thread m_thread;
|
||||
mutable std::recursive_mutex m_mutex;
|
||||
wl_event_queue* m_queue = nullptr;
|
||||
|
||||
int m_wake[2] = {-1, -1};
|
||||
|
||||
bool m_stop = false;
|
||||
bool m_drawing = false;
|
||||
|
||||
bool started = false;
|
||||
|
||||
bool m_forceDecode = false;
|
||||
bool m_imageChanged = false;
|
||||
|
||||
QImage m_posterImage;
|
||||
uint32_t m_posterTex = 0;
|
||||
QString m_posterPath;
|
||||
bool m_posterReady = false;
|
||||
bool m_posterLoading = false;
|
||||
bool m_posterChanged = false;
|
||||
};
|
||||
|
||||
} // namespace ZShell::internal
|
||||
Reference in New Issue
Block a user