Basic OpenGL Graph Rendering (#1432)

This commit is contained in:
Florian Märkl 2019-04-07 12:53:42 +02:00 committed by GitHub
parent 0583b06191
commit 14c64e01f3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 124 additions and 26 deletions

View File

@ -7,10 +7,30 @@
#include <QMouseEvent>
#include <QPropertyAnimation>
#ifndef QT_NO_OPENGL
#include <QOpenGLContext>
#include <QOpenGLWidget>
#include <QOpenGLPaintDevice>
#include <QOpenGLExtraFunctions>
#endif
GraphView::GraphView(QWidget *parent)
: QAbstractScrollArea(parent)
, graphLayoutSystem(new GraphGridLayout())
, useGL(false)
#ifndef QT_NO_OPENGL
, cacheTexture(0)
, cacheFBO(0)
#endif
{
#ifndef QT_NO_OPENGL
if (useGL) {
glWidget = new QOpenGLWidget(this);
setViewport(glWidget);
} else {
glWidget = nullptr;
}
#endif
}
GraphView::~GraphView()
@ -113,19 +133,88 @@ QPolygonF GraphView::recalculatePolygon(QPolygonF polygon)
return ret;
}
void GraphView::paintEvent(QPaintEvent *event)
void GraphView::paintEvent(QPaintEvent *)
{
Q_UNUSED(event);
qreal dpr = devicePixelRatioF();
if (useCache && qFuzzyCompare(dpr, pixmap.devicePixelRatioF())) {
drawGraph();
return;
#ifndef QT_NO_OPENGL
if (useGL) {
glWidget->makeCurrent();
}
pixmap = QPixmap(int(viewport()->width() * dpr), int(viewport()->height() * dpr));
pixmap.setDevicePixelRatio(dpr);
QPainter p(&pixmap);
#endif
p.setRenderHint(QPainter::Antialiasing);
if(!useCache || !qFuzzyCompare(devicePixelRatioF(), pixmap.devicePixelRatioF())) {
paintGraphCache();
}
if (useGL) {
#ifndef QT_NO_OPENGL
auto gl = glWidget->context()->extraFunctions();
gl->glBindFramebuffer(GL_READ_FRAMEBUFFER, cacheFBO);
gl->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, glWidget->defaultFramebufferObject());
gl->glBlitFramebuffer(0, 0, viewport()->width(), viewport()->height(),
0, 0, viewport()->width(), viewport()->height(),
GL_COLOR_BUFFER_BIT, GL_NEAREST);
glWidget->doneCurrent();
#endif
} else {
QRectF target(0.0, 0.0, viewport()->width(), viewport()->height());
QRectF source(0.0, 0.0, viewport()->width() * pixmap.devicePixelRatioF(),
viewport()->height() * pixmap.devicePixelRatioF());
QPainter p(viewport());
p.drawPixmap(target, pixmap, source);
}
if(!useCache) { // TODO: does this condition make sense?
emit refreshBlock();
}
}
void GraphView::paintGraphCache()
{
#ifndef QT_NO_OPENGL
QOpenGLPaintDevice *paintDevice = nullptr;
#endif
QPainter p;
if (useGL) {
#ifndef QT_NO_OPENGL
auto gl = QOpenGLContext::currentContext()->functions();
bool resizeTex = false;
if (!cacheTexture) {
gl->glGenTextures(1, &cacheTexture);
gl->glBindTexture(GL_TEXTURE_2D, cacheTexture);
gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
resizeTex = true;
} else if(cacheSize != viewport()->size()) {
gl->glBindTexture(GL_TEXTURE_2D, cacheTexture);
resizeTex = true;
}
if (resizeTex) {
cacheSize = viewport()->size();
gl->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, viewport()->width(), viewport()->height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
gl->glGenFramebuffers(1, &cacheFBO);
gl->glBindFramebuffer(GL_FRAMEBUFFER, cacheFBO);
gl->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, cacheTexture, 0);
} else {
gl->glBindFramebuffer(GL_FRAMEBUFFER, cacheFBO);
}
gl->glViewport(0, 0, viewport()->width(), viewport()->height());
gl->glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
gl->glClear(GL_COLOR_BUFFER_BIT);
paintDevice = new QOpenGLPaintDevice(viewport()->size());
p.begin(paintDevice);
#endif
} else {
auto dpr = devicePixelRatioF();
pixmap = QPixmap(int(viewport()->width() * dpr), int(viewport()->height() * dpr));
pixmap.setDevicePixelRatio(dpr);
p.begin(&pixmap);
p.setRenderHint(QPainter::Antialiasing);
}
int render_width = viewport()->width();
int render_height = viewport()->height();
@ -190,17 +279,11 @@ void GraphView::paintEvent(QPaintEvent *event)
}
}
}
drawGraph();
emit refreshBlock();
}
void GraphView::drawGraph()
{
QRectF target(0.0, 0.0, viewport()->width(), viewport()->height());
QRectF source(0.0, 0.0, viewport()->width() * pixmap.devicePixelRatioF(),
viewport()->height() * pixmap.devicePixelRatioF());
QPainter p(viewport());
p.drawPixmap(target, pixmap, source);
p.end();
#ifndef QT_NO_OPENGL
delete paintDevice;
#endif
}

View File

@ -17,6 +17,10 @@
#include "core/Cutter.h"
#include "widgets/GraphLayout.h"
#ifndef QT_NO_OPENGL
class QOpenGLWidget;
#endif
class GraphView : public QAbstractScrollArea
{
Q_OBJECT
@ -36,6 +40,7 @@ public:
explicit GraphView(QWidget *parent);
~GraphView() override;
void paintEvent(QPaintEvent *event) override;
void showBlock(GraphBlock &block);
@ -80,7 +85,6 @@ protected:
virtual void wheelEvent(QWheelEvent *event) override;
virtual EdgeConfiguration edgeConfiguration(GraphView::GraphBlock &from, GraphView::GraphBlock *to);
void drawGraph();
bool event(QEvent *event) override;
// Mouse events
@ -95,12 +99,9 @@ protected:
int width = 0;
int height = 0;
/**
* @brief pixmap that caches the graph nodes
*/
QPixmap pixmap;
private:
void paintGraphCache();
bool checkPointClicked(QPointF &point, int x, int y, bool above_y = false);
ut64 entry;
@ -117,6 +118,20 @@ private:
// Todo: remove charheight/charwidth cause it should be handled in child class
qreal charWidth = 10.0;
bool useGL;
/**
* @brief pixmap that caches the graph nodes
*/
QPixmap pixmap;
#ifndef QT_NO_OPENGL
uint32_t cacheTexture;
uint32_t cacheFBO;
QSize cacheSize;
QOpenGLWidget *glWidget;
#endif
QPolygonF recalculatePolygon(QPolygonF polygon);
};