aboutsummaryrefslogtreecommitdiffstats
path: root/gui/fpgaviewwidget.h
diff options
context:
space:
mode:
Diffstat (limited to 'gui/fpgaviewwidget.h')
-rw-r--r--gui/fpgaviewwidget.h228
1 files changed, 27 insertions, 201 deletions
diff --git a/gui/fpgaviewwidget.h b/gui/fpgaviewwidget.h
index c1165ef3..a360eea7 100644
--- a/gui/fpgaviewwidget.h
+++ b/gui/fpgaviewwidget.h
@@ -34,183 +34,10 @@
#include "nextpnr.h"
#include "quadtree.h"
+#include "lineshader.h"
NEXTPNR_NAMESPACE_BEGIN
-// Vertex2DPOD is a structure of X, Y coordinates that can be passed to OpenGL
-// directly.
-NPNR_PACKED_STRUCT(struct Vertex2DPOD {
- GLfloat x;
- GLfloat y;
-
- Vertex2DPOD(GLfloat X, GLfloat Y) : x(X), y(Y) {}
-});
-
-// LineShaderData is a built set of vertices that can be rendered by the
-// LineShader.
-// Each LineShaderData can have its' own color and thickness.
-struct LineShaderData
-{
- std::vector<Vertex2DPOD> vertices;
- std::vector<Vertex2DPOD> normals;
- std::vector<GLfloat> miters;
- std::vector<GLuint> indices;
-
- LineShaderData(void) {}
-
- void clear(void)
- {
- vertices.clear();
- normals.clear();
- miters.clear();
- indices.clear();
- }
-};
-
-// PolyLine is a set of segments defined by points, that can be built to a
-// ShaderLine for GPU rendering.
-class PolyLine
-{
- private:
- std::vector<QVector2D> points_;
- bool closed_;
-
- void buildPoint(LineShaderData *building, const QVector2D *prev, const QVector2D *cur, const QVector2D *next) const;
-
- public:
- // Create an empty PolyLine.
- PolyLine(bool closed = false) : closed_(closed) {}
-
- // Create a non-closed polyline consisting of one segment.
- PolyLine(float x0, float y0, float x1, float y1) : closed_(false)
- {
- point(x0, y0);
- point(x1, y1);
- }
-
- // Add a point to the PolyLine.
- void point(float x, float y) { points_.push_back(QVector2D(x, y)); }
-
- // Built PolyLine to shader data.
- void build(LineShaderData &target) const;
-
- // Set whether line is closed (ie. a loop).
- void setClosed(bool closed) { closed_ = closed; }
-};
-
-// LineShader is an OpenGL shader program that renders LineShaderData on the
-// GPU.
-// The LineShader expects two vertices per line point. It will push those
-// vertices along the given normal * miter. This is used to 'stretch' the line
-// to be as wide as the given thickness. The normal and miter are calculated
-// by the PolyLine build method in order to construct a constant thickness line
-// with miter edge joints.
-//
-// +------+------+
-//
-// |
-// PolyLine.build()
-// |
-// V
-//
-// ^ ^ ^
-// | | | <--- normal vectors (x2, pointing in the same
-// +/+----+/+----+/+ direction)
-//
-// |
-// vertex shader
-// |
-// V
-//
-// +------+------+ ^ by normal * miter * thickness/2
-// | | |
-// +------+------+ V by normal * miter * thickness/2
-//
-// (miter is flipped for every second vertex generated)
-class LineShader
-{
- private:
- QObject *parent_;
- QOpenGLShaderProgram *program_;
-
- // GL attribute locations.
- struct
- {
- // original position of line vertex
- GLuint position;
- // normal by which vertex should be translated
- GLuint normal;
- // scalar defining:
- // - how stretched the normal vector should be to
- // compensate for bends
- // - which way the normal should be applied (+1 for one vertex, -1
- // for the other)
- GLuint miter;
- } attributes_;
-
- // GL buffers
- struct
- {
- QOpenGLBuffer position;
- QOpenGLBuffer normal;
- QOpenGLBuffer miter;
- QOpenGLBuffer index;
- } buffers_;
-
- // GL uniform locations.
- struct
- {
- // combines m/v/p matrix to apply
- GLuint projection;
- // desired thickness of line
- GLuint thickness;
- // color of line
- 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_ =
- "#version 110\n"
- "attribute highp vec2 position;\n"
- "attribute highp vec2 normal;\n"
- "attribute highp float miter;\n"
- "uniform highp float thickness;\n"
- "uniform highp mat4 projection;\n"
- "void main() {\n"
- " vec2 p = position.xy + vec2(normal * thickness/2.0 / miter);\n"
- " gl_Position = projection * vec4(p, 0.0, 1.0);\n"
- "}\n";
-
- static constexpr const char *fragmentShaderSource_ = "#version 110\n"
- "uniform lowp vec4 color;\n"
- "void main() {\n"
- " gl_FragColor = color;\n"
- "}\n";
-
- // Must be called on initialization.
- bool compile(void);
-
- // Render a LineShaderData with a given M/V/P transformation.
- void draw(const LineShaderData &data, const QColor &color, float thickness, const QMatrix4x4 &projection);
-};
-
class PeriodicRunner : public QThread
{
Q_OBJECT
@@ -268,18 +95,17 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions
FPGAViewWidget(QWidget *parent = 0);
~FPGAViewWidget();
- QSize minimumSizeHint() const override;
- QSize sizeHint() const override;
-
protected:
+ // Qt callbacks.
void initializeGL() Q_DECL_OVERRIDE;
void paintGL() Q_DECL_OVERRIDE;
void resizeGL(int width, int height) Q_DECL_OVERRIDE;
void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE;
- void drawDecal(LineShaderData &data, const DecalXY &decal);
- void drawDecal(LineShaderData out[], const DecalXY &decal);
+ QSize minimumSizeHint() const override;
+ QSize sizeHint() const override;
+
public Q_SLOTS:
void newContext(Context *ctx);
@@ -295,26 +121,13 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions
void clickedBel(BelId bel);
private:
- void renderLines(void);
- void zoom(int level);
-
- QPoint lastPos_;
- LineShader lineShader_;
- QMatrix4x4 viewMove_;
- float zoom_;
- QMatrix4x4 getProjection(void);
- QVector4D mouseToWorldCoordinates(int x, int y);
- QVector4D mouseToWorldDimensions(int x, int y);
-
const float zoomNear_ = 1.0f; // do not zoom closer than this
const float zoomFar_ = 10000.0f; // do not zoom further than this
-
const float zoomLvl1_ = 100.0f;
const float zoomLvl2_ = 50.0f;
Context *ctx_;
QTimer paintTimer_;
-
std::unique_ptr<PeriodicRunner> renderRunner_;
using QuadTreeBels = QuadTree<float, BelId>;
@@ -326,12 +139,17 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions
float offsetY = decal.y;
for (auto &el : ctx_->getDecalGraphics(decal.decal)) {
- if (el.type == GraphicElement::G_BOX) {
+ 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_;
+ LineShader lineShader_;
+ QMatrix4x4 viewMove_;
+ float zoom_;
+
struct
{
QColor background;
@@ -346,23 +164,31 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions
struct RendererData
{
- LineShaderData decals[4];
- LineShaderData selected;
- LineShaderData highlighted[8];
+ LineShaderData gfxByStyle[GraphicElement::STYLE_MAX];
+ LineShaderData gfxSelected;
+ LineShaderData gfxHighlighted[8];
std::unique_ptr<QuadTreeBels> qtBels;
};
+ std::unique_ptr<RendererData> rendererData_;
+ QMutex rendererDataLock_;
struct RendererArgs
{
- std::vector<DecalXY> selectedItems;
- std::vector<DecalXY> highlightedItems[8];
+ std::vector<DecalXY> selectedDecals;
+ std::vector<DecalXY> highlightedDecals[8];
bool highlightedOrSelectedChanged;
};
-
- std::unique_ptr<RendererData> rendererData_;
- QMutex rendererDataLock_;
std::unique_ptr<RendererArgs> rendererArgs_;
QMutex rendererArgsLock_;
+
+ void zoom(int level);
+ void renderLines(void);
+ void drawGraphicElement(LineShaderData &out, const GraphicElement &el, float x, float y);
+ void drawDecal(LineShaderData &out, const DecalXY &decal);
+ void drawArchDecal(LineShaderData out[GraphicElement::STYLE_MAX], const DecalXY &decal);
+ QVector4D mouseToWorldCoordinates(int x, int y);
+ QVector4D mouseToWorldDimensions(int x, int y);
+ QMatrix4x4 getProjection(void);
};
NEXTPNR_NAMESPACE_END