gui: refactor FPGAViewWidget slightly

This commit is contained in:
Sergiusz Bazanski 2018-07-26 17:26:26 +01:00
parent c37d2baaf6
commit 706fe2f365
2 changed files with 149 additions and 136 deletions

View File

@ -311,69 +311,49 @@ void FPGAViewWidget::initializeGL()
0.0); 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; const float scale = 1.0;
float offsetX = 0.0, offsetY = 0.0;
for (auto &el : ctx_->getDecalGraphics(decal.decal)) { if (el.type == GraphicElement::TYPE_BOX) {
offsetX = decal.x; auto line = PolyLine(true);
offsetY = decal.y; 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_BOX) { if (el.type == GraphicElement::TYPE_LINE || el.type == GraphicElement::TYPE_ARROW) {
auto line = PolyLine(true); PolyLine(x + scale * el.x1, y + scale * el.y1, x + scale * el.x2, y + scale * el.y2)
line.point(offsetX + scale * el.x1, offsetY + scale * el.y1); .build(out);
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_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);
}
} }
} }
void FPGAViewWidget::drawDecal(LineShaderData out[], const DecalXY &decal) void FPGAViewWidget::drawDecal(LineShaderData &out, const DecalXY &decal)
{ {
const float scale = 1.0; float offsetX = decal.x;
float offsetX = 0.0, offsetY = 0.0; float offsetY = decal.y;
for (auto &el : ctx_->getDecalGraphics(decal.decal)) { for (auto &el : ctx_->getDecalGraphics(decal.decal)) {
offsetX = decal.x; drawGraphicElement(out, el, offsetX, offsetY);
offsetY = decal.y; }
}
if (el.type == GraphicElement::TYPE_BOX) { void FPGAViewWidget::drawArchDecal(LineShaderData out[GraphicElement::STYLE_MAX], const DecalXY &decal)
auto line = PolyLine(true); {
line.point(offsetX + scale * el.x1, offsetY + scale * el.y1); float offsetX = decal.x;
line.point(offsetX + scale * el.x2, offsetY + scale * el.y1); float offsetY = decal.y;
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;
}
}
if (el.type == GraphicElement::TYPE_LINE || el.type == GraphicElement::TYPE_ARROW) { for (auto &el : ctx_->getDecalGraphics(decal.decal)) {
auto line = PolyLine(offsetX + scale * el.x1, offsetY + scale * el.y1, offsetX + scale * el.x2, switch (el.style) {
offsetY + scale * el.y2); case GraphicElement::STYLE_FRAME:
switch (el.style) { case GraphicElement::STYLE_INACTIVE:
case GraphicElement::STYLE_FRAME: case GraphicElement::STYLE_ACTIVE:
case GraphicElement::STYLE_INACTIVE: drawGraphicElement(out[el.style], el, offsetX, offsetY);
case GraphicElement::STYLE_ACTIVE: break;
line.build(out[el.style]); default:
break; break;
default:
break;
}
} }
} }
} }
@ -403,24 +383,28 @@ void FPGAViewWidget::paintGL()
float thick1Px = mouseToWorldCoordinates(1, 0).x(); float thick1Px = mouseToWorldCoordinates(1, 0).x();
float thick11Px = mouseToWorldCoordinates(1.1, 0).x(); float thick11Px = mouseToWorldCoordinates(1.1, 0).x();
// Draw grid. // Render grid.
auto grid = LineShaderData(); auto grid = LineShaderData();
for (float i = -100.0f; i < 100.0f; i += 1.0f) { for (float i = -100.0f; i < 100.0f; i += 1.0f) {
PolyLine(-100.0f, i, 100.0f, i).build(grid); PolyLine(-100.0f, i, 100.0f, i).build(grid);
PolyLine(i, -100.0f, i, 100.0f).build(grid); PolyLine(i, -100.0f, i, 100.0f).build(grid);
} }
// Draw grid.
lineShader_.draw(grid, colors_.grid, thick1Px, matrix); lineShader_.draw(grid, colors_.grid, thick1Px, matrix);
rendererDataLock_.lock(); 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++) 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(); rendererDataLock_.unlock();
} }
@ -431,120 +415,148 @@ void FPGAViewWidget::renderLines(void)
if (ctx_ == nullptr) if (ctx_ == nullptr)
return; return;
ctx_->lock_ui(); // Data from Context needed to render all decals.
// 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.
std::vector<DecalXY> belDecals; std::vector<DecalXY> belDecals;
std::vector<DecalXY> wireDecals; std::vector<DecalXY> wireDecals;
std::vector<DecalXY> pipDecals; std::vector<DecalXY> pipDecals;
std::vector<DecalXY> groupDecals; std::vector<DecalXY> groupDecals;
if (decalsChanged) { bool decalsChanged = false;
for (auto bel : ctx_->getBels()) { {
belDecals.push_back(ctx_->getBelDecal(bel)); // Take the UI/Normal mutex on the Context, copy over all we need as
// fast as we can.
std::lock_guard<std::mutex> lock_ui(ctx_->ui_mutex);
std::lock_guard<std::mutex> 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;
} }
for (auto wire : ctx_->getWires()) { if (ctx_->frameUiReload) {
wireDecals.push_back(ctx_->getWireDecal(wire)); ctx_->frameUiReload = false;
decalsChanged = true;
} }
for (auto pip : ctx_->getPips()) { if (ctx_->belUiReload.size() > 0) {
pipDecals.push_back(ctx_->getPipDecal(pip)); ctx_->belUiReload.clear();
decalsChanged = true;
} }
for (auto group : ctx_->getGroups()) { if (ctx_->wireUiReload.size() > 0) {
groupDecals.push_back(ctx_->getGroupDecal(group)); 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.
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(); // Arguments from the main UI thread on what we should render.
auto selectedItems = rendererArgs_->selectedItems; std::vector<DecalXY> selectedDecals;
auto highlightedItems = rendererArgs_->highlightedItems; std::vector<DecalXY> highlightedDecals[8];
auto highlightedOrSelectedChanged = rendererArgs_->highlightedOrSelectedChanged; bool highlightedOrSelectedChanged;
rendererArgs_->highlightedOrSelectedChanged = false; {
rendererArgsLock_.unlock(); // 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) { if (decalsChanged) {
auto data = std::unique_ptr<FPGAViewWidget::RendererData>(new FPGAViewWidget::RendererData); auto data = std::unique_ptr<FPGAViewWidget::RendererData>(new FPGAViewWidget::RendererData);
// Draw Bels. // Draw Bels.
for (auto const &decal : belDecals) { for (auto const &decal : belDecals) {
drawDecal(data->decals, decal); drawArchDecal(data->gfxByStyle, decal);
} }
// Draw Wires. // Draw Wires.
for (auto const &decal : wireDecals) { for (auto const &decal : wireDecals) {
drawDecal(data->decals, decal); drawArchDecal(data->gfxByStyle, decal);
} }
// Draw Pips. // Draw Pips.
for (auto const &decal : pipDecals) { for (auto const &decal : pipDecals) {
drawDecal(data->decals, decal); drawArchDecal(data->gfxByStyle, decal);
} }
// Draw Groups. // Draw Groups.
for (auto const &decal : groupDecals) { for (auto const &decal : groupDecals) {
drawDecal(data->decals, decal); drawArchDecal(data->gfxByStyle, decal);
} }
// Swap over. // Swap over.
rendererDataLock_.lock(); {
rendererData_ = std::move(data); QMutexLocker lock(&rendererDataLock_);
rendererDataLock_.unlock();
// 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 (highlightedOrSelectedChanged) {
if (decalsChanged || highlightedOrSelectedChanged) { QMutexLocker locker(&rendererDataLock_);
rendererData_->selected.clear();
for (auto &decal : selectedItems) { // Render selected.
drawDecal(rendererData_->selected, decal); rendererData_->gfxSelected.clear();
for (auto &decal : selectedDecals) {
drawDecal(rendererData_->gfxSelected, decal);
} }
// Render highlighted.
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
rendererData_->highlighted[i].clear(); rendererData_->gfxHighlighted[i].clear();
for (auto &decal : highlightedItems[i]) { for (auto &decal : highlightedDecals[i]) {
drawDecal(rendererData_->highlighted[i], decal); drawDecal(rendererData_->gfxHighlighted[i], decal);
} }
} }
} }
rendererDataLock_.unlock();
} }
void FPGAViewWidget::onSelectedArchItem(std::vector<DecalXY> decals) void FPGAViewWidget::onSelectedArchItem(std::vector<DecalXY> decals)
{ {
rendererArgsLock_.lock(); {
rendererArgs_->selectedItems = decals; QMutexLocker locker(&rendererArgsLock_);
rendererArgs_->highlightedOrSelectedChanged = true; rendererArgs_->selectedDecals = decals;
rendererArgsLock_.unlock(); rendererArgs_->highlightedOrSelectedChanged = true;
}
pokeRenderer(); pokeRenderer();
} }
void FPGAViewWidget::onHighlightGroupChanged(std::vector<DecalXY> decals, int group) void FPGAViewWidget::onHighlightGroupChanged(std::vector<DecalXY> decals, int group)
{ {
rendererArgsLock_.lock(); {
rendererArgs_->highlightedItems[group] = decals; QMutexLocker locker(&rendererArgsLock_);
rendererArgs_->highlightedOrSelectedChanged = true; rendererArgs_->highlightedDecals[group] = decals;
rendererArgsLock_.unlock(); rendererArgs_->highlightedOrSelectedChanged = true;
}
pokeRenderer(); pokeRenderer();
} }

View File

@ -277,8 +277,6 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions
void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE; void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE; void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void wheelEvent(QWheelEvent *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: public Q_SLOTS:
void newContext(Context *ctx); void newContext(Context *ctx);
@ -291,6 +289,9 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions
void zoomOutbound(); void zoomOutbound();
private: 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 renderLines(void);
void zoom(int level); void zoom(int level);
@ -326,15 +327,15 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions
struct RendererData struct RendererData
{ {
LineShaderData decals[4]; LineShaderData gfxByStyle[GraphicElement::STYLE_MAX];
LineShaderData selected; LineShaderData gfxSelected;
LineShaderData highlighted[8]; LineShaderData gfxHighlighted[8];
}; };
struct RendererArgs struct RendererArgs
{ {
std::vector<DecalXY> selectedItems; std::vector<DecalXY> selectedDecals;
std::vector<DecalXY> highlightedItems[8]; std::vector<DecalXY> highlightedDecals[8];
bool highlightedOrSelectedChanged; bool highlightedOrSelectedChanged;
}; };