feat: add wallpaper transitions, store crop in database per-wallpaper, move CUDA context creation to async thread
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include <QImage>
|
||||
#include <QHash>
|
||||
#include <QList>
|
||||
#include <QElapsedTimer>
|
||||
#include <QRectF>
|
||||
@@ -15,6 +16,7 @@
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QVariantMap>
|
||||
#include <QVector>
|
||||
#include <QtQml/qqml.h>
|
||||
#include <qtmetamacros.h>
|
||||
#include <atomic>
|
||||
@@ -28,6 +30,7 @@
|
||||
#include <wayland-client-protocol.h>
|
||||
|
||||
#include "wallpapersurface.hpp"
|
||||
#include "config/enums.hpp"
|
||||
|
||||
struct mpv_handle;
|
||||
struct mpv_render_context;
|
||||
@@ -131,8 +134,76 @@ class WallpaperService : public QObject {
|
||||
|
||||
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();
|
||||
@@ -150,8 +221,14 @@ class WallpaperService : public QObject {
|
||||
|
||||
[[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);
|
||||
@@ -187,7 +264,6 @@ class WallpaperService : public QObject {
|
||||
|
||||
bool m_isVideo = false;
|
||||
bool m_videoReload = false;
|
||||
bool m_previousVideo = false;
|
||||
mpv_handle* m_mpv = nullptr;
|
||||
mpv_render_context* m_mpvRender = nullptr;
|
||||
uint32_t m_blackTex = 0;
|
||||
@@ -223,6 +299,45 @@ class WallpaperService : public QObject {
|
||||
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;
|
||||
@@ -240,14 +355,7 @@ class WallpaperService : public QObject {
|
||||
bool m_usePlayer = true;
|
||||
#endif
|
||||
|
||||
QImage m_previousImage;
|
||||
QVariantMap m_previousCrops;
|
||||
uint32_t m_previousTexture = 0;
|
||||
std::vector<uint32_t> m_orphanTextures;
|
||||
bool m_fading = false;
|
||||
bool m_fadeClockStarted = false;
|
||||
bool m_firstFadeDone = false;
|
||||
QElapsedTimer m_fadeTimer;
|
||||
|
||||
QList<WallpaperSurface*> m_surfaces;
|
||||
|
||||
@@ -264,6 +372,13 @@ class WallpaperService : public QObject {
|
||||
|
||||
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