协程架构重构成功, 下一步准备指针交换 无锁化重构
This commit is contained in:
+115
-45
@@ -1,6 +1,8 @@
|
||||
#include "Plot_p.h"
|
||||
#include "PerformanceShower_p.h"
|
||||
#include "Global.h"
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
|
||||
namespace YSG {
|
||||
class PrePareMutiDataMutexGuard {
|
||||
@@ -31,7 +33,9 @@ namespace YSG {
|
||||
g->mTimerThreadMap[threadName] = newThread;
|
||||
newThread->setObjectName(threadName);
|
||||
}
|
||||
g->mTimerThreadMap[threadName]->mPlots.append(this);
|
||||
TimerThread* thread = g->mTimerThreadMap[threadName];
|
||||
thread->mPlots.append(this);
|
||||
d->mTimerThread = thread;
|
||||
}
|
||||
|
||||
Plot::Plot(){
|
||||
@@ -57,12 +61,12 @@ namespace YSG {
|
||||
}
|
||||
|
||||
Plot::~Plot() {
|
||||
delete d->mRenderBuffer;
|
||||
pauseRender();
|
||||
delete d;
|
||||
}
|
||||
|
||||
bool Plot::isRendering() {
|
||||
if(!d->mTimer) return false;
|
||||
return d->mTimer->isActive();
|
||||
return d->mRenderEnabled;
|
||||
}
|
||||
|
||||
void Plot::startRender(int refreshTimesPreSecond) {
|
||||
@@ -71,36 +75,57 @@ namespace YSG {
|
||||
}
|
||||
|
||||
void Plot::startRender() const {
|
||||
if(d->mTimer) QMetaObject::invokeMethod(d->mTimer, "start", Qt::AutoConnection, Q_ARG(int, qRound(1000.0 / (double) d->mRefreshTimesPreSecond)));
|
||||
d->mRenderEnabled = true;
|
||||
if(!d->mTimerThread) return;
|
||||
Plot* self = const_cast<Plot*>(this);
|
||||
d->mTimerThread->post([self]() {
|
||||
PlotPrivate* d = self->d;
|
||||
if(d->mRenderTimer) {
|
||||
d->mRenderTimer->cancel();
|
||||
self->scheduleRenderTimer();
|
||||
}
|
||||
self->submitRender();
|
||||
});
|
||||
}
|
||||
|
||||
void Plot::pauseRender() const {
|
||||
if(d->mTimer) QMetaObject::invokeMethod(d->mTimer, "stop", Qt::AutoConnection);
|
||||
d->mRenderEnabled = false;
|
||||
if(!d->mTimerThread) return;
|
||||
Plot* self = const_cast<Plot*>(this);
|
||||
d->mTimerThread->post([self]() {
|
||||
PlotPrivate* d = self->d;
|
||||
if(d->mRenderTimer) {
|
||||
d->mRenderTimer->cancel();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Plot::paintEvent(QPaintEvent* event) {
|
||||
SpinLockGuard guard(&d->mBufferLock);
|
||||
Q_UNUSED(event)
|
||||
QPainter painter(this);
|
||||
painter.drawPixmap(QPoint(0, 0), d->mPaintBuffer);
|
||||
//painter.drawImage(QPoint(0, 0), d->mPaintBuffer);
|
||||
RenderAble::ColorBuffer* color = d->mPipeline.consumeReadyColor();
|
||||
if(color && !color->image.isNull()) painter.drawImage(QPoint(0, 0), color->image);
|
||||
else painter.fillRect(rect(), d->mBackground);
|
||||
painter.end();
|
||||
if(d->mShower) d->mShower->counterIncrease("plot paint");
|
||||
d->mPlotState.storeRelease(PlotPrivate::NeedToRender);
|
||||
}
|
||||
void Plot::render() {
|
||||
if (mFirstResize) return;
|
||||
if (d->mPlotState.loadAcquire() != PlotPrivate::NeedToRender) return;
|
||||
if(!d->mRenderBuffer) return;
|
||||
SpinLockGuard renderGuard(&d->mRenderLock);
|
||||
if(d->mRenderBuffer->isNull()) return;
|
||||
|
||||
submitRender();
|
||||
}
|
||||
void Plot::submitRender() {
|
||||
if(mFirstResize) return;
|
||||
if(!d->mRenderEnabled) return;
|
||||
QSize renderSize = d->mRenderSize;
|
||||
if(renderSize.width() <= 0 || renderSize.height() <= 0) return;
|
||||
RenderAble::RenderPipeline& pipeline = d->mPipeline;
|
||||
if(pipeline.jobState != RenderAble::JobState::Idle) return;
|
||||
if(!pipeline.hasNewState()) return;
|
||||
pipeline.jobState = RenderAble::JobState::Queued;
|
||||
pipeline.renderStateVersion = pipeline.editStateVersion.load(std::memory_order_acquire);
|
||||
if(d->mShower) {
|
||||
d->mShower->counterIncrease("渲染帧率");
|
||||
d->mShower->mInfos["interval"] = QString("渲染:%1, global:%2").arg(d->mTimer->interval()).arg(Global::instance()->mInterval);
|
||||
d->mShower->mInfos["interval"] = QString("渲染:%1, global:%2").arg(qRound(1000.0 / (double)d->mRefreshTimesPreSecond)).arg(Global::instance()->mInterval);
|
||||
}
|
||||
Cacl renderData("整体渲染耗时: %1 avg: %2", d->mShower);
|
||||
QPainter painter(d->mRenderBuffer);
|
||||
painter.fillRect(rect(), d->mBackground);
|
||||
{
|
||||
Cacl prepareData("准备数据耗时: %1 avg: %2", d->mShower);
|
||||
SpinLockGuard prepareDataLock(&d->mPrepareDataLock);
|
||||
@@ -125,10 +150,46 @@ namespace YSG {
|
||||
}
|
||||
if(mFirstPrepareData) mFirstPrepareData = false;
|
||||
}
|
||||
|
||||
|
||||
for(Layer* layer : mLayerList) {
|
||||
for(RenderAble* able : layer->mRenderAbles) {
|
||||
able->mPrepared = false;
|
||||
}
|
||||
}
|
||||
RenderAble::ColorBuffer* color = pipeline.currentRenderColor();
|
||||
QColor background = d->mBackground;
|
||||
std::uint64_t version = pipeline.renderStateVersion;
|
||||
TimerThread* thread = d->mTimerThread;
|
||||
pipeline.jobState = RenderAble::JobState::Running;
|
||||
if(thread) {
|
||||
thread->postCpu([this, color, renderSize, background, version, thread]() {
|
||||
renderColor(color, renderSize, background, version);
|
||||
thread->post([this]() {
|
||||
finishRender();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
renderColor(color, renderSize, background, version);
|
||||
finishRender();
|
||||
}
|
||||
}
|
||||
void Plot::finishRender() {
|
||||
RenderAble::RenderPipeline& pipeline = d->mPipeline;
|
||||
QRegion updateRegion = pipeline.publishRenderColor();
|
||||
pipeline.jobState = RenderAble::JobState::Idle;
|
||||
if(!updateRegion.isEmpty()) requestUpdate(updateRegion);
|
||||
if(d->mShower) d->mShower->refresh();
|
||||
if(pipeline.hasNewState()) submitRender();
|
||||
}
|
||||
void Plot::renderColor(RenderAble::ColorBuffer* color, QSize size, QColor background, std::uint64_t version) {
|
||||
Cacl renderData("整体渲染耗时: %1 avg: %2", d->mShower);
|
||||
if(color->image.size() != size || color->image.format() != QImage::Format_ARGB32) {
|
||||
color->image = QImage(size, QImage::Format_ARGB32);
|
||||
}
|
||||
color->image.detach();
|
||||
color->image.fill(background);
|
||||
QPainter painter(&color->image);
|
||||
{
|
||||
Cacl prepareData("draw耗时: %1 avg: %2", d->mShower);
|
||||
Cacl drawData("draw耗时: %1 avg: %2", d->mShower);
|
||||
for(Layer* layer : mLayerList) {
|
||||
for(RenderAble* cur : layer->mRenderAbles) {
|
||||
if(!cur->mVisable) continue;
|
||||
@@ -136,23 +197,35 @@ namespace YSG {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
SpinLockGuard bufferGuard(&d->mBufferLock);
|
||||
// d->mPaintBuffer = *d->mRenderBuffer;
|
||||
d->mPaintBuffer = QPixmap::fromImage(*d->mRenderBuffer);
|
||||
d->mPlotState.storeRelease(PlotPrivate::NeedToPaint);
|
||||
}
|
||||
|
||||
for(Layer* layer : mLayerList) {
|
||||
for(RenderAble* able : layer->mRenderAbles) {
|
||||
able->mPrepared = false;
|
||||
}
|
||||
}
|
||||
if(d->mShower) {
|
||||
d->mShower->refresh();
|
||||
}
|
||||
painter.end();
|
||||
color->version = version;
|
||||
color->dirtyRegion = QRegion(QRect(QPoint(0, 0), size));
|
||||
}
|
||||
void Plot::scheduleRenderTimer() {
|
||||
if(!d->mRenderTimer || !d->mRenderEnabled) return;
|
||||
int interval = std::max(1, qRound(1000.0 / (double)d->mRefreshTimesPreSecond));
|
||||
d->mRenderTimer->expires_after(std::chrono::milliseconds(interval));
|
||||
d->mRenderTimer->async_wait([this](const asio::error_code& error) {
|
||||
if(error) return;
|
||||
submitRender();
|
||||
scheduleRenderTimer();
|
||||
});
|
||||
}
|
||||
void Plot::markRenderStateDirty() {
|
||||
d->mPipeline.markEditState();
|
||||
requestRender();
|
||||
}
|
||||
void Plot::requestRender() {
|
||||
if(!d->mTimerThread) return;
|
||||
d->mTimerThread->post([this]() {
|
||||
submitRender();
|
||||
});
|
||||
}
|
||||
void Plot::requestUpdate(const QRegion& region) {
|
||||
QTimer::singleShot(0, this, [this, region]() {
|
||||
if(region.isEmpty()) update();
|
||||
else update(region);
|
||||
});
|
||||
}
|
||||
|
||||
QColor Plot::backgroundColor() {
|
||||
@@ -169,12 +242,8 @@ namespace YSG {
|
||||
case QEvent::Resize: {
|
||||
auto e = reinterpret_cast<QResizeEvent*>(event);
|
||||
{
|
||||
//qDebug() << resizeEvent->size();
|
||||
SpinLockGuard guard(&d->mRenderLock);
|
||||
delete d->mRenderBuffer;
|
||||
//d->mRenderBuffer = new QPixmap(e->size());
|
||||
d->mRenderBuffer = new QImage(e->size().width(), e->size().height(), QImage::Format_ARGB32);
|
||||
|
||||
d->mRenderSize = e->size();
|
||||
if(mFirstResize) {
|
||||
for(Layer* layer : mLayerList) {
|
||||
for(RenderAble* able : layer->mRenderAbles) {
|
||||
@@ -189,6 +258,7 @@ namespace YSG {
|
||||
}
|
||||
if(mFirstResize) mFirstResize = false;
|
||||
}
|
||||
markRenderStateDirty();
|
||||
break;
|
||||
}
|
||||
case QEvent::Show: {
|
||||
|
||||
Reference in New Issue
Block a user