aboutsummaryrefslogtreecommitdiffstats
path: root/gui
diff options
context:
space:
mode:
Diffstat (limited to 'gui')
-rw-r--r--gui/CMakeLists.txt8
-rwxr-xr-xgui/create_img.sh6
-rw-r--r--gui/designwidget.cc21
-rw-r--r--gui/designwidget.h5
-rw-r--r--gui/ecp5/mainwindow.cc52
-rw-r--r--gui/ecp5/mainwindow.h6
-rw-r--r--gui/ecp5/nextpnr.qrc1
-rw-r--r--gui/ecp5/resources/open_base.pngbin2022 -> 2175 bytes
-rw-r--r--gui/ecp5/resources/open_lpf.pngbin0 -> 2117 bytes
-rw-r--r--gui/ecp5/resources/save_config.pngbin1428 -> 1645 bytes
-rw-r--r--gui/fpgaviewwidget.cc174
-rw-r--r--gui/fpgaviewwidget.h9
-rw-r--r--gui/generic/mainwindow.h2
-rw-r--r--gui/ice40/mainwindow.h2
-rw-r--r--gui/ice40/resources/open_pcf.pngbin1984 -> 2139 bytes
-rw-r--r--gui/ice40/resources/save_asc.pngbin1384 -> 1509 bytes
-rw-r--r--gui/lineshader.cc117
-rw-r--r--gui/lineshader.h32
-rw-r--r--gui/resources/open_json.pngbin2093 -> 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
index d58d226c..b60cf25a 100644
--- a/gui/ecp5/resources/open_base.png
+++ b/gui/ecp5/resources/open_base.png
Binary files differ
diff --git a/gui/ecp5/resources/open_lpf.png b/gui/ecp5/resources/open_lpf.png
new file mode 100644
index 00000000..54b6f6f9
--- /dev/null
+++ b/gui/ecp5/resources/open_lpf.png
Binary files differ
diff --git a/gui/ecp5/resources/save_config.png b/gui/ecp5/resources/save_config.png
index 2ade7128..63b5ab56 100644
--- a/gui/ecp5/resources/save_config.png
+++ b/gui/ecp5/resources/save_config.png
Binary files differ
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
index 093dec39..9a4c64d5 100644
--- a/gui/ice40/resources/open_pcf.png
+++ b/gui/ice40/resources/open_pcf.png
Binary files differ
diff --git a/gui/ice40/resources/save_asc.png b/gui/ice40/resources/save_asc.png
index 15b59ca1..c3e6b0ab 100644
--- a/gui/ice40/resources/save_asc.png
+++ b/gui/ice40/resources/save_asc.png
Binary files differ
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
index 90c07267..7352824b 100644
--- a/gui/resources/open_json.png
+++ b/gui/resources/open_json.png
Binary files differ