From 706fe2f3655210467d329c9a8c98f5821fb02c60 Mon Sep 17 00:00:00 2001 From: Sergiusz Bazanski Date: Thu, 26 Jul 2018 17:26:26 +0100 Subject: gui: refactor FPGAViewWidget slightly --- gui/fpgaviewwidget.cc | 272 ++++++++++++++++++++++++++------------------------ gui/fpgaviewwidget.h | 15 +-- 2 files changed, 150 insertions(+), 137 deletions(-) (limited to 'gui') diff --git a/gui/fpgaviewwidget.cc b/gui/fpgaviewwidget.cc index e9096bf4..2211c93b 100644 --- a/gui/fpgaviewwidget.cc +++ b/gui/fpgaviewwidget.cc @@ -311,69 +311,49 @@ void FPGAViewWidget::initializeGL() 0.0); } -void FPGAViewWidget::drawDecal(LineShaderData &out, const DecalXY &decal) +void FPGAViewWidget::drawGraphicElement(LineShaderData &out, const GraphicElement &el, float x, float y) { const float scale = 1.0; - float offsetX = 0.0, offsetY = 0.0; - for (auto &el : ctx_->getDecalGraphics(decal.decal)) { - offsetX = decal.x; - offsetY = decal.y; - - if (el.type == GraphicElement::TYPE_BOX) { - auto line = PolyLine(true); - line.point(offsetX + scale * el.x1, offsetY + scale * el.y1); - line.point(offsetX + scale * el.x2, offsetY + scale * el.y1); - line.point(offsetX + scale * el.x2, offsetY + scale * el.y2); - line.point(offsetX + scale * el.x1, offsetY + scale * el.y2); - line.build(out); - } + if (el.type == GraphicElement::TYPE_BOX) { + auto line = PolyLine(true); + line.point(x + scale * el.x1, y + scale * el.y1); + line.point(x + scale * el.x2, y + scale * el.y1); + line.point(x + scale * el.x2, y + scale * el.y2); + line.point(x + scale * el.x1, y + scale * el.y2); + line.build(out); + } - if (el.type == GraphicElement::TYPE_LINE || el.type == GraphicElement::TYPE_ARROW) { - PolyLine(offsetX + scale * el.x1, offsetY + scale * el.y1, offsetX + scale * el.x2, offsetY + scale * el.y2) - .build(out); - } + if (el.type == GraphicElement::TYPE_LINE || el.type == GraphicElement::TYPE_ARROW) { + PolyLine(x + scale * el.x1, y + scale * el.y1, x + scale * el.x2, y + scale * el.y2) + .build(out); } } -void FPGAViewWidget::drawDecal(LineShaderData out[], const DecalXY &decal) +void FPGAViewWidget::drawDecal(LineShaderData &out, const DecalXY &decal) { - const float scale = 1.0; - float offsetX = 0.0, offsetY = 0.0; + float offsetX = decal.x; + float offsetY = decal.y; for (auto &el : ctx_->getDecalGraphics(decal.decal)) { - offsetX = decal.x; - offsetY = decal.y; - - if (el.type == GraphicElement::TYPE_BOX) { - auto line = PolyLine(true); - line.point(offsetX + scale * el.x1, offsetY + scale * el.y1); - line.point(offsetX + scale * el.x2, offsetY + scale * el.y1); - line.point(offsetX + scale * el.x2, offsetY + scale * el.y2); - line.point(offsetX + scale * el.x1, offsetY + scale * el.y2); - switch (el.style) { - case GraphicElement::STYLE_FRAME: - case GraphicElement::STYLE_INACTIVE: - case GraphicElement::STYLE_ACTIVE: - line.build(out[el.style]); - break; - default: - break; - } - } + drawGraphicElement(out, el, offsetX, offsetY); + } +} - if (el.type == GraphicElement::TYPE_LINE || el.type == GraphicElement::TYPE_ARROW) { - auto line = PolyLine(offsetX + scale * el.x1, offsetY + scale * el.y1, offsetX + scale * el.x2, - offsetY + scale * el.y2); - switch (el.style) { - case GraphicElement::STYLE_FRAME: - case GraphicElement::STYLE_INACTIVE: - case GraphicElement::STYLE_ACTIVE: - line.build(out[el.style]); - break; - default: - break; - } +void FPGAViewWidget::drawArchDecal(LineShaderData out[GraphicElement::STYLE_MAX], const DecalXY &decal) +{ + float offsetX = decal.x; + float offsetY = decal.y; + + for (auto &el : ctx_->getDecalGraphics(decal.decal)) { + switch (el.style) { + case GraphicElement::STYLE_FRAME: + case GraphicElement::STYLE_INACTIVE: + case GraphicElement::STYLE_ACTIVE: + drawGraphicElement(out[el.style], el, offsetX, offsetY); + break; + default: + break; } } } @@ -403,24 +383,28 @@ void FPGAViewWidget::paintGL() float thick1Px = mouseToWorldCoordinates(1, 0).x(); float thick11Px = mouseToWorldCoordinates(1.1, 0).x(); - // Draw grid. + // Render grid. auto grid = LineShaderData(); for (float i = -100.0f; i < 100.0f; i += 1.0f) { PolyLine(-100.0f, i, 100.0f, i).build(grid); PolyLine(i, -100.0f, i, 100.0f).build(grid); } + // Draw grid. lineShader_.draw(grid, colors_.grid, thick1Px, matrix); rendererDataLock_.lock(); - lineShader_.draw(rendererData_->decals[0], colors_.frame, thick11Px, matrix); - lineShader_.draw(rendererData_->decals[1], colors_.hidden, thick11Px, matrix); - lineShader_.draw(rendererData_->decals[2], colors_.inactive, thick11Px, matrix); - lineShader_.draw(rendererData_->decals[3], colors_.active, thick11Px, matrix); + // Render Arch graphics. + lineShader_.draw(rendererData_->gfxByStyle[GraphicElement::STYLE_FRAME], colors_.frame, thick11Px, matrix); + lineShader_.draw(rendererData_->gfxByStyle[GraphicElement::STYLE_HIDDEN], colors_.hidden, thick11Px, matrix); + lineShader_.draw(rendererData_->gfxByStyle[GraphicElement::STYLE_INACTIVE], colors_.inactive, thick11Px, matrix); + lineShader_.draw(rendererData_->gfxByStyle[GraphicElement::STYLE_ACTIVE], colors_.active, thick11Px, matrix); + + // Draw highlighted items. for (int i = 0; i < 8; i++) - lineShader_.draw(rendererData_->highlighted[i], colors_.highlight[i], thick11Px, matrix); + lineShader_.draw(rendererData_->gfxHighlighted[i], colors_.highlight[i], thick11Px, matrix); - lineShader_.draw(rendererData_->selected, colors_.selected, thick11Px, matrix); + lineShader_.draw(rendererData_->gfxSelected, colors_.selected, thick11Px, matrix); rendererDataLock_.unlock(); } @@ -431,120 +415,148 @@ void FPGAViewWidget::renderLines(void) if (ctx_ == nullptr) return; - ctx_->lock_ui(); - - // For now, collapse any decal changes into change of all decals. - // TODO(q3k): fix this - bool decalsChanged = false; - if (ctx_->allUiReload) { - ctx_->allUiReload = false; - decalsChanged = true; - } - if (ctx_->frameUiReload) { - ctx_->frameUiReload = false; - decalsChanged = true; - } - if (ctx_->belUiReload.size() > 0) { - ctx_->belUiReload.clear(); - decalsChanged = true; - } - if (ctx_->wireUiReload.size() > 0) { - ctx_->wireUiReload.clear(); - decalsChanged = true; - } - if (ctx_->pipUiReload.size() > 0) { - ctx_->pipUiReload.clear(); - decalsChanged = true; - } - if (ctx_->groupUiReload.size() > 0) { - ctx_->groupUiReload.clear(); - decalsChanged = true; - } - - // Local copy of decals, taken as fast as possible to not block the P&R. + // Data from Context needed to render all decals. std::vector belDecals; std::vector wireDecals; std::vector pipDecals; std::vector groupDecals; - if (decalsChanged) { - for (auto bel : ctx_->getBels()) { - belDecals.push_back(ctx_->getBelDecal(bel)); + bool decalsChanged = false; + { + // Take the UI/Normal mutex on the Context, copy over all we need as + // fast as we can. + std::lock_guard lock_ui(ctx_->ui_mutex); + std::lock_guard lock(ctx_->mutex); + + // For now, collapse any decal changes into change of all decals. + // TODO(q3k): fix this + if (ctx_->allUiReload) { + ctx_->allUiReload = false; + decalsChanged = true; + } + if (ctx_->frameUiReload) { + ctx_->frameUiReload = false; + decalsChanged = true; } - for (auto wire : ctx_->getWires()) { - wireDecals.push_back(ctx_->getWireDecal(wire)); + if (ctx_->belUiReload.size() > 0) { + ctx_->belUiReload.clear(); + decalsChanged = true; } - for (auto pip : ctx_->getPips()) { - pipDecals.push_back(ctx_->getPipDecal(pip)); + if (ctx_->wireUiReload.size() > 0) { + ctx_->wireUiReload.clear(); + decalsChanged = true; } - for (auto group : ctx_->getGroups()) { - groupDecals.push_back(ctx_->getGroupDecal(group)); + if (ctx_->pipUiReload.size() > 0) { + ctx_->pipUiReload.clear(); + decalsChanged = true; + } + if (ctx_->groupUiReload.size() > 0) { + ctx_->groupUiReload.clear(); + decalsChanged = true; + } + + // Local copy of decals, taken as fast as possible to not block the P&R. + if (decalsChanged) { + for (auto bel : ctx_->getBels()) { + belDecals.push_back(ctx_->getBelDecal(bel)); + } + for (auto wire : ctx_->getWires()) { + wireDecals.push_back(ctx_->getWireDecal(wire)); + } + for (auto pip : ctx_->getPips()) { + pipDecals.push_back(ctx_->getPipDecal(pip)); + } + for (auto group : ctx_->getGroups()) { + groupDecals.push_back(ctx_->getGroupDecal(group)); + } } } - ctx_->unlock_ui(); - rendererArgsLock_.lock(); - auto selectedItems = rendererArgs_->selectedItems; - auto highlightedItems = rendererArgs_->highlightedItems; - auto highlightedOrSelectedChanged = rendererArgs_->highlightedOrSelectedChanged; - rendererArgs_->highlightedOrSelectedChanged = false; - rendererArgsLock_.unlock(); + // Arguments from the main UI thread on what we should render. + std::vector selectedDecals; + std::vector highlightedDecals[8]; + bool highlightedOrSelectedChanged; + { + // Take the renderer arguments lock, copy over all we need. + QMutexLocker lock(&rendererArgsLock_); + selectedDecals = rendererArgs_->selectedDecals; + for (int i = 0; i < 8; i++) + highlightedDecals[i] = rendererArgs_->highlightedDecals[i]; + highlightedOrSelectedChanged = rendererArgs_->highlightedOrSelectedChanged; + rendererArgs_->highlightedOrSelectedChanged = false; + } + // Render decals if necessary. if (decalsChanged) { auto data = std::unique_ptr(new FPGAViewWidget::RendererData); // Draw Bels. for (auto const &decal : belDecals) { - drawDecal(data->decals, decal); + drawArchDecal(data->gfxByStyle, decal); } // Draw Wires. for (auto const &decal : wireDecals) { - drawDecal(data->decals, decal); + drawArchDecal(data->gfxByStyle, decal); } // Draw Pips. for (auto const &decal : pipDecals) { - drawDecal(data->decals, decal); + drawArchDecal(data->gfxByStyle, decal); } // Draw Groups. for (auto const &decal : groupDecals) { - drawDecal(data->decals, decal); + drawArchDecal(data->gfxByStyle, decal); } // Swap over. - rendererDataLock_.lock(); - rendererData_ = std::move(data); - rendererDataLock_.unlock(); + { + QMutexLocker lock(&rendererDataLock_); + + // If we're not re-rendering any highlights/selections, let's + // copy them over from teh current object. + if (!highlightedOrSelectedChanged) { + data->gfxSelected = rendererData_->gfxSelected; + for (int i = 0; i < 8; i++) + data->gfxHighlighted[i] = rendererData_->gfxHighlighted[i]; + } + + rendererData_ = std::move(data); + } } - rendererDataLock_.lock(); - if (decalsChanged || highlightedOrSelectedChanged) { - rendererData_->selected.clear(); - for (auto &decal : selectedItems) { - drawDecal(rendererData_->selected, decal); + if (highlightedOrSelectedChanged) { + QMutexLocker locker(&rendererDataLock_); + + // Render selected. + rendererData_->gfxSelected.clear(); + for (auto &decal : selectedDecals) { + drawDecal(rendererData_->gfxSelected, decal); } + + // Render highlighted. for (int i = 0; i < 8; i++) { - rendererData_->highlighted[i].clear(); - for (auto &decal : highlightedItems[i]) { - drawDecal(rendererData_->highlighted[i], decal); + rendererData_->gfxHighlighted[i].clear(); + for (auto &decal : highlightedDecals[i]) { + drawDecal(rendererData_->gfxHighlighted[i], decal); } } } - rendererDataLock_.unlock(); } void FPGAViewWidget::onSelectedArchItem(std::vector decals) { - rendererArgsLock_.lock(); - rendererArgs_->selectedItems = decals; - rendererArgs_->highlightedOrSelectedChanged = true; - rendererArgsLock_.unlock(); + { + QMutexLocker locker(&rendererArgsLock_); + rendererArgs_->selectedDecals = decals; + rendererArgs_->highlightedOrSelectedChanged = true; + } pokeRenderer(); } void FPGAViewWidget::onHighlightGroupChanged(std::vector decals, int group) { - rendererArgsLock_.lock(); - rendererArgs_->highlightedItems[group] = decals; - rendererArgs_->highlightedOrSelectedChanged = true; - rendererArgsLock_.unlock(); + { + QMutexLocker locker(&rendererArgsLock_); + rendererArgs_->highlightedDecals[group] = decals; + rendererArgs_->highlightedOrSelectedChanged = true; + } pokeRenderer(); } diff --git a/gui/fpgaviewwidget.h b/gui/fpgaviewwidget.h index 46231b16..69e947cf 100644 --- a/gui/fpgaviewwidget.h +++ b/gui/fpgaviewwidget.h @@ -277,8 +277,6 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE; void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE; void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE; - void drawDecal(LineShaderData &data, const DecalXY &decal); - void drawDecal(LineShaderData out[], const DecalXY &decal); public Q_SLOTS: void newContext(Context *ctx); @@ -291,6 +289,9 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions void zoomOutbound(); private: + void drawGraphicElement(LineShaderData &out, const GraphicElement &el, float x, float y); + void drawArchDecal(LineShaderData out[GraphicElement::STYLE_MAX], const DecalXY &decal); + void drawDecal(LineShaderData &out, const DecalXY &decal); void renderLines(void); void zoom(int level); @@ -326,15 +327,15 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions struct RendererData { - LineShaderData decals[4]; - LineShaderData selected; - LineShaderData highlighted[8]; + LineShaderData gfxByStyle[GraphicElement::STYLE_MAX]; + LineShaderData gfxSelected; + LineShaderData gfxHighlighted[8]; }; struct RendererArgs { - std::vector selectedItems; - std::vector highlightedItems[8]; + std::vector selectedDecals; + std::vector highlightedDecals[8]; bool highlightedOrSelectedChanged; }; -- cgit v1.2.3