diff --git a/common/nextpnr.h b/common/nextpnr.h index efcab9fc..50465869 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -238,16 +238,6 @@ struct CellInfo std::unordered_map pins; }; -struct UIUpdatesRequired -{ - bool allUIReload; - bool frameUIReload; - std::unordered_set belUIReload; - std::unordered_set wireUIReload; - std::unordered_set pipUIReload; - std::unordered_set groupUIReload; -}; - struct BaseCtx { // -------------------------------------------------------------- @@ -270,8 +260,6 @@ struct BaseCtx idstring_idx_to_str = new std::vector; IdString::initialize_add(this, "", 0); IdString::initialize_arch(this); - - allUiReload = true; } ~BaseCtx() @@ -304,25 +292,6 @@ struct BaseCtx void refreshUiPip(PipId pip) { pipUiReload.insert(pip); } void refreshUiGroup(GroupId group) { groupUiReload.insert(group); } - - UIUpdatesRequired getUIUpdatesRequired(void) - { - UIUpdatesRequired req; - req.allUIReload = allUiReload; - req.frameUIReload = frameUiReload; - req.belUIReload = belUiReload; - req.wireUIReload = wireUiReload; - req.pipUIReload = pipUiReload; - req.groupUIReload = groupUiReload; - - allUiReload = false; - frameUiReload = false; - belUiReload.clear(); - wireUiReload.clear(); - pipUiReload.clear(); - groupUiReload.clear(); - return req; - } }; NEXTPNR_NAMESPACE_END diff --git a/gui/fpgaviewwidget.cc b/gui/fpgaviewwidget.cc index 21ce5b67..6b6a2617 100644 --- a/gui/fpgaviewwidget.cc +++ b/gui/fpgaviewwidget.cc @@ -23,7 +23,6 @@ #include #include #include -#include #include #include "fpgaviewwidget.h" @@ -196,7 +195,7 @@ bool LineShader::compile(void) return true; } -void LineShader::draw(const LineShaderData &line, const QColor &color, const float thickness, const QMatrix4x4 &projection) +void LineShader::draw(const LineShaderData &line, const QMatrix4x4 &projection) { auto gl = QOpenGLContext::currentContext()->functions(); vao_.bind(); @@ -215,8 +214,8 @@ void LineShader::draw(const LineShaderData &line, const QColor &color, const flo buffers_.index.allocate(&line.indices[0], sizeof(GLuint) * line.indices.size()); program_->setUniformValue(uniforms_.projection, projection); - program_->setUniformValue(uniforms_.thickness, thickness); - program_->setUniformValue(uniforms_.color, color.redF(), color.greenF(), color.blueF(), color.alphaF()); + program_->setUniformValue(uniforms_.thickness, line.thickness); + program_->setUniformValue(uniforms_.color, line.color.r, line.color.g, line.color.b, line.color.a); buffers_.position.bind(); program_->enableAttributeArray("position"); @@ -265,10 +264,6 @@ FPGAViewWidget::FPGAViewWidget(QWidget *parent) : QOpenGLWidget(parent), lineSha if (fmt.minorVersion() < 1) { printf("Could not get OpenGL 3.1 context - trying anyway...\n "); } - - QTimer *timer = new QTimer(this); - connect(timer, SIGNAL(timeout()), this, SLOT(update())); - timer->start(5000); } FPGAViewWidget::~FPGAViewWidget() {} @@ -292,6 +287,73 @@ void FPGAViewWidget::initializeGL() glClearColor(backgroundColor_.red() / 255, backgroundColor_.green() / 255, backgroundColor_.blue() / 255, 0.0); } +void FPGAViewWidget::drawDecal(LineShaderData &out, const DecalXY &decal) +{ + 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::G_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::G_LINE) { + 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) +{ + 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::G_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::G_FRAME: + case GraphicElement::G_INACTIVE: + case GraphicElement::G_ACTIVE: + line.build(out[el.style]); + break; + default: + break; + } + } + + if (el.type == GraphicElement::G_LINE) { + auto line = PolyLine(offsetX + scale * el.x1, offsetY + scale * el.y1, offsetX + scale * el.x2, + offsetY + scale * el.y2); + switch (el.style) { + case GraphicElement::G_FRAME: + case GraphicElement::G_INACTIVE: + case GraphicElement::G_ACTIVE: + line.build(out[el.style]); + break; + default: + break; + } + } + } +} + QMatrix4x4 FPGAViewWidget::getProjection(void) { QMatrix4x4 matrix; @@ -318,59 +380,47 @@ void FPGAViewWidget::paintGL() float thick11Px = mouseToWorldCoordinates(1.1, 0).x(); // Draw grid. - auto grid = LineShaderData(); + auto grid = LineShaderData(thick1Px, gridColor_); 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); } - lineShader_.draw(grid, gridColor_, thick1Px, matrix); + lineShader_.draw(grid, matrix); + + LineShaderData shaders[4] = {[GraphicElement::G_FRAME] = LineShaderData(thick11Px, gFrameColor_), + [GraphicElement::G_HIDDEN] = LineShaderData(thick11Px, gHiddenColor_), + [GraphicElement::G_INACTIVE] = LineShaderData(thick11Px, gInactiveColor_), + [GraphicElement::G_ACTIVE] = LineShaderData(thick11Px, gActiveColor_)}; if (ctx_) { - auto &&proxy = ctx_->rwproxy(); - auto updates = proxy.getUIUpdatesRequired(); - - // Collapse all updates to a full redraw. - // TODO(q3k) fix this. - - bool redraw = (updates.allUIReload - || !updates.belUIReload.empty() - || !updates.wireUIReload.empty() - || !updates.pipUIReload.empty() - || !updates.groupUIReload.empty() - || updates.frameUIReload); - - if (redraw) { - shaders_[0].clear(); - shaders_[1].clear(); - shaders_[2].clear(); - shaders_[3].clear(); - - // Draw Bels. - for (auto bel : ctx_->getBels()) { - drawDecal(proxy, shaders_, ctx_->getBelDecal(bel)); - } - // Draw Wires. - for (auto wire : ctx_->getWires()) { - drawDecal(proxy, shaders_, ctx_->getWireDecal(wire)); - } - // Draw Pips. - for (auto pip : ctx_->getPips()) { - drawDecal(proxy, shaders_, ctx_->getPipDecal(pip)); - } - // Draw Groups. - for (auto group : ctx_->getGroups()) { - drawDecal(proxy, shaders_, ctx_->getGroupDecal(group)); - } - // Draw Frame Graphics. - drawDecal(proxy, shaders_, ctx_->getFrameDecal()); + // Draw Bels. + for (auto bel : ctx_->getBels()) { + drawDecal(shaders, ctx_->getBelDecal(bel)); + } + // Draw Wires. + for (auto wire : ctx_->getWires()) { + drawDecal(shaders, ctx_->getWireDecal(wire)); + } + // Draw Pips. + for (auto pip : ctx_->getPips()) { + drawDecal(shaders, ctx_->getPipDecal(pip)); + } + // Draw Groups. + for (auto group : ctx_->getGroups()) { + drawDecal(shaders, ctx_->getGroupDecal(group)); } } + lineShader_.draw(shaders[0], matrix); + lineShader_.draw(shaders[1], matrix); + lineShader_.draw(shaders[2], matrix); + lineShader_.draw(shaders[3], matrix); - lineShader_.draw(shaders_[0], gFrameColor_, thick11Px, matrix); - lineShader_.draw(shaders_[1], gHiddenColor_, thick11Px, matrix); - lineShader_.draw(shaders_[2], gInactiveColor_, thick11Px, matrix); - lineShader_.draw(shaders_[3], gActiveColor_, thick11Px, matrix); - //lineShader_.draw(frame, matrix); + // Draw Frame Graphics. + auto frames = LineShaderData(thick11Px, frameColor_); + if (ctx_) { + drawDecal(frames, ctx_->getFrameDecal()); + lineShader_.draw(frames, matrix); + } } void FPGAViewWidget::resizeGL(int width, int height) {} diff --git a/gui/fpgaviewwidget.h b/gui/fpgaviewwidget.h index 3652e82e..410b0582 100644 --- a/gui/fpgaviewwidget.h +++ b/gui/fpgaviewwidget.h @@ -41,6 +41,18 @@ NPNR_PACKED_STRUCT(struct Vertex2DPOD { Vertex2DPOD(GLfloat X, GLfloat Y) : x(X), y(Y) {} }); +// Vertex2DPOD is a structure of R, G, B, A values that can be passed to OpenGL +// directly. +NPNR_PACKED_STRUCT(struct ColorPOD { + GLfloat r; + GLfloat g; + GLfloat b; + GLfloat a; + + ColorPOD(GLfloat R, GLfloat G, GLfloat B, GLfloat A) : r(R), g(G), b(B), a(A) {} + ColorPOD(const QColor &color) : r(color.redF()), g(color.greenF()), b(color.blueF()), a(color.alphaF()) {} +}); + // LineShaderData is a built set of vertices that can be rendered by the // LineShader. // Each LineShaderData can have its' own color and thickness. @@ -51,13 +63,10 @@ struct LineShaderData std::vector miters; std::vector indices; - void clear(void) - { - vertices.clear(); - normals.clear(); - miters.clear(); - indices.clear(); - } + GLfloat thickness; + ColorPOD color; + + LineShaderData(GLfloat Thickness, QColor Color) : thickness(Thickness), color(Color) {} }; // PolyLine is a set of segments defined by points, that can be built to a @@ -201,7 +210,7 @@ class LineShader bool compile(void); // Render a LineShaderData with a given M/V/P transformation. - void draw(const LineShaderData &data, const QColor &color, const float thickness, const QMatrix4x4 &projection); + void draw(const LineShaderData &data, const QMatrix4x4 &projection); }; class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions @@ -237,76 +246,8 @@ 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; - - template - void drawDecal(const T &proxy, LineShaderData &out, const DecalXY &decal) - { - const float scale = 1.0; - float offsetX = 0.0, offsetY = 0.0; - - for (auto &el : proxy.getDecalGraphics(decal.decal)) { - offsetX = decal.x; - offsetY = decal.y; - - if (el.type == GraphicElement::G_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::G_LINE) { - PolyLine(offsetX + scale * el.x1, offsetY + scale * el.y1, offsetX + scale * el.x2, offsetY + scale * el.y2) - .build(out); - } - } - } - - template - void drawDecal(const T &proxy, LineShaderData out[], const DecalXY &decal) - { - const float scale = 1.0; - float offsetX = 0.0, offsetY = 0.0; - - for (auto &el : proxy.getDecalGraphics(decal.decal)) { - offsetX = decal.x; - offsetY = decal.y; - - if (el.type == GraphicElement::G_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::G_FRAME: - case GraphicElement::G_INACTIVE: - case GraphicElement::G_ACTIVE: - line.build(out[el.style]); - break; - default: - break; - } - } - - if (el.type == GraphicElement::G_LINE) { - auto line = PolyLine(offsetX + scale * el.x1, offsetY + scale * el.y1, offsetX + scale * el.x2, - offsetY + scale * el.y2); - switch (el.style) { - case GraphicElement::G_FRAME: - case GraphicElement::G_INACTIVE: - case GraphicElement::G_ACTIVE: - line.build(out[el.style]); - break; - default: - break; - } - } - } - } - + void drawDecal(LineShaderData &data, const DecalXY &decal); + void drawDecal(LineShaderData out[], const DecalXY &decal); public Q_SLOTS: void newContext(Context *ctx); @@ -333,8 +274,6 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions QColor gInactiveColor_; QColor gActiveColor_; QColor frameColor_; - - LineShaderData shaders_[4]; }; NEXTPNR_NAMESPACE_END diff --git a/ice40/arch.cc b/ice40/arch.cc index 547dbcd6..af6e922c 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -534,8 +534,9 @@ DecalXY Arch::getGroupDecal(GroupId group) const return decalxy; }; -std::vector ArchRProxyMethods::getDecalGraphics(DecalId decal) const +std::vector Arch::getDecalGraphics(DecalId decal) const { + boost::shared_lock_guard lock(mtx_); std::vector ret; if (decal.type == DecalId::TYPE_FRAME) { @@ -567,7 +568,7 @@ std::vector ArchRProxyMethods::getDecalGraphics(DecalId decal) c BelId bel; bel.index = decal.index; - auto bel_type = parent_->getBelType(bel); + auto bel_type = getBelType(bel); if (bel_type == TYPE_ICESTORM_LC) { GraphicElement el; @@ -953,9 +954,4 @@ CellInfo *ArchRWProxyMethods::getCell(IdString cell) return parent_->cells.at(cell).get(); } -UIUpdatesRequired ArchRWProxyMethods::getUIUpdatesRequired(void) -{ - return parent_->getUIUpdatesRequired(); -} - NEXTPNR_NAMESPACE_END diff --git a/ice40/arch.h b/ice40/arch.h index 4311f4a5..da1e583a 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -604,6 +604,8 @@ public: // ------------------------------------------------- + std::vector getDecalGraphics(DecalId decal) const; + DecalXY getFrameDecal() const; DecalXY getBelDecal(BelId bel) const; DecalXY getWireDecal(WireId wire) const; @@ -689,8 +691,6 @@ public: IdString getBoundBelCell(BelId bel) const; BelId getBelByName(IdString name) const; - - std::vector getDecalGraphics(DecalId decal) const; }; // A proxy object that keeps an Arch shared/readonly lock until it goes out @@ -750,10 +750,6 @@ public: void bindBel(BelId bel, IdString cell, PlaceStrength strength); // Returned pointer is valid as long as Proxy object exists. CellInfo *getCell(IdString cell); - - - // Methods to be used by UI for detecting whether we need to redraw. - UIUpdatesRequired getUIUpdatesRequired(void); }; // A proxy object that keeps an Arch readwrite lock until it goes out of scope. diff --git a/ice40/main.cc b/ice40/main.cc index d38c786c..e77bdd34 100644 --- a/ice40/main.cc +++ b/ice40/main.cc @@ -51,8 +51,7 @@ void svg_dump_decal(const Context *ctx, const DecalXY &decal) const float scale = 10.0, offset = 10.0; const std::string style = "stroke=\"black\" stroke-width=\"0.1\" fill=\"none\""; - auto &&proxy = ctx->rproxy(); - for (auto &el : proxy.getDecalGraphics(decal.decal)) { + for (auto &el : ctx->getDecalGraphics(decal.decal)) { if (el.type == GraphicElement::G_BOX) { std::cout << "