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,71 +311,51 @@ 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)) {
offsetX = decal.x;
offsetY = decal.y;
if (el.type == GraphicElement::TYPE_BOX) { if (el.type == GraphicElement::TYPE_BOX) {
auto line = PolyLine(true); auto line = PolyLine(true);
line.point(offsetX + scale * el.x1, offsetY + scale * el.y1); line.point(x + scale * el.x1, y + scale * el.y1);
line.point(offsetX + scale * el.x2, offsetY + scale * el.y1); line.point(x + scale * el.x2, y + scale * el.y1);
line.point(offsetX + scale * el.x2, offsetY + scale * el.y2); line.point(x + scale * el.x2, y + scale * el.y2);
line.point(offsetX + scale * el.x1, offsetY + scale * el.y2); line.point(x + scale * el.x1, y + scale * el.y2);
line.build(out); line.build(out);
} }
if (el.type == GraphicElement::TYPE_LINE || el.type == GraphicElement::TYPE_ARROW) { 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) PolyLine(x + scale * el.x1, y + scale * el.y1, x + scale * el.x2, y + scale * el.y2)
.build(out); .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); for (auto &el : ctx_->getDecalGraphics(decal.decal)) {
switch (el.style) { switch (el.style) {
case GraphicElement::STYLE_FRAME: case GraphicElement::STYLE_FRAME:
case GraphicElement::STYLE_INACTIVE: case GraphicElement::STYLE_INACTIVE:
case GraphicElement::STYLE_ACTIVE: case GraphicElement::STYLE_ACTIVE:
line.build(out[el.style]); drawGraphicElement(out[el.style], el, offsetX, offsetY);
break; break;
default: default:
break; break;
} }
} }
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;
}
}
}
} }
QMatrix4x4 FPGAViewWidget::getProjection(void) QMatrix4x4 FPGAViewWidget::getProjection(void)
@ -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,11 +415,20 @@ void FPGAViewWidget::renderLines(void)
if (ctx_ == nullptr) if (ctx_ == nullptr)
return; return;
ctx_->lock_ui(); // Data from Context needed to render all decals.
std::vector<DecalXY> belDecals;
std::vector<DecalXY> wireDecals;
std::vector<DecalXY> pipDecals;
std::vector<DecalXY> groupDecals;
bool decalsChanged = false;
{
// 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. // For now, collapse any decal changes into change of all decals.
// TODO(q3k): fix this // TODO(q3k): fix this
bool decalsChanged = false;
if (ctx_->allUiReload) { if (ctx_->allUiReload) {
ctx_->allUiReload = false; ctx_->allUiReload = false;
decalsChanged = true; decalsChanged = true;
@ -462,10 +455,6 @@ void FPGAViewWidget::renderLines(void)
} }
// Local copy of decals, taken as fast as possible to not block the P&R. // Local copy of decals, taken as fast as possible to not block the P&R.
std::vector<DecalXY> belDecals;
std::vector<DecalXY> wireDecals;
std::vector<DecalXY> pipDecals;
std::vector<DecalXY> groupDecals;
if (decalsChanged) { if (decalsChanged) {
for (auto bel : ctx_->getBels()) { for (auto bel : ctx_->getBels()) {
belDecals.push_back(ctx_->getBelDecal(bel)); belDecals.push_back(ctx_->getBelDecal(bel));
@ -480,71 +469,94 @@ void FPGAViewWidget::renderLines(void)
groupDecals.push_back(ctx_->getGroupDecal(group)); 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;
{
// 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; rendererArgs_->highlightedOrSelectedChanged = false;
rendererArgsLock_.unlock(); }
// 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];
} }
rendererDataLock_.lock(); rendererData_ = std::move(data);
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++) { 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_->selectedDecals = decals;
rendererArgs_->highlightedOrSelectedChanged = true; rendererArgs_->highlightedOrSelectedChanged = true;
rendererArgsLock_.unlock(); }
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_->highlightedDecals[group] = decals;
rendererArgs_->highlightedOrSelectedChanged = true; rendererArgs_->highlightedOrSelectedChanged = true;
rendererArgsLock_.unlock(); }
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;
}; };