This commit is contained in:
Sergiusz Bazanski 2018-07-26 18:43:00 +01:00
parent 940886f9fa
commit 567566585c
2 changed files with 82 additions and 65 deletions

View File

@ -102,36 +102,40 @@ void FPGAViewWidget::initializeGL()
0.0); 0.0);
} }
void FPGAViewWidget::drawGraphicElement(LineShaderData &out, const GraphicElement &el, float x, float y) void FPGAViewWidget::renderGraphicElement(RendererData *data, LineShaderData &out, const GraphicElement &el, float x, float y)
{ {
const float scale = 1.0;
if (el.type == GraphicElement::TYPE_BOX) { if (el.type == GraphicElement::TYPE_BOX) {
auto line = PolyLine(true); auto line = PolyLine(true);
line.point(x + scale * el.x1, y + scale * el.y1); line.point(x + el.x1, y + el.y1);
line.point(x + scale * el.x2, y + scale * el.y1); line.point(x + el.x2, y + el.y1);
line.point(x + scale * el.x2, y + scale * el.y2); line.point(x + el.x2, y + el.y2);
line.point(x + scale * el.x1, y + scale * el.y2); line.point(x + el.x1, y + el.y2);
line.build(out); line.build(out);
data->bbX0 = std::min(data->bbX0, x + el.x1);
data->bbY0 = std::min(data->bbY0, x + el.y1);
data->bbX1 = std::max(data->bbX1, x + el.x2);
data->bbY1 = std::max(data->bbY1, x + el.y2);
return;
} }
if (el.type == GraphicElement::TYPE_LINE || el.type == GraphicElement::TYPE_ARROW) { 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) PolyLine(x + el.x1, y + el.y1, x + el.x2, y + el.y2).build(out);
.build(out); return;
} }
} }
void FPGAViewWidget::drawDecal(LineShaderData &out, const DecalXY &decal) void FPGAViewWidget::renderDecal(RendererData *data, LineShaderData &out, const DecalXY &decal)
{ {
float offsetX = decal.x; float offsetX = decal.x;
float offsetY = decal.y; float offsetY = decal.y;
for (auto &el : ctx_->getDecalGraphics(decal.decal)) { for (auto &el : ctx_->getDecalGraphics(decal.decal)) {
drawGraphicElement(out, el, offsetX, offsetY); renderGraphicElement(data, out, el, offsetX, offsetY);
} }
} }
void FPGAViewWidget::drawArchDecal(LineShaderData out[GraphicElement::STYLE_MAX], const DecalXY &decal) void FPGAViewWidget::renderArchDecal(RendererData *data, const DecalXY &decal)
{ {
float offsetX = decal.x; float offsetX = decal.x;
float offsetY = decal.y; float offsetY = decal.y;
@ -141,7 +145,7 @@ void FPGAViewWidget::drawArchDecal(LineShaderData out[GraphicElement::STYLE_MAX]
case GraphicElement::STYLE_FRAME: case GraphicElement::STYLE_FRAME:
case GraphicElement::STYLE_INACTIVE: case GraphicElement::STYLE_INACTIVE:
case GraphicElement::STYLE_ACTIVE: case GraphicElement::STYLE_ACTIVE:
drawGraphicElement(out[el.style], el, offsetX, offsetY); renderGraphicElement(data, data->gfxByStyle[el.style], el, offsetX, offsetY);
break; break;
default: default:
break; break;
@ -149,6 +153,10 @@ void FPGAViewWidget::drawArchDecal(LineShaderData out[GraphicElement::STYLE_MAX]
} }
} }
void FPGAViewWidget::populateQuadTree(RendererData *data, const DecalXY &decal, IdString id)
{
}
QMatrix4x4 FPGAViewWidget::getProjection(void) QMatrix4x4 FPGAViewWidget::getProjection(void)
{ {
QMatrix4x4 matrix; QMatrix4x4 matrix;
@ -183,7 +191,8 @@ void FPGAViewWidget::paintGL()
// Draw grid. // Draw grid.
lineShader_.draw(grid, colors_.grid, thick1Px, matrix); lineShader_.draw(grid, colors_.grid, thick1Px, matrix);
rendererDataLock_.lock(); {
QMutexLocker locker(&rendererDataLock_);
// Render Arch graphics. // Render Arch graphics.
lineShader_.draw(rendererData_->gfxByStyle[GraphicElement::STYLE_FRAME], colors_.frame, thick11Px, matrix); lineShader_.draw(rendererData_->gfxByStyle[GraphicElement::STYLE_FRAME], colors_.frame, thick11Px, matrix);
@ -196,7 +205,7 @@ void FPGAViewWidget::paintGL()
lineShader_.draw(rendererData_->gfxHighlighted[i], colors_.highlight[i], thick11Px, matrix); lineShader_.draw(rendererData_->gfxHighlighted[i], colors_.highlight[i], thick11Px, matrix);
lineShader_.draw(rendererData_->gfxSelected, colors_.selected, thick11Px, matrix); lineShader_.draw(rendererData_->gfxSelected, colors_.selected, thick11Px, matrix);
rendererDataLock_.unlock(); }
} }
void FPGAViewWidget::pokeRenderer(void) { renderRunner_->poke(); } void FPGAViewWidget::pokeRenderer(void) { renderRunner_->poke(); }
@ -207,10 +216,10 @@ void FPGAViewWidget::renderLines(void)
return; return;
// Data from Context needed to render all decals. // Data from Context needed to render all decals.
std::vector<DecalXY> belDecals; std::vector<std::pair<DecalXY, IdString>> belDecals;
std::vector<DecalXY> wireDecals; std::vector<std::pair<DecalXY, IdString>> wireDecals;
std::vector<DecalXY> pipDecals; std::vector<std::pair<DecalXY, IdString>> pipDecals;
std::vector<DecalXY> groupDecals; std::vector<std::pair<DecalXY, IdString>> groupDecals;
bool decalsChanged = false; bool decalsChanged = false;
{ {
// Take the UI/Normal mutex on the Context, copy over all we need as // Take the UI/Normal mutex on the Context, copy over all we need as
@ -248,16 +257,16 @@ 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.
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), ctx_->getBelName(bel)});
} }
for (auto wire : ctx_->getWires()) { for (auto wire : ctx_->getWires()) {
wireDecals.push_back(ctx_->getWireDecal(wire)); wireDecals.push_back({ctx_->getWireDecal(wire), ctx_->getWireName(wire)});
} }
for (auto pip : ctx_->getPips()) { for (auto pip : ctx_->getPips()) {
pipDecals.push_back(ctx_->getPipDecal(pip)); pipDecals.push_back({ctx_->getPipDecal(pip), ctx_->getPipName(pip)});
} }
for (auto group : ctx_->getGroups()) { for (auto group : ctx_->getGroups()) {
groupDecals.push_back(ctx_->getGroupDecal(group)); groupDecals.push_back({ctx_->getGroupDecal(group), ctx_->getGroupName(group)});
} }
} }
} }
@ -276,29 +285,45 @@ void FPGAViewWidget::renderLines(void)
rendererArgs_->highlightedOrSelectedChanged = false; rendererArgs_->highlightedOrSelectedChanged = false;
} }
QuadTreeBels::BoundingBox globalBB = QuadTreeBels::BoundingBox(-1000, -1000, 1000, 1000);
// Render decals if necessary. // 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);
// Reset bounding box.
data->bbX0 = 0;
data->bbY0 = 0;
data->bbX1 = 0;
data->bbY1 = 0;
// Draw Bels. // Draw Bels.
data->qtBels = std::unique_ptr<QuadTreeBels>(new QuadTreeBels(globalBB));
for (auto const &decal : belDecals) { for (auto const &decal : belDecals) {
drawArchDecal(data->gfxByStyle, decal); renderArchDecal(data.get(), decal.first);
} }
// Draw Wires. // Draw Wires.
for (auto const &decal : wireDecals) { for (auto const &decal : wireDecals) {
drawArchDecal(data->gfxByStyle, decal); renderArchDecal(data.get(), decal.first);
} }
// Draw Pips. // Draw Pips.
for (auto const &decal : pipDecals) { for (auto const &decal : pipDecals) {
drawArchDecal(data->gfxByStyle, decal); renderArchDecal(data.get(), decal.first);
} }
// Draw Groups. // Draw Groups.
for (auto const &decal : groupDecals) { for (auto const &decal : groupDecals) {
drawArchDecal(data->gfxByStyle, decal); renderArchDecal(data.get(), decal.first);
} }
// Bounding box should be calculated by now.
NPNR_ASSERT((data->bbX1 - data->bbX0) != 0);
NPNR_ASSERT((data->bbY1 - data->bbY0) != 0);
auto bb = QuadTreeElements::BoundingBox(data->bbX0, data->bbY0, data->bbX1, data->bbY1);
// Populate picking quadtree.
//data->qt = std::unique_ptr<QuadTreeElements>(new QuadTreeElements(bb));
//for (auto const &decal : belDecals) {
// populateQuadTree(data.get(), decal.first, decal.second);
//}
// Swap over. // Swap over.
{ {
QMutexLocker lock(&rendererDataLock_); QMutexLocker lock(&rendererDataLock_);
@ -321,14 +346,14 @@ void FPGAViewWidget::renderLines(void)
// Render selected. // Render selected.
rendererData_->gfxSelected.clear(); rendererData_->gfxSelected.clear();
for (auto &decal : selectedDecals) { for (auto &decal : selectedDecals) {
drawDecal(rendererData_->gfxSelected, decal); renderDecal(rendererData_.get(), rendererData_->gfxSelected, decal);
} }
// Render highlighted. // Render highlighted.
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
rendererData_->gfxHighlighted[i].clear(); rendererData_->gfxHighlighted[i].clear();
for (auto &decal : highlightedDecals[i]) { for (auto &decal : highlightedDecals[i]) {
drawDecal(rendererData_->gfxHighlighted[i], decal); renderDecal(rendererData_.get(), rendererData_->gfxHighlighted[i], decal);
} }
} }
} }
@ -366,12 +391,12 @@ void FPGAViewWidget::mousePressEvent(QMouseEvent *event)
int y = event->y(); int y = event->y();
auto world = mouseToWorldCoordinates(x, y); auto world = mouseToWorldCoordinates(x, y);
rendererDataLock_.lock(); rendererDataLock_.lock();
if (rendererData_->qtBels != nullptr) { //if (rendererData_->qtBels != nullptr) {
auto elems = rendererData_->qtBels->get(world.x(), world.y()); // auto elems = rendererData_->qtBels->get(world.x(), world.y());
if (elems.size() > 0) { // if (elems.size() > 0) {
clickedBel(elems[0]); // clickedBel(elems[0]);
} // }
} //}
rendererDataLock_.unlock(); rendererDataLock_.unlock();
} }
} }

View File

@ -35,6 +35,7 @@
#include "nextpnr.h" #include "nextpnr.h"
#include "quadtree.h" #include "quadtree.h"
#include "lineshader.h" #include "lineshader.h"
#include "designwidget.h"
NEXTPNR_NAMESPACE_BEGIN NEXTPNR_NAMESPACE_BEGIN
@ -126,25 +127,12 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions
const float zoomLvl1_ = 100.0f; const float zoomLvl1_ = 100.0f;
const float zoomLvl2_ = 50.0f; const float zoomLvl2_ = 50.0f;
using QuadTreeElements = QuadTree<float, std::pair<ElementType, IdString>>;
Context *ctx_; Context *ctx_;
QTimer paintTimer_; QTimer paintTimer_;
std::unique_ptr<PeriodicRunner> renderRunner_; std::unique_ptr<PeriodicRunner> renderRunner_;
using QuadTreeBels = QuadTree<float, BelId>;
template <typename T>
void commitToQuadtree(T *tree, const DecalXY &decal, BelId bel)
{
float offsetX = decal.x;
float offsetY = decal.y;
for (auto &el : ctx_->getDecalGraphics(decal.decal)) {
if (el.type == GraphicElement::TYPE_BOX) {
tree->insert(typename T::BoundingBox(offsetX + el.x1, offsetY + el.y1, offsetX + el.x2, offsetY + el.y2), bel);
}
}
}
QPoint lastDragPos_; QPoint lastDragPos_;
LineShader lineShader_; LineShader lineShader_;
QMatrix4x4 viewMove_; QMatrix4x4 viewMove_;
@ -167,7 +155,10 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions
LineShaderData gfxByStyle[GraphicElement::STYLE_MAX]; LineShaderData gfxByStyle[GraphicElement::STYLE_MAX];
LineShaderData gfxSelected; LineShaderData gfxSelected;
LineShaderData gfxHighlighted[8]; LineShaderData gfxHighlighted[8];
std::unique_ptr<QuadTreeBels> qtBels; // Global bounding box of data from Arch.
float bbX0, bbY0, bbX1, bbY1;
// Quadtree for picking objects.
std::unique_ptr<QuadTreeElements> qt;
}; };
std::unique_ptr<RendererData> rendererData_; std::unique_ptr<RendererData> rendererData_;
QMutex rendererDataLock_; QMutex rendererDataLock_;
@ -183,9 +174,10 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions
void zoom(int level); void zoom(int level);
void renderLines(void); void renderLines(void);
void drawGraphicElement(LineShaderData &out, const GraphicElement &el, float x, float y); void renderGraphicElement(RendererData *data, LineShaderData &out, const GraphicElement &el, float x, float y);
void drawDecal(LineShaderData &out, const DecalXY &decal); void renderDecal(RendererData *data, LineShaderData &out, const DecalXY &decal);
void drawArchDecal(LineShaderData out[GraphicElement::STYLE_MAX], const DecalXY &decal); void renderArchDecal(RendererData *data, const DecalXY &decal);
void populateQuadTree(RendererData *data, const DecalXY &decal, IdString id);
QVector4D mouseToWorldCoordinates(int x, int y); QVector4D mouseToWorldCoordinates(int x, int y);
QVector4D mouseToWorldDimensions(int x, int y); QVector4D mouseToWorldDimensions(int x, int y);
QMatrix4x4 getProjection(void); QMatrix4x4 getProjection(void);