diff options
Diffstat (limited to 'gui')
| -rw-r--r-- | gui/CMakeLists.txt | 8 | ||||
| -rwxr-xr-x | gui/create_img.sh | 6 | ||||
| -rw-r--r-- | gui/designwidget.cc | 21 | ||||
| -rw-r--r-- | gui/designwidget.h | 5 | ||||
| -rw-r--r-- | gui/ecp5/mainwindow.cc | 52 | ||||
| -rw-r--r-- | gui/ecp5/mainwindow.h | 6 | ||||
| -rw-r--r-- | gui/ecp5/nextpnr.qrc | 1 | ||||
| -rw-r--r-- | gui/ecp5/resources/open_base.png | bin | 2022 -> 2175 bytes | |||
| -rw-r--r-- | gui/ecp5/resources/open_lpf.png | bin | 0 -> 2117 bytes | |||
| -rw-r--r-- | gui/ecp5/resources/save_config.png | bin | 1428 -> 1645 bytes | |||
| -rw-r--r-- | gui/fpgaviewwidget.cc | 174 | ||||
| -rw-r--r-- | gui/fpgaviewwidget.h | 9 | ||||
| -rw-r--r-- | gui/generic/mainwindow.h | 2 | ||||
| -rw-r--r-- | gui/ice40/mainwindow.h | 2 | ||||
| -rw-r--r-- | gui/ice40/resources/open_pcf.png | bin | 1984 -> 2139 bytes | |||
| -rw-r--r-- | gui/ice40/resources/save_asc.png | bin | 1384 -> 1509 bytes | |||
| -rw-r--r-- | gui/lineshader.cc | 117 | ||||
| -rw-r--r-- | gui/lineshader.h | 32 | ||||
| -rw-r--r-- | gui/resources/open_json.png | bin | 2093 -> 2177 bytes |
19 files changed, 314 insertions, 121 deletions
diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index 2e8e367e..a818640f 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -12,6 +12,12 @@ if (BUILD_PYTHON) ../3rdparty/python-console/modified/pyredirector.cc ../3rdparty/python-console/modified/pyinterpreter.cc + ../3rdparty/imgui/imgui_widgets.cpp + ../3rdparty/imgui/imgui_draw.cpp + ../3rdparty/imgui/imgui.cpp + ../3rdparty/imgui/imgui_demo.cpp + ../3rdparty/qtimgui/ImGuiRenderer.cpp + ../3rdparty/qtimgui/QtImGui.cpp ) endif() @@ -27,7 +33,7 @@ set(GUI_LIBRARY_FILES_${ufamily} Qt5::Widgets Qt5::OpenGL ${OPENGL_LIBRARIES} Qt add_library(gui_${family} STATIC ${GUI_SOURCE_FILES} ${PYTHON_CONSOLE_SRC} ${GUI_RESOURCE_FILES}) include(${family}/family.cmake) -target_include_directories(gui_${family} PRIVATE ../${family} ${family} ../3rdparty/QtPropertyBrowser/src) +target_include_directories(gui_${family} PRIVATE ../${family} ${family} ../3rdparty/QtPropertyBrowser/src ../3rdparty/imgui ../3rdparty/qtimgui/) if (BUILD_PYTHON) target_include_directories(gui_${family} PRIVATE ../3rdparty/python-console ../3rdparty/python-console/modified) endif() diff --git a/gui/create_img.sh b/gui/create_img.sh new file mode 100755 index 00000000..1508d023 --- /dev/null +++ b/gui/create_img.sh @@ -0,0 +1,6 @@ +convert -font helvetica -fill red -pointsize 8 -gravity center -draw "text 2,8 'JSON'" resources/open.png resources/open_json.png +convert -font helvetica -fill red -pointsize 8 -gravity center -draw "text 2,8 'PCF'" resources/open.png ice40/resources/open_pcf.png +convert -font helvetica -fill red -pointsize 8 -gravity center -draw "text 2,8 'BASE'" resources/open.png ecp5/resources/open_base.png +convert -font helvetica -fill red -pointsize 8 -gravity center -draw "text 2,8 'LPF'" resources/open.png ecp5/resources/open_lpf.png +convert -font helvetica -fill red -pointsize 8 -gravity center -draw "text 2,8 'ASC'" resources/save.png ice40/resources/save_asc.png +convert -font helvetica -fill red -pointsize 7 -gravity center -draw "text 2,8 'CONFIG'" resources/save.png ecp5/resources/save_config.png
\ No newline at end of file diff --git a/gui/designwidget.cc b/gui/designwidget.cc index c49df085..a45752fc 100644 --- a/gui/designwidget.cc +++ b/gui/designwidget.cc @@ -37,17 +37,14 @@ TreeView::~TreeView() {} void TreeView::mouseMoveEvent(QMouseEvent *event)
{
QModelIndex index = indexAt(event->pos());
- if (index!=current) {
+ if (index != current) {
current = index;
Q_EMIT hoverIndexChanged(index);
}
QTreeView::mouseMoveEvent(event);
}
-void TreeView::leaveEvent(QEvent *event)
-{
- Q_EMIT hoverIndexChanged(QModelIndex());
-}
+void TreeView::leaveEvent(QEvent *event) { Q_EMIT hoverIndexChanged(QModelIndex()); }
DesignWidget::DesignWidget(QWidget *parent) : QWidget(parent), ctx(nullptr), selectionModel(nullptr)
{
@@ -827,24 +824,28 @@ void DesignWidget::onHoverIndexChanged(QModelIndex index) if (index.isValid()) {
TreeModel::Item *item = treeModel->nodeFromIndex(index);
if (item->type() != ElementType::NONE) {
- Q_EMIT hover(getDecals(item->type(), item->id()).at(0));
+ std::vector<DecalXY> decals = getDecals(item->type(), item->id());
+ if (decals.size() > 0)
+ Q_EMIT hover(decals.at(0));
return;
}
}
- Q_EMIT hover(DecalXY());
+ Q_EMIT hover(DecalXY());
}
void DesignWidget::onHoverPropertyChanged(QtBrowserItem *item)
{
- if (item!=nullptr) {
+ if (item != nullptr) {
QtProperty *selectedProperty = item->property();
ElementType type = getElementTypeByName(selectedProperty->propertyId());
if (type != ElementType::NONE) {
IdString value = ctx->id(selectedProperty->valueText().toStdString());
- if (value!=IdString()) {
+ if (value != IdString()) {
auto node = treeModel->nodeForIdType(type, value);
if (node) {
- Q_EMIT hover(getDecals((*node)->type(), (*node)->id()).at(0));
+ std::vector<DecalXY> decals = getDecals((*node)->type(), (*node)->id());
+ if (decals.size() > 0)
+ Q_EMIT hover(decals.at(0));
return;
}
}
diff --git a/gui/designwidget.h b/gui/designwidget.h index 91da556a..0248d2c7 100644 --- a/gui/designwidget.h +++ b/gui/designwidget.h @@ -20,9 +20,9 @@ #ifndef DESIGNWIDGET_H
#define DESIGNWIDGET_H
+#include <QMouseEvent>
#include <QTreeView>
#include <QVariant>
-#include <QMouseEvent>
#include "nextpnr.h"
#include "qtgroupboxpropertybrowser.h"
#include "qtpropertymanager.h"
@@ -35,7 +35,7 @@ NEXTPNR_NAMESPACE_BEGIN class TreeView : public QTreeView
{
Q_OBJECT
-
+
public:
explicit TreeView(QWidget *parent = 0);
~TreeView();
@@ -44,6 +44,7 @@ class TreeView : public QTreeView Q_SIGNALS:
void hoverIndexChanged(QModelIndex index);
+
private:
QModelIndex current;
};
diff --git a/gui/ecp5/mainwindow.cc b/gui/ecp5/mainwindow.cc index b3c53849..fe2f9e57 100644 --- a/gui/ecp5/mainwindow.cc +++ b/gui/ecp5/mainwindow.cc @@ -20,6 +20,7 @@ #include "mainwindow.h"
#include "bitstream.h"
#include "log.h"
+#include <fstream>
#include <QFileDialog>
#include <QInputDialog>
@@ -53,6 +54,12 @@ void MainWindow::newContext(Context *ctx) void MainWindow::createMenu()
{
// Add arch specific actions
+ actionLoadLPF = new QAction("Open LPF", this);
+ actionLoadLPF->setIcon(QIcon(":/icons/resources/open_lpf.png"));
+ actionLoadLPF->setStatusTip("Open LPF file");
+ actionLoadLPF->setEnabled(false);
+ connect(actionLoadLPF, &QAction::triggered, this, &MainWindow::open_lpf);
+
actionLoadBase = new QAction("Open Base Config", this);
actionLoadBase->setIcon(QIcon(":/icons/resources/open_base.png"));
actionLoadBase->setStatusTip("Open Base Config file");
@@ -67,10 +74,12 @@ void MainWindow::createMenu() // Add actions in menus
mainActionBar->addSeparator();
+ mainActionBar->addAction(actionLoadLPF);
mainActionBar->addAction(actionLoadBase);
mainActionBar->addAction(actionSaveConfig);
menuDesign->addSeparator();
+ menuDesign->addAction(actionLoadLPF);
menuDesign->addAction(actionLoadBase);
menuDesign->addAction(actionSaveConfig);
}
@@ -81,11 +90,11 @@ static QStringList getSupportedPackages(ArchArgs::ArchArgsTypes chip) {
QStringList packages;
const ChipInfoPOD *chip_info;
- if (chip == ArchArgs::LFE5U_25F) {
+ if (chip == ArchArgs::LFE5U_25F || chip == ArchArgs::LFE5UM_25F || chip == ArchArgs::LFE5UM5G_25F) {
chip_info = get_chip_info(reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_25k));
- } else if (chip == ArchArgs::LFE5U_45F) {
+ } else if (chip == ArchArgs::LFE5U_45F || chip == ArchArgs::LFE5UM_45F || chip == ArchArgs::LFE5UM5G_45F) {
chip_info = get_chip_info(reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_45k));
- } else if (chip == ArchArgs::LFE5U_85F) {
+ } else if (chip == ArchArgs::LFE5U_85F || chip == ArchArgs::LFE5UM_85F || chip == ArchArgs::LFE5UM5G_85F) {
chip_info = get_chip_info(reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_85k));
} else {
log_error("Unsupported ECP5 chip type.\n");
@@ -100,9 +109,15 @@ static QStringList getSupportedPackages(ArchArgs::ArchArgsTypes chip) void MainWindow::new_proj()
{
QMap<QString, int> arch;
- arch.insert("Lattice ECP5 25K", ArchArgs::LFE5U_25F);
- arch.insert("Lattice ECP5 45K", ArchArgs::LFE5U_45F);
- arch.insert("Lattice ECP5 85K", ArchArgs::LFE5U_85F);
+ arch.insert("Lattice ECP5 LFE5U-25F", ArchArgs::LFE5U_25F);
+ arch.insert("Lattice ECP5 LFE5U-45F", ArchArgs::LFE5U_45F);
+ arch.insert("Lattice ECP5 LFE5U-85F", ArchArgs::LFE5U_85F);
+ arch.insert("Lattice ECP5 LFE5UM-25F", ArchArgs::LFE5UM_25F);
+ arch.insert("Lattice ECP5 LFE5UM-45F", ArchArgs::LFE5UM_45F);
+ arch.insert("Lattice ECP5 LFE5UM-85F", ArchArgs::LFE5UM_85F);
+ arch.insert("Lattice ECP5 LFE5UM5G-25F", ArchArgs::LFE5UM5G_25F);
+ arch.insert("Lattice ECP5 LFE5UM5G-45F", ArchArgs::LFE5UM5G_45F);
+ arch.insert("Lattice ECP5 LFE5UM5G-85F", ArchArgs::LFE5UM5G_85F);
bool ok;
QString item = QInputDialog::getItem(this, "Select new context", "Chip:", arch.keys(), 0, false, &ok);
if (ok && !item.isEmpty()) {
@@ -131,6 +146,22 @@ void MainWindow::load_base_config(std::string filename) actionSaveConfig->setEnabled(true);
}
+void MainWindow::open_lpf()
+{
+ QString fileName = QFileDialog::getOpenFileName(this, QString("Open LPF"), QString(), QString("*.lpf"));
+ if (!fileName.isEmpty()) {
+ std::ifstream in(fileName.toStdString());
+ if (ctx->applyLPF(fileName.toStdString(), in)) {
+ log("Loading LPF successful.\n");
+ actionPack->setEnabled(true);
+ actionLoadLPF->setEnabled(false);
+ } else {
+ actionLoadLPF->setEnabled(true);
+ log("Loading LPF failed.\n");
+ }
+ }
+}
+
void MainWindow::open_base()
{
QString fileName = QFileDialog::getOpenFileName(this, QString("Open Base Config"), QString(), QString("*.config"));
@@ -152,10 +183,19 @@ void MainWindow::save_config() void MainWindow::onDisableActions()
{
+ actionLoadLPF->setEnabled(false);
actionLoadBase->setEnabled(false);
actionSaveConfig->setEnabled(false);
}
+void MainWindow::onJsonLoaded() { actionLoadLPF->setEnabled(true); }
+
void MainWindow::onRouteFinished() { actionLoadBase->setEnabled(true); }
+void MainWindow::onProjectLoaded()
+{
+ if (ctx->settings.find(ctx->id("input/lpf")) != ctx->settings.end())
+ actionLoadLPF->setEnabled(false);
+}
+
NEXTPNR_NAMESPACE_END
diff --git a/gui/ecp5/mainwindow.h b/gui/ecp5/mainwindow.h index f85c2abc..721c6c0b 100644 --- a/gui/ecp5/mainwindow.h +++ b/gui/ecp5/mainwindow.h @@ -38,15 +38,19 @@ class MainWindow : public BaseMainWindow protected:
void onDisableActions() override;
+ void onJsonLoaded() override;
void onRouteFinished() override;
+ void onProjectLoaded() override;
protected Q_SLOTS:
- virtual void new_proj();
+ void new_proj() override;
void newContext(Context *ctx);
+ void open_lpf();
void open_base();
void save_config();
private:
+ QAction *actionLoadLPF;
QAction *actionLoadBase;
QAction *actionSaveConfig;
diff --git a/gui/ecp5/nextpnr.qrc b/gui/ecp5/nextpnr.qrc index 09f96d74..ca7e5b1a 100644 --- a/gui/ecp5/nextpnr.qrc +++ b/gui/ecp5/nextpnr.qrc @@ -1,5 +1,6 @@ <RCC> <qresource prefix="/icons"> + <file>resources/open_lpf.png</file> <file>resources/open_base.png</file> <file>resources/save_config.png</file> </qresource> diff --git a/gui/ecp5/resources/open_base.png b/gui/ecp5/resources/open_base.png Binary files differindex d58d226c..b60cf25a 100644 --- a/gui/ecp5/resources/open_base.png +++ b/gui/ecp5/resources/open_base.png diff --git a/gui/ecp5/resources/open_lpf.png b/gui/ecp5/resources/open_lpf.png Binary files differnew file mode 100644 index 00000000..54b6f6f9 --- /dev/null +++ b/gui/ecp5/resources/open_lpf.png diff --git a/gui/ecp5/resources/save_config.png b/gui/ecp5/resources/save_config.png Binary files differindex 2ade7128..63b5ab56 100644 --- a/gui/ecp5/resources/save_config.png +++ b/gui/ecp5/resources/save_config.png diff --git a/gui/fpgaviewwidget.cc b/gui/fpgaviewwidget.cc index 53ee7282..24fbc35d 100644 --- a/gui/fpgaviewwidget.cc +++ b/gui/fpgaviewwidget.cc @@ -25,6 +25,9 @@ #include <QMouseEvent> #include <QWidget> +#include "QtImGui.h" +#include "imgui.h" + #include "fpgaviewwidget.h" #include "log.h" #include "mainwindow.h" @@ -57,7 +60,7 @@ FPGAViewWidget::FPGAViewWidget(QWidget *parent) auto fmt = format(); fmt.setMajorVersion(3); - fmt.setMinorVersion(1); + fmt.setMinorVersion(2); setFormat(fmt); fmt = format(); @@ -65,8 +68,8 @@ FPGAViewWidget::FPGAViewWidget(QWidget *parent) printf("Could not get OpenGL 3.0 context. Aborting.\n"); log_abort(); } - if (fmt.minorVersion() < 1) { - printf("Could not get OpenGL 3.1 context - trying anyway...\n "); + if (fmt.minorVersion() < 2) { + printf("Could not get OpenGL 3.2 context - trying anyway...\n "); } connect(&paintTimer_, SIGNAL(timeout()), this, SLOT(update())); @@ -103,8 +106,22 @@ void FPGAViewWidget::initializeGL() log_error("Could not compile shader.\n"); } initializeOpenGLFunctions(); - glClearColor(colors_.background.red() / 255, colors_.background.green() / 255, colors_.background.blue() / 255, - 0.0); + QtImGui::initialize(this); + glClearColor(colors_.background.red() / 255, colors_.background.green() / 255, + colors_.background.blue() / 255, 0.0); + + + { + QMutexLocker locker(&rendererDataLock_); + // 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); + } + grid.last_render = 1; + lineShader_.update_vbos(GraphicElement::STYLE_GRID, grid); + } } float FPGAViewWidget::PickedElement::distance(Context *ctx, float wx, float wy) const @@ -276,7 +293,7 @@ QMatrix4x4 FPGAViewWidget::getProjection(void) QMatrix4x4 matrix; const float aspect = float(width()) / float(height()); - matrix.perspective(90, aspect, zoomNear_, zoomFar_); + matrix.perspective(90, aspect, zoomNear_, zoomFar_ + 0.1f); return matrix; } @@ -297,36 +314,40 @@ void FPGAViewWidget::paintGL() float thick11Px = mouseToWorldDimensions(1.1, 0).x(); float thick2Px = mouseToWorldDimensions(2, 0).x(); - // 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); - } - // Flags from pipeline. - PassthroughFlags flags; - // Draw grid. - lineShader_.draw(grid, colors_.grid, thick1Px, matrix); - { QMutexLocker locker(&rendererDataLock_); + // Must be called from a thread holding the OpenGL context + update_vbos(); + } - // 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_->gfxHighlighted[i], colors_.highlight[i], thick11Px, matrix); + // Render the grid. + lineShader_.draw(GraphicElement::STYLE_GRID, colors_.grid, thick1Px, + matrix); + + // Render Arch graphics. + lineShader_.draw(GraphicElement::STYLE_FRAME, colors_.frame, thick11Px, + matrix); + lineShader_.draw(GraphicElement::STYLE_HIDDEN, colors_.hidden, thick11Px, + matrix); + lineShader_.draw(GraphicElement::STYLE_INACTIVE, colors_.inactive, + thick11Px, matrix); + lineShader_.draw(GraphicElement::STYLE_ACTIVE, colors_.active, thick11Px, + matrix); + + // Draw highlighted items. + for (int i = 0; i < 8; i++) { + GraphicElement::style_t style = (GraphicElement::style_t)( + GraphicElement::STYLE_HIGHLIGHTED0 + i); + lineShader_.draw(style, colors_.highlight[i], thick11Px, matrix); + } - lineShader_.draw(rendererData_->gfxSelected, colors_.selected, thick11Px, matrix); - lineShader_.draw(rendererData_->gfxHovered, colors_.hovered, thick2Px, matrix); + lineShader_.draw(GraphicElement::STYLE_SELECTED, colors_.selected, + thick11Px, matrix); + lineShader_.draw(GraphicElement::STYLE_HOVER, colors_.hovered, + thick2Px, matrix); - flags = rendererData_->flags; - } + // Flags from pipeline. + PassthroughFlags flags = rendererData_->flags; // Check flags passed through pipeline. if (flags.zoomOutbound) { @@ -341,6 +362,18 @@ void FPGAViewWidget::paintGL() } } } + QtImGui::newFrame(); + QMutexLocker lock(&rendererArgsLock_); + if (!(rendererArgs_->hoveredDecal == DecalXY()) && rendererArgs_->hintText.size() > 0) + { + ImGui::SetNextWindowPos(ImVec2(rendererArgs_->x, rendererArgs_->y)); + ImGui::BeginTooltip(); + ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); + ImGui::TextUnformatted(rendererArgs_->hintText.c_str()); + ImGui::PopTextWrapPos(); + ImGui::EndTooltip(); + } + ImGui::Render(); } void FPGAViewWidget::pokeRenderer(void) { renderRunner_->poke(); } @@ -424,12 +457,18 @@ void FPGAViewWidget::renderLines(void) highlightedOrSelectedChanged = rendererArgs_->changed; rendererArgs_->changed = false; - flags = rendererArgs_->flags; } // Render decals if necessary. if (decalsChanged) { + int last_render[GraphicElement::STYLE_HIGHLIGHTED0]; + { + QMutexLocker locker(&rendererDataLock_); + for(int i =0; i<GraphicElement::STYLE_HIGHLIGHTED0; i++) + last_render[i] = rendererData_->gfxByStyle[(enum GraphicElement::style_t)i].last_render; + } + auto data = std::unique_ptr<FPGAViewWidget::RendererData>(new FPGAViewWidget::RendererData); // Reset bounding box. data->bbGlobal.clear(); @@ -495,7 +534,8 @@ void FPGAViewWidget::renderLines(void) for (int i = 0; i < 8; i++) data->gfxHighlighted[i] = rendererData_->gfxHighlighted[i]; } - + for(int i =0; i<GraphicElement::STYLE_HIGHLIGHTED0; i++) + data->gfxByStyle[(enum GraphicElement::style_t)i].last_render = ++last_render[i]; rendererData_ = std::move(data); } } @@ -505,7 +545,7 @@ void FPGAViewWidget::renderLines(void) // Whether the currently being hovered decal is also selected. bool hoveringSelected = false; - // Render selected. + // Render selected. rendererData_->bbSelected.clear(); rendererData_->gfxSelected.clear(); for (auto &decal : selectedDecals) { @@ -513,12 +553,14 @@ void FPGAViewWidget::renderLines(void) hoveringSelected = true; renderDecal(rendererData_->gfxSelected, rendererData_->bbSelected, decal); } + rendererData_->gfxSelected.last_render++; // Render hovered. rendererData_->gfxHovered.clear(); if (!hoveringSelected) { renderDecal(rendererData_->gfxHovered, rendererData_->bbGlobal, hoveredDecal); } + rendererData_->gfxHovered.last_render++; // Render highlighted. for (int i = 0; i < 8; i++) { @@ -526,6 +568,7 @@ void FPGAViewWidget::renderLines(void) for (auto &decal : highlightedDecals[i]) { renderDecal(rendererData_->gfxHighlighted[i], rendererData_->bbGlobal, decal); } + rendererData_->gfxHighlighted[i].last_render++; } } @@ -611,6 +654,9 @@ boost::optional<FPGAViewWidget::PickedElement> FPGAViewWidget::pickElement(float void FPGAViewWidget::mousePressEvent(QMouseEvent *event) { + ImGuiIO &io = ImGui::GetIO(); + if (io.WantCaptureMouse) return; + if (event->buttons() & Qt::RightButton || event->buttons() & Qt::MidButton) { lastDragPos_ = event->pos(); } @@ -644,6 +690,9 @@ void FPGAViewWidget::mousePressEvent(QMouseEvent *event) void FPGAViewWidget::mouseMoveEvent(QMouseEvent *event) { + ImGuiIO &io = ImGui::GetIO(); + if (io.WantCaptureMouse) return; + if (event->buttons() & Qt::RightButton || event->buttons() & Qt::MidButton) { const int dx = event->x() - lastDragPos_.x(); const int dy = event->y() - lastDragPos_.y(); @@ -663,6 +712,7 @@ void FPGAViewWidget::mouseMoveEvent(QMouseEvent *event) QMutexLocker locked(&rendererArgsLock_); rendererArgs_->hoveredDecal = DecalXY(); rendererArgs_->changed = true; + rendererArgs_->hintText = ""; pokeRenderer(); return; } @@ -673,6 +723,27 @@ void FPGAViewWidget::mouseMoveEvent(QMouseEvent *event) QMutexLocker locked(&rendererArgsLock_); rendererArgs_->hoveredDecal = closest.decal(ctx_); rendererArgs_->changed = true; + rendererArgs_->x = event->x(); + rendererArgs_->y = event->y(); + if (closest.type == ElementType::BEL) { + rendererArgs_->hintText = std::string("BEL\n") + ctx_->getBelName(closest.bel).c_str(ctx_); + CellInfo *cell = ctx_->getBoundBelCell(closest.bel); + if (cell!=nullptr) + rendererArgs_->hintText += std::string("\nCELL\n") +ctx_->nameOf(cell); + } else if (closest.type == ElementType::WIRE) { + rendererArgs_->hintText = std::string("WIRE\n") + ctx_->getWireName(closest.wire).c_str(ctx_); + NetInfo *net = ctx_->getBoundWireNet(closest.wire); + if (net!=nullptr) + rendererArgs_->hintText += std::string("\nNET\n") +ctx_->nameOf(net); + } else if (closest.type == ElementType::PIP) { + rendererArgs_->hintText = std::string("PIP\n") + ctx_->getPipName(closest.pip).c_str(ctx_); + NetInfo *net = ctx_->getBoundPipNet(closest.pip); + if (net!=nullptr) + rendererArgs_->hintText += std::string("\nNET\n") +ctx_->nameOf(net); + } else if (closest.type == ElementType::GROUP) { + rendererArgs_->hintText = std::string("GROUP\n") + ctx_->getGroupName(closest.group).c_str(ctx_); + } else rendererArgs_->hintText = ""; + pokeRenderer(); } update(); @@ -721,6 +792,9 @@ QVector4D FPGAViewWidget::mouseToWorldDimensions(float x, float y) void FPGAViewWidget::wheelEvent(QWheelEvent *event) { + ImGuiIO &io = ImGui::GetIO(); + if (io.WantCaptureMouse) return; + QPoint degree = event->angleDelta() / 8; if (!degree.isNull()) @@ -756,7 +830,7 @@ void FPGAViewWidget::zoomIn() { zoom(10); } void FPGAViewWidget::zoomOut() { zoom(-10); } -void FPGAViewWidget::zoomToBB(const PickQuadTree::BoundingBox &bb, float margin) +void FPGAViewWidget::zoomToBB(const PickQuadTree::BoundingBox &bb, float margin, bool clamp) { if (fabs(bb.w()) < 0.00005 && fabs(bb.h()) < 0.00005) return; @@ -769,14 +843,15 @@ void FPGAViewWidget::zoomToBB(const PickQuadTree::BoundingBox &bb, float margin) float distance_w = bb.w() / 2 + margin; float distance_h = bb.h() / 2 + margin; zoom_ = std::max(distance_w, distance_h); - clampZoom(); + if (clamp) + clampZoom(); } void FPGAViewWidget::zoomSelected() { { QMutexLocker lock(&rendererDataLock_); - zoomToBB(rendererData_->bbSelected, 0.5f); + zoomToBB(rendererData_->bbSelected, 0.5f, true); } update(); } @@ -785,7 +860,8 @@ void FPGAViewWidget::zoomOutbound() { { QMutexLocker lock(&rendererDataLock_); - zoomToBB(rendererData_->bbGlobal, 1.0f); + zoomToBB(rendererData_->bbGlobal, 1.0f, false); + zoomFar_ = zoom_; } } @@ -794,7 +870,29 @@ void FPGAViewWidget::leaveEvent(QEvent *event) QMutexLocker locked(&rendererArgsLock_); rendererArgs_->hoveredDecal = DecalXY(); rendererArgs_->changed = true; + rendererArgs_->hintText = ""; pokeRenderer(); } +void FPGAViewWidget::update_vbos() +{ + for (int style = GraphicElement::STYLE_FRAME; style + < GraphicElement::STYLE_HIGHLIGHTED0; + style++) { + lineShader_.update_vbos((enum GraphicElement::style_t)(style), + rendererData_->gfxByStyle[style]); + } + + for (int i = 0; i < 8; i++) { + GraphicElement::style_t style = (GraphicElement::style_t)( + GraphicElement::STYLE_HIGHLIGHTED0 + i); + lineShader_.update_vbos(style, rendererData_->gfxHighlighted[i]); + } + + lineShader_.update_vbos(GraphicElement::STYLE_SELECTED, + rendererData_->gfxSelected); + lineShader_.update_vbos(GraphicElement::STYLE_HOVER, + rendererData_->gfxHovered); +} + NEXTPNR_NAMESPACE_END diff --git a/gui/fpgaviewwidget.h b/gui/fpgaviewwidget.h index 51a038fc..e76e6f32 100644 --- a/gui/fpgaviewwidget.h +++ b/gui/fpgaviewwidget.h @@ -127,7 +127,7 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions private: const float zoomNear_ = 0.1f; // do not zoom closer than this - const float zoomFar_ = 30.0f; // do not zoom further than this + float zoomFar_ = 10.0f; // do not zoom further than this const float zoomLvl1_ = 1.0f; const float zoomLvl2_ = 5.0f; @@ -268,6 +268,10 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions // Flags to pass back into the RendererData. PassthroughFlags flags; + // Hint text + std::string hintText; + // cursor pos + int x,y; }; std::unique_ptr<RendererArgs> rendererArgs_; QMutex rendererArgsLock_; @@ -291,7 +295,7 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions QMutex rendererDataLock_; void clampZoom(); - void zoomToBB(const PickQuadTree::BoundingBox &bb, float margin); + void zoomToBB(const PickQuadTree::BoundingBox &bb, float margin, bool clamp); void zoom(int level); void renderLines(void); void renderGraphicElement(LineShaderData &out, PickQuadTree::BoundingBox &bb, const GraphicElement &el, float x, @@ -304,6 +308,7 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions QVector4D mouseToWorldCoordinates(int x, int y); QVector4D mouseToWorldDimensions(float x, float y); QMatrix4x4 getProjection(void); + void update_vbos(); }; NEXTPNR_NAMESPACE_END diff --git a/gui/generic/mainwindow.h b/gui/generic/mainwindow.h index a4ce9958..bb6a4cf1 100644 --- a/gui/generic/mainwindow.h +++ b/gui/generic/mainwindow.h @@ -36,7 +36,7 @@ class MainWindow : public BaseMainWindow void createMenu();
protected Q_SLOTS:
- virtual void new_proj();
+ void new_proj() override;
void newContext(Context *ctx);
};
diff --git a/gui/ice40/mainwindow.h b/gui/ice40/mainwindow.h index bb8ed75f..4a9a7d8e 100644 --- a/gui/ice40/mainwindow.h +++ b/gui/ice40/mainwindow.h @@ -44,7 +44,7 @@ class MainWindow : public BaseMainWindow void onProjectLoaded() override;
protected Q_SLOTS:
- virtual void new_proj();
+ void new_proj() override;
void open_pcf();
void save_asc();
diff --git a/gui/ice40/resources/open_pcf.png b/gui/ice40/resources/open_pcf.png Binary files differindex 093dec39..9a4c64d5 100644 --- a/gui/ice40/resources/open_pcf.png +++ b/gui/ice40/resources/open_pcf.png diff --git a/gui/ice40/resources/save_asc.png b/gui/ice40/resources/save_asc.png Binary files differindex 15b59ca1..c3e6b0ab 100644 --- a/gui/ice40/resources/save_asc.png +++ b/gui/ice40/resources/save_asc.png diff --git a/gui/lineshader.cc b/gui/lineshader.cc index eba96020..fc726df5 100644 --- a/gui/lineshader.cc +++ b/gui/lineshader.cc @@ -162,75 +162,108 @@ bool LineShader::compile(void) return false; } - if (!vao_.create()) - log_abort(); - vao_.bind(); - - if (!buffers_.position.create()) - log_abort(); - if (!buffers_.normal.create()) - log_abort(); - if (!buffers_.miter.create()) - log_abort(); - if (!buffers_.index.create()) - log_abort(); - + program_->bind(); attributes_.position = program_->attributeLocation("position"); attributes_.normal = program_->attributeLocation("normal"); attributes_.miter = program_->attributeLocation("miter"); uniforms_.thickness = program_->uniformLocation("thickness"); uniforms_.projection = program_->uniformLocation("projection"); uniforms_.color = program_->uniformLocation("color"); + program_->release(); + + for (int style = 0; style < GraphicElement::STYLE_MAX; style++) { + buffers_[style].position = QOpenGLBuffer(QOpenGLBuffer::VertexBuffer); + buffers_[style].normal = QOpenGLBuffer(QOpenGLBuffer::VertexBuffer); + buffers_[style].miter = QOpenGLBuffer(QOpenGLBuffer::VertexBuffer); + buffers_[style].index = QOpenGLBuffer(QOpenGLBuffer::IndexBuffer); + + if (!buffers_[style].vao.create()) + log_abort(); + buffers_[style].vao.bind(); + + if (!buffers_[style].position.create()) + log_abort(); + if (!buffers_[style].normal.create()) + log_abort(); + if (!buffers_[style].miter.create()) + log_abort(); + if (!buffers_[style].index.create()) + log_abort(); + + buffers_[style].position.setUsagePattern(QOpenGLBuffer::StaticDraw); + buffers_[style].normal.setUsagePattern(QOpenGLBuffer::StaticDraw); + buffers_[style].miter.setUsagePattern(QOpenGLBuffer::StaticDraw); + buffers_[style].index.setUsagePattern(QOpenGLBuffer::StaticDraw); + + buffers_[style].position.bind(); + buffers_[style].normal.bind(); + buffers_[style].miter.bind(); + buffers_[style].index.bind(); + + buffers_[style].vao.release(); + } - vao_.release(); return true; } -void LineShader::draw(const LineShaderData &line, const QColor &color, float thickness, const QMatrix4x4 &projection) +void LineShader::update_vbos(enum GraphicElement::style_t style, + const LineShaderData &line) { - auto gl = QOpenGLContext::currentContext()->functions(); - if (line.vertices.size() == 0) + if (buffers_[style].last_vbo_update == line.last_render) return; - vao_.bind(); - program_->bind(); + buffers_[style].last_vbo_update = line.last_render; - buffers_.position.bind(); - buffers_.position.allocate(&line.vertices[0], sizeof(Vertex2DPOD) * line.vertices.size()); + buffers_[style].indices = line.indices.size(); + if (buffers_[style].indices == 0) + return; - buffers_.normal.bind(); - buffers_.normal.allocate(&line.normals[0], sizeof(Vertex2DPOD) * line.normals.size()); + buffers_[style].position.bind(); + buffers_[style].position.allocate(&line.vertices[0], sizeof(Vertex2DPOD) * line.vertices.size()); - buffers_.miter.bind(); - buffers_.miter.allocate(&line.miters[0], sizeof(GLfloat) * line.miters.size()); + buffers_[style].normal.bind(); + buffers_[style].normal.allocate(&line.normals[0], sizeof(Vertex2DPOD) * line.normals.size()); - buffers_.index.bind(); - buffers_.index.allocate(&line.indices[0], sizeof(GLuint) * line.indices.size()); + buffers_[style].miter.bind(); + buffers_[style].miter.allocate(&line.miters[0], sizeof(GLfloat) * line.miters.size()); + + buffers_[style].index.bind(); + buffers_[style].index.allocate(&line.indices[0], sizeof(GLuint) * line.indices.size()); +} + +void LineShader::draw(enum GraphicElement::style_t style, const QColor &color, + float thickness, const QMatrix4x4 &projection) +{ + auto gl = QOpenGLContext::currentContext()->functions(); + if (buffers_[style].indices == 0) + return; + program_->bind(); + buffers_[style].vao.bind(); program_->setUniformValue(uniforms_.projection, projection); program_->setUniformValue(uniforms_.thickness, thickness); program_->setUniformValue(uniforms_.color, color.redF(), color.greenF(), color.blueF(), color.alphaF()); - buffers_.position.bind(); - program_->enableAttributeArray("position"); - gl->glVertexAttribPointer(attributes_.position, 2, GL_FLOAT, GL_FALSE, 0, (void *)0); + buffers_[style].position.bind(); + program_->enableAttributeArray(attributes_.position); + program_->setAttributeBuffer(attributes_.position, GL_FLOAT, 0, 2); - buffers_.normal.bind(); - program_->enableAttributeArray("normal"); - gl->glVertexAttribPointer(attributes_.normal, 2, GL_FLOAT, GL_FALSE, 0, (void *)0); + buffers_[style].normal.bind(); + program_->enableAttributeArray(attributes_.normal); + program_->setAttributeBuffer(attributes_.normal, GL_FLOAT, 0, 2); - buffers_.miter.bind(); - program_->enableAttributeArray("miter"); - gl->glVertexAttribPointer(attributes_.miter, 1, GL_FLOAT, GL_FALSE, 0, (void *)0); + buffers_[style].miter.bind(); + program_->enableAttributeArray(attributes_.miter); + program_->setAttributeBuffer(attributes_.miter, GL_FLOAT, 0, 1); - buffers_.index.bind(); - gl->glDrawElements(GL_TRIANGLES, line.indices.size(), GL_UNSIGNED_INT, (void *)0); + buffers_[style].index.bind(); + gl->glDrawElements(GL_TRIANGLES, buffers_[style].indices, GL_UNSIGNED_INT, (void *)0); - program_->disableAttributeArray("miter"); - program_->disableAttributeArray("normal"); - program_->disableAttributeArray("position"); + program_->disableAttributeArray(attributes_.position); + program_->disableAttributeArray(attributes_.normal); + program_->disableAttributeArray(attributes_.miter); + buffers_[style].vao.release(); program_->release(); - vao_.release(); } NEXTPNR_NAMESPACE_END diff --git a/gui/lineshader.h b/gui/lineshader.h index 3f4c4057..eb0f9e09 100644 --- a/gui/lineshader.h +++ b/gui/lineshader.h @@ -20,12 +20,14 @@ #ifndef LINESHADER_H #define LINESHADER_H +#include <array> #include <QOpenGLBuffer> #include <QOpenGLFunctions> #include <QOpenGLShaderProgram> #include <QOpenGLVertexArrayObject> #include <QOpenGLWidget> +#include "log.h" #include "nextpnr.h" NEXTPNR_NAMESPACE_BEGIN @@ -49,7 +51,7 @@ struct LineShaderData std::vector<GLfloat> miters; std::vector<GLuint> indices; - LineShaderData(void) {} + int last_render = 0; void clear(void) { @@ -142,13 +144,18 @@ class LineShader } attributes_; // GL buffers - struct + struct Buffers { QOpenGLBuffer position; QOpenGLBuffer normal; QOpenGLBuffer miter; QOpenGLBuffer index; - } buffers_; + QOpenGLVertexArrayObject vao; + int indices = 0; + + int last_vbo_update = 0; + }; + std::array<Buffers, GraphicElement::STYLE_MAX> buffers_; // GL uniform locations. struct @@ -161,22 +168,9 @@ class LineShader GLuint color; } uniforms_; - QOpenGLVertexArrayObject vao_; - public: LineShader(QObject *parent) : parent_(parent), program_(nullptr) { - buffers_.position = QOpenGLBuffer(QOpenGLBuffer::VertexBuffer); - buffers_.position.setUsagePattern(QOpenGLBuffer::StaticDraw); - - buffers_.normal = QOpenGLBuffer(QOpenGLBuffer::VertexBuffer); - buffers_.normal.setUsagePattern(QOpenGLBuffer::StaticDraw); - - buffers_.miter = QOpenGLBuffer(QOpenGLBuffer::VertexBuffer); - buffers_.miter.setUsagePattern(QOpenGLBuffer::StaticDraw); - - buffers_.index = QOpenGLBuffer(QOpenGLBuffer::IndexBuffer); - buffers_.index.setUsagePattern(QOpenGLBuffer::StaticDraw); } static constexpr const char *vertexShaderSource_ = @@ -200,8 +194,12 @@ class LineShader // Must be called on initialization. bool compile(void); + void update_vbos(enum GraphicElement::style_t style, + const LineShaderData &line); + // Render a LineShaderData with a given M/V/P transformation. - void draw(const LineShaderData &data, const QColor &color, float thickness, const QMatrix4x4 &projection); + void draw(enum GraphicElement::style_t style, const QColor &color, + float thickness, const QMatrix4x4 &projection); }; NEXTPNR_NAMESPACE_END diff --git a/gui/resources/open_json.png b/gui/resources/open_json.png Binary files differindex 90c07267..7352824b 100644 --- a/gui/resources/open_json.png +++ b/gui/resources/open_json.png |
