#include "RenderAble.h" #include #include "base/Plot.h" #include "Axis/AbsAxis.h" #include "plottable/HoverInfo.h" #include "psc_global_include/export.h" #include "psc_global_include/Fail_Fast.h" namespace YSG { QDebug operator<<(QDebug debug, const Range& range) { QDebugStateSaver saver(debug); // 保存当前的 qDebug 状态 debug.nospace() << "Range(" << range.lower << ", " << range.upper << ")"; return debug; } RenderAble::RenderPipeline::RenderPipeline() { colorControl.set_stats(&colorBufferStats); colorControl.reset(); } void RenderAble::RenderPipeline::markEditState() { editStateVersion.fetch_add(1, std::memory_order_release); } bool RenderAble::RenderPipeline::hasNewState() const { return RenderAble::version_newer(editStateVersion.load(std::memory_order_acquire), renderStateVersion); } RenderAble::ColorBuffer* RenderAble::RenderPipeline::colorByIndex(std::uint8_t index) { return &colorBuffers[index]; } RenderAble::ColorBuffer* RenderAble::RenderPipeline::colorByRole(std::uint8_t role) { return colorByIndex(colorControl.read_view()[role]); } RenderAble::ColorBufferLease RenderAble::RenderPipeline::waitRenderColor() { auto lease = colorControl.wait_mark_use_role(Color_Render); return {colorByIndex(lease.index), lease}; } RenderAble::ColorBufferLease RenderAble::RenderPipeline::waitFrontColor() { auto lease = colorControl.wait_mark_use_role(Color_Front); return {colorByIndex(lease.index), lease}; } RenderAble::ColorBufferLease RenderAble::RenderPipeline::tryFrontColor() { auto record = colorControl.try_mark_use_role(Color_Front); if(record.result != Triple_Buffer_Result::Success) { return {}; } return {colorByIndex(record.lease.index), record.lease}; } void RenderAble::RenderPipeline::unmarkColor(ColorBufferLease lease) { colorControl.unmark_use(lease.lease); } Plot_Buffer_Acquire_Mode RenderAble::bufferAcquireMode() const { return dPtr->bufferAcquireMode(); } void RenderAble::setBufferAcquireMode(Plot_Buffer_Acquire_Mode mode) { dPtr->setBufferAcquireMode(mode); } bool RenderAble::independentPixelCache() const { return dPtr->independentPixelCache(); } void RenderAble::setIndependentPixelCache(bool enabled) { dPtr->setIndependentPixelCache(enabled); } QRegion RenderAble::RenderPipeline::publishRenderColor() { colorControl.wait_swap_role(Color_Ready, Color_Render, [this](const Triple_Buffer_View& view) { auto render = colorByIndex(view[Color_Render]); auto ready = colorByIndex(view[Color_Ready]); return RenderAble::version_newer(render->version.load(std::memory_order_acquire), ready->version.load(std::memory_order_acquire)); }); auto view = colorControl.read_view(); auto ready = colorByIndex(view[Color_Ready]); auto front = colorByIndex(view[Color_Front]); if(RenderAble::version_newer(ready->version.load(std::memory_order_acquire), front->version.load(std::memory_order_acquire)) && !paintRequestPending.exchange(true, std::memory_order_acq_rel)) { return ready->dirtyRegion; } return {}; } RenderAble::ColorBufferLease RenderAble::RenderPipeline::consumeReadyColor(Triple_Buffer_Mode mode) { auto canSwap = [this](const Triple_Buffer_View& view) { auto ready = colorByIndex(view[Color_Ready]); auto front = colorByIndex(view[Color_Front]); return RenderAble::version_newer(ready->version.load(std::memory_order_acquire), front->version.load(std::memory_order_acquire)); }; if(mode == Triple_Buffer_Mode::Wait) { colorControl.wait_swap_role(Color_Front, Color_Ready, canSwap); } else { colorControl.try_swap_role(Color_Front, Color_Ready, canSwap); } paintRequestPending.store(false, std::memory_order_release); if(mode == Triple_Buffer_Mode::Wait) { return waitFrontColor(); } return tryFrontColor(); } RenderEditGuard::RenderEditGuard(RenderData* data, Triple_Buffer_Lease lease) : mData(data), mLease(lease) { } RenderEditGuard::~RenderEditGuard() { if(!mData) return; ++mData->stateByIndex(mLease.index)->version; if(mData->qPtr) mData->qPtr->markRenderDirty(); mData->unmarkState(mLease); } RenderInputGuard::RenderInputGuard(RenderData* data, Triple_Buffer_Lease lease) : mData(data), mLease(lease) { } RenderInputGuard::~RenderInputGuard() { if(!mData) return; mData->markInputDirty(mLease); mData->mInputControl.unmark_use(mLease); } void RenderData::markInputDirty(Triple_Buffer_Lease lease, bool notifyRender) { InputBufferSlot& slot = inputSlotByIndex(lease.index); slot.version = ++mInputVersion; slot.pending = true; if(notifyRender && qPtr) qPtr->markRenderDirty(); } void RenderAble::init(Plot* plot, QString layerName) { if(layerName.isEmpty()) { layerName = plot->mDefaultLayerName; } plot->mLayerMap[layerName]->mRenderAbles.append(this); mPlot = plot; if(!dPtr) dPtr = createRenderData(); dPtr->setBufferAcquireMode(plot->renderAbleBufferAcquireMode()); dPtr->clearStateBuffers(); dPtr->clearInputBuffers(); dPtr->mStateBuffers[State_Edit] = createRenderState(); dPtr->mStateBuffers[State_Ready] = createRenderState(); dPtr->mStateBuffers[State_Render] = createRenderState(); dPtr->mInputBuffers[Input_Edit].data = createInputData(); dPtr->mInputBuffers[Input_Ready].data = createInputData(); dPtr->mInputBuffers[Input_Render].data = createInputData(); for(RenderState* state : dPtr->mStateBuffers) { state->dPtr = dPtr; } dPtr->qPtr = this; dPtr->mStateBuffers[State_Edit]->version = 1; if(mPlot) mPlot->markRenderStateDirty(); } void RenderAble::markStateDirty() { if(dPtr) { auto lease = dPtr->mStateControl.wait_mark_use_role(State_Edit); ++dPtr->stateByIndex(lease.index)->version; dPtr->mStateControl.unmark_use(lease); } markRenderDirty(); } void RenderAble::markRenderDirty() { if(!mPlot) return; if(dPtr && dPtr->independentPixelCache()) { dPtr->markPixelDirty(); mPlot->markIndependentRenderDirty(this); return; } mPlot->markRenderStateDirty(); } bool RenderAble::ok() const { return dPtr->mRenderStart && mPlot && !mPlot->mFirstResize && !mPlot->mFirstPrepareData; } RenderAble::~RenderAble(){ } bool RenderAble::dectCycleRely() { QQueue queue; queue.enqueue(this); while (!queue.isEmpty()) { RenderAble* current = queue.dequeue(); QSet visited; QSet recursionStack; QVector path; bool has = hasCycleRely(current, visited, recursionStack, path); if(has){ return true; } } qDebug() << this << " 检测成功!"; return false; } bool RenderAble::hasCycleRely(RenderAble* node, QSet& visited, QSet& recursionStack, QVector& currentPath) { if (!node) return false; if (recursionStack.contains(node)) { // 节点已经在当前递归路径中,检测到循环 qDebug() << "Cycle detected in path:"; // 打印循环依赖链 for (RenderAble* n : currentPath) { qDebug() << n->mObjectName << "(" << n << ")->"; } qDebug() << node; // 打印形成循环的节点 return true; } if (visited.contains(node)) { // 节点已经被处理过,无需再次处理 return false; } // 标记当前节点为已访问 visited.insert(node); // 将当前节点标记为递归路径中的节点 recursionStack.insert(node); // 记录当前节点在路径中 currentPath.append(node); // 递归检查所有子节点 for (RenderAble* child : node->mBeRelyList) { if (hasCycleRely(child, visited, recursionStack, currentPath)) { return true; } } // 从递归路径中移除当前节点 recursionStack.remove(node); // 从路径中移除当前节点 currentPath.removeLast(); return false; } QVector getTurboColorGradient() { QVector colors; // std::cout << "11111111111111111111111111111111111111" << std::endl; // for (auto s : QDir(":/").entryList()) // { // std::cout << "QDir=============" << s.toStdString() << std::endl; // } // // std::cout << "11111111111111111111111111111111111111" << std::endl; // QFile file(":/turbo.colorMap"); if (!file.open(QIODevice::ReadOnly)) { std::ostringstream oss; oss << file.errorString().toStdString() << " getTurboColorGradient2: Failed to open file" << LOG_POS_SIMPLE << std::endl; Psc::fail_fast(oss.str()); return colors; // 返回一个空的 std::vector } QByteArray fileData = file.readAll(); file.close(); // 检查文件内容 if (fileData.size() != 768) { qDebug() << "getTurboColorGradient2: File size is not as expected (768 bytes), got" << fileData.size(); return colors; // 返回一个空的 std::vector } // 确保每个颜色有 3 个字节 (RGB),总共有 256 个颜色 colors.reserve(256); for (int i = 0; i < 256; ++i) { uchar r = fileData[i * 3]; uchar g = fileData[i * 3 + 1]; uchar b = fileData[i * 3 + 2]; colors.push_back(qRgb(r, g, b)); } return colors; } SRC RenderState::src() { auto view = dPtr->mStateControl.read_view(); for(std::uint8_t role = State_Edit; role <= State_Render; ++role) { if(dPtr->mStateBuffers[view[role]] == this) return static_cast(role); } return SRC::Edit; } }