257 lines
9.3 KiB
C++
257 lines
9.3 KiB
C++
#pragma once
|
||
#include <array>
|
||
#include <atomic>
|
||
#include <cstdint>
|
||
#include <qlinkedlist.h>
|
||
#include <QImage>
|
||
#include <QRegion>
|
||
#include <qscreen.h>
|
||
#include "GlobalTypes.h"
|
||
namespace YSG {
|
||
#define INIT_GET(className) className##Private* privateData = d(); \
|
||
className##RenderState* renderState = reinterpret_cast<className##RenderState*>(d()->getState(src));
|
||
struct TempData {
|
||
virtual ~TempData() = default;
|
||
};
|
||
struct RenderState {
|
||
virtual ~RenderState() = default;
|
||
std::uint64_t version = 0;
|
||
RenderData* dPtr{};
|
||
SRC src();
|
||
};
|
||
struct RenderData {
|
||
SpinLock mBufferLock;
|
||
RenderAble* qPtr{};
|
||
bool mRenderStart = false;
|
||
RenderState* getState(SRC src) const {
|
||
switch (src) {
|
||
case SRC::Render: {
|
||
return mRenderState;
|
||
}
|
||
case SRC::Cache: {
|
||
return mRenderStateCache;
|
||
}
|
||
case SRC::Auto: {
|
||
return mRenderStart ? mRenderState : mRenderStateCache;
|
||
}
|
||
}
|
||
qDebug() << "RenderState* RenderData::getState(SRC src) error! 不存在的枚举值" << static_cast<int>(src);
|
||
return nullptr;
|
||
}
|
||
RenderState *mRenderState{}, *mRenderStateCache{};
|
||
TempData *mTempData{}, *mTempDataCache{};
|
||
protected:
|
||
virtual void loadCache() = 0;
|
||
virtual RenderState* renderState() = 0;
|
||
virtual RenderState* renderStateCache() = 0;
|
||
virtual TempData* tempData() = 0;
|
||
virtual TempData* tempDataCache() = 0;
|
||
virtual ~RenderData() {
|
||
delete mTempData;
|
||
delete mTempDataCache;
|
||
delete mRenderState;
|
||
delete mRenderStateCache;
|
||
}
|
||
virtual void draw(QPainter* painter) {}
|
||
virtual void prepareData() {
|
||
SpinLockGuard g(&mBufferLock);
|
||
//qDebug() << "qPtr->mObjectName " << qPtr->mObjectName;
|
||
loadCache();
|
||
}
|
||
virtual bool selectTest(const QPointF& pos) {
|
||
return false;
|
||
}
|
||
virtual void plotEvent(QEvent* event) {}
|
||
virtual void mousePressEvent(QMouseEvent* event) {}
|
||
virtual void mouseMoveEvent(QMouseEvent* event) {}
|
||
virtual void mouseReleaseEvent(QMouseEvent* event) {}
|
||
virtual void setHoverState(const QPoint& pos, bool active) {}
|
||
virtual void keyPressEvent(QKeyEvent* event) {}
|
||
virtual void keyReleaseEvent(QKeyEvent* event) {}
|
||
virtual void firstResizeEvent(QResizeEvent* event) {}
|
||
virtual void resizeEvent(QResizeEvent* event) {}
|
||
virtual void wheelEvent(QWheelEvent* event) {}
|
||
friend struct RenderAble;
|
||
};
|
||
struct BaseRenderData : RenderData {
|
||
RenderState* renderState() override {
|
||
return nullptr;
|
||
}
|
||
RenderState* renderStateCache() override {
|
||
return nullptr;
|
||
}
|
||
TempData* tempData() override {
|
||
return nullptr;
|
||
}
|
||
TempData* tempDataCache() override {
|
||
return nullptr;
|
||
}
|
||
void loadCache() override {}
|
||
};
|
||
class Plot;
|
||
struct LIB_DECL RenderEditGuard {
|
||
explicit RenderEditGuard(RenderData* data);
|
||
~RenderEditGuard();
|
||
RenderData* mData{};
|
||
};
|
||
struct RenderAble {
|
||
enum class JobState {
|
||
Idle,
|
||
Queued,
|
||
Running
|
||
};
|
||
struct ColorBuffer {
|
||
std::uint64_t version = 0;
|
||
QImage image;
|
||
QRegion dirtyRegion;
|
||
};
|
||
struct RenderPipeline {
|
||
SpinLock colorLock;
|
||
std::array<ColorBuffer, 3> colorBuffers;
|
||
ColorBuffer* frontColor{};
|
||
ColorBuffer* readyColor{};
|
||
ColorBuffer* renderColor{};
|
||
std::atomic<std::uint64_t> editStateVersion{1};
|
||
std::uint64_t renderStateVersion = 0;
|
||
JobState jobState = JobState::Idle;
|
||
bool paintRequestPending = false;
|
||
QRegion dirtyRegion;
|
||
RenderPipeline();
|
||
void markEditState();
|
||
bool hasNewState() const;
|
||
ColorBuffer* currentRenderColor() const;
|
||
QRegion publishRenderColor();
|
||
ColorBuffer* consumeReadyColor();
|
||
};
|
||
virtual RenderData* createRenderData() {
|
||
return new BaseRenderData;
|
||
}
|
||
virtual RenderState* createRenderState() {
|
||
return new RenderState;
|
||
}
|
||
virtual TempData* createTempData() {
|
||
return new TempData;
|
||
}
|
||
virtual void init(Plot* plot, QString layerName = "");
|
||
virtual void draw(QPainter* painter) {
|
||
dPtr->draw(painter);
|
||
}
|
||
virtual void prepareData() {
|
||
dPtr->prepareData();
|
||
}
|
||
virtual bool selectTest(const QPointF& pos) {
|
||
return dPtr->selectTest(pos);
|
||
}
|
||
virtual void plotEvent(QEvent* event) {
|
||
dPtr->plotEvent(event);
|
||
}
|
||
virtual void mousePressEvent(QMouseEvent* event) {
|
||
dPtr->mousePressEvent(event);
|
||
}
|
||
virtual void mouseMoveEvent(QMouseEvent* event) {
|
||
dPtr->mouseMoveEvent(event);
|
||
}
|
||
virtual void mouseReleaseEvent(QMouseEvent* event) {
|
||
dPtr->mouseReleaseEvent(event);
|
||
}
|
||
virtual void setHoverState(const QPoint& pos, bool active) {
|
||
dPtr->setHoverState(pos, active);
|
||
}
|
||
virtual void keyPressEvent(QKeyEvent* event) {
|
||
dPtr->keyPressEvent(event);
|
||
}
|
||
virtual void keyReleaseEvent(QKeyEvent* event) {
|
||
dPtr->keyReleaseEvent(event);
|
||
}
|
||
virtual void firstResizeEvent(QResizeEvent* event) {
|
||
dPtr->firstResizeEvent(event);
|
||
}
|
||
virtual void resizeEvent(QResizeEvent* event) {
|
||
dPtr->resizeEvent(event);
|
||
}
|
||
virtual void wheelEvent(QWheelEvent* event) {
|
||
dPtr->wheelEvent(event);
|
||
};
|
||
static bool version_newer(std::uint64_t a, std::uint64_t b) {
|
||
return static_cast<std::int64_t>(a - b) > 0;
|
||
}
|
||
void markStateDirty();
|
||
QString mObjectName;
|
||
RenderData* dPtr{};
|
||
Plot* mPlot{};
|
||
[[nodiscard]] bool ok() const;
|
||
bool mPrepared = false;
|
||
// 这里面可以预先准备数据用来同步
|
||
virtual ~RenderAble();
|
||
virtual bool select(QPointF pos) {
|
||
return false;
|
||
}
|
||
bool mVisable = true;
|
||
RenderAble* mParent{};
|
||
QVector<RenderAble*> mBeRelyList;
|
||
bool dectCycleRely();
|
||
private:
|
||
bool hasCycleRely(RenderAble* node, QSet<RenderAble*>& visited, QSet<RenderAble*>& recursionStack, QVector<RenderAble*>& currentPath);
|
||
};
|
||
#define Q_Ptr2(ClassName) \
|
||
ClassName##Private* d() {return reinterpret_cast<ClassName##Private*>(dPtr);} \
|
||
RenderData* createRenderData() override; \
|
||
RenderState* createRenderState() override; \
|
||
TempData* createTempData() override; \
|
||
protected: \
|
||
ClassName(); \
|
||
friend struct ClassName##Private; \
|
||
friend struct ClassName##RenderState; \
|
||
friend struct ClassName##TempData; \
|
||
public:
|
||
#define Q_Ptr(ClassName) \
|
||
ClassName(); \
|
||
ClassName##Private* d() {return reinterpret_cast<ClassName##Private*>(dPtr);} \
|
||
RenderData* createRenderData() override; \
|
||
RenderState* createRenderState() override; \
|
||
TempData* createTempData() override;
|
||
#define Q_Ptr_cpp(ClassName) \
|
||
ClassName::ClassName() { \
|
||
dPtr = new ClassName##Private; \
|
||
mObjectName = #ClassName; \
|
||
} \
|
||
RenderData* ClassName::createRenderData() {return new ClassName##Private;} \
|
||
RenderState* ClassName::createRenderState() {return new ClassName##RenderState;} \
|
||
TempData* ClassName::createTempData() {return new ClassName##TempData;}
|
||
#define D_Ptr_3(ClassName) \
|
||
ClassName##RenderState* renderState() override {return reinterpret_cast<ClassName##RenderState*>(mRenderState);} \
|
||
ClassName##RenderState* renderStateCache() override {return reinterpret_cast<ClassName##RenderState*>(mRenderStateCache);} \
|
||
ClassName##TempData* tempData() override {return reinterpret_cast<ClassName##TempData*>(mTempData);} \
|
||
ClassName##TempData* tempDataCache() override {return reinterpret_cast<ClassName##TempData*>(mTempDataCache);} \
|
||
friend class ClassName; \
|
||
void loadCache() override { \
|
||
*renderState() = *renderStateCache(); \
|
||
std::swap(mTempData, mTempDataCache); \
|
||
if(!mRenderStart) mRenderStart = true; \
|
||
}
|
||
#define D_Ptr(ClassName) \
|
||
ClassName* q() {return reinterpret_cast<ClassName*>(qPtr);} \
|
||
ClassName##RenderState* renderState() override {return reinterpret_cast<ClassName##RenderState*>(mRenderState);} \
|
||
ClassName##RenderState* renderStateCache() override {return reinterpret_cast<ClassName##RenderState*>(mRenderStateCache);} \
|
||
ClassName##TempData* tempData() override {return reinterpret_cast<ClassName##TempData*>(mTempData);} \
|
||
ClassName##TempData* tempDataCache() override {return reinterpret_cast<ClassName##TempData*>(mTempDataCache);} \
|
||
friend class ClassName; \
|
||
void loadCache() override { \
|
||
*renderState() = *renderStateCache(); \
|
||
std::swap(mTempData, mTempDataCache); \
|
||
if(!mRenderStart) mRenderStart = true; \
|
||
}
|
||
#define D_Ptr2(ClassName) \
|
||
ClassName* q() {return reinterpret_cast<ClassName*>(qPtr);} \
|
||
ClassName##RenderState* renderState() override {return reinterpret_cast<ClassName##RenderState*>(mRenderState);} \
|
||
ClassName##RenderState* renderStateCache() override {return reinterpret_cast<ClassName##RenderState*>(mRenderStateCache);} \
|
||
ClassName##TempData* tempData() override {return reinterpret_cast<ClassName##TempData*>(mTempData);} \
|
||
ClassName##TempData* tempDataCache() override {return reinterpret_cast<ClassName##TempData*>(mTempDataCache);} \
|
||
friend class ClassName;
|
||
#define INIT_SET(className) className##Private* pd = d(); \
|
||
className##RenderState* sc = pd->renderStateCache();\
|
||
className##TempData* td = pd->tempDataCache(); \
|
||
SpinLockGuard _guard(&pd->mBufferLock); \
|
||
RenderEditGuard _editGuard(pd);
|
||
}
|