ElementRenderer改用独立Context
parent
7d4a191f02
commit
f4f1547d21
|
@ -46,7 +46,7 @@ PixelPath GroupElement::getPaintObject() const
|
||||||
PixelPath SimpleElement::getPaintObject(std::vector<Renderer::ElementStyleStrokeDemo> styles) const {
|
PixelPath SimpleElement::getPaintObject(std::vector<Renderer::ElementStyleStrokeDemo> styles) const {
|
||||||
PixelPath result;
|
PixelPath result;
|
||||||
Renderer::ElementStyleStrokeDemo demo(2);
|
Renderer::ElementStyleStrokeDemo demo(2);
|
||||||
auto [img, mov] = renderer->drawElement(painterPath, demo, 1.0, false);
|
auto [img, mov] = renderer->drawElement(painterPath, demo, 1.0);
|
||||||
//qDebug() << img << " ------";
|
//qDebug() << img << " ------";
|
||||||
result.addImage(img, mov);
|
result.addImage(img, mov);
|
||||||
//result.addPath(painterPath);
|
//result.addPath(painterPath);
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "Renderer/RendererGLWidget.h"
|
#include "Renderer/RendererGLWidget.h"
|
||||||
#include "qslider.h"
|
#include "qslider.h"
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
|
#include <QScreen>
|
||||||
#include "NavigationBarWidget.h"
|
#include "NavigationBarWidget.h"
|
||||||
#include <FramelessHelper/Core/utils.h>
|
#include <FramelessHelper/Core/utils.h>
|
||||||
#include <FramelessHelper/Widgets/standardtitlebar.h>
|
#include <FramelessHelper/Widgets/standardtitlebar.h>
|
||||||
|
@ -50,15 +51,15 @@ MainWindow::MainWindow(QWidget* parent, const Qt::WindowFlags flags)
|
||||||
helper->setSystemButton(m_titleBar->maximizeButton(), Global::SystemButtonType::Maximize);
|
helper->setSystemButton(m_titleBar->maximizeButton(), Global::SystemButtonType::Maximize);
|
||||||
helper->setSystemButton(m_titleBar->closeButton(), Global::SystemButtonType::Close);
|
helper->setSystemButton(m_titleBar->closeButton(), Global::SystemButtonType::Close);
|
||||||
|
|
||||||
/*connect(helper, &FramelessWidgetsHelper::ready, this, [this, helper]() {
|
//connect(helper, &FramelessWidgetsHelper::ready, this, [this, helper]() {
|
||||||
helper->moveWindowToDesktopCenter();
|
// helper->moveWindowToDesktopCenter();
|
||||||
});*/
|
// });
|
||||||
|
|
||||||
setWindowIcon(QIcon(":/images/icon.png"));
|
setWindowIcon(QIcon(":/images/icon.png"));
|
||||||
setWindowTitle("ArchitectureColoredPainting");
|
setWindowTitle("ArchitectureColoredPainting");
|
||||||
|
|
||||||
resize(m_central_widget->size());
|
resize(m_central_widget->size());
|
||||||
//move(QGuiApplication::primaryScreen()->availableGeometry().center() - rect().center());
|
move(QGuiApplication::primaryScreen()->availableGeometry().center() - rect().center());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,17 +17,6 @@ Renderer::ElementRenderer::ElementRenderer(QOpenGLWidget* glWidget)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::ElementRenderer::initialize()
|
|
||||||
{
|
|
||||||
initializeOpenGLFunctions();
|
|
||||||
shader = std::make_unique<QOpenGLShaderProgram>();
|
|
||||||
if (!shader->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/element.comp"))
|
|
||||||
qDebug() << "ERROR: " << shader->log();
|
|
||||||
if (!shader->link())
|
|
||||||
qDebug() << "ERROR: " << shader->log();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<glm::vec2> generatePathBuffer(const QPainterPath& path)
|
std::vector<glm::vec2> generatePathBuffer(const QPainterPath& path)
|
||||||
{
|
{
|
||||||
std::vector<glm::vec2> pathBuffer;
|
std::vector<glm::vec2> pathBuffer;
|
||||||
|
@ -130,42 +119,92 @@ QRectF calcBoundingRect(const QPainterPath& path, const std::vector<BaseStyle>&
|
||||||
return QRectF(QPointF(leftTop.x, leftTop.y), QPointF(rightBottom.x, rightBottom.y));
|
return QRectF(QPointF(leftTop.x, leftTop.y), QPointF(rightBottom.x, rightBottom.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<QImage, QPointF> Renderer::ElementRenderer::drawElement(const QPainterPath& path, const ElementStyle& style, float pixelRatio, bool releaseContext)
|
void Renderer::ElementRenderer::initialize()
|
||||||
{
|
{
|
||||||
auto baseStyles = style.toBaseStyles();
|
auto mainContext = QOpenGLContext::currentContext();
|
||||||
QRectF bound = calcBoundingRect(path, baseStyles);
|
auto mainSurface = mainContext->surface();
|
||||||
QPointF leftTop = bound.topLeft();
|
surface.setFormat(mainContext->format());
|
||||||
QSize size(ceil(bound.width() * pixelRatio), ceil(bound.height() * pixelRatio));
|
surface.create();
|
||||||
|
mainContext->doneCurrent();
|
||||||
|
|
||||||
auto pathBuffer = generatePathBuffer(path);
|
thread = std::jthread([&] {
|
||||||
auto styleBuffer = generateStyleBuffer(baseStyles);
|
QOpenGLContext context;
|
||||||
|
context.setFormat(mainContext->format());
|
||||||
|
context.setShareContext(mainContext);
|
||||||
|
context.create();
|
||||||
|
context.makeCurrent(&surface);
|
||||||
|
|
||||||
if (releaseContext) glWidget->makeCurrent();
|
initializeOpenGLFunctions();
|
||||||
|
shader = std::make_unique<QOpenGLShaderProgram>();
|
||||||
|
if (!shader->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/element.comp"))
|
||||||
|
qDebug() << "ERROR: " << shader->log();
|
||||||
|
if (!shader->link())
|
||||||
|
qDebug() << "ERROR: " << shader->log();
|
||||||
|
|
||||||
GLuint ssbo[2];
|
initialized = true;
|
||||||
glCreateBuffers(2, ssbo);
|
|
||||||
glNamedBufferData(ssbo[0], pathBuffer.size() * sizeof(glm::vec2), pathBuffer.data(), GL_STATIC_READ);
|
|
||||||
glNamedBufferData(ssbo[1], styleBuffer.size() * sizeof(GLfloat), styleBuffer.data(), GL_STATIC_READ);
|
|
||||||
|
|
||||||
auto fbo = QOpenGLFramebufferObject(size, QOpenGLFramebufferObject::NoAttachment, GL_TEXTURE_2D);
|
while (true)
|
||||||
fbo.bind();
|
{
|
||||||
glClearColor(0, 0, 0, 0);
|
std::unique_lock<std::mutex> lock(drawMutex);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
draw.wait(lock, [&] {return needDraw; });
|
||||||
fbo.release();
|
{
|
||||||
|
needDraw = false;
|
||||||
|
auto baseStyles = style->toBaseStyles();
|
||||||
|
QRectF bound = calcBoundingRect(*path, baseStyles);
|
||||||
|
QPointF leftTop = bound.topLeft();
|
||||||
|
QSize size(ceil(bound.width() * pixelRatio), ceil(bound.height() * pixelRatio));
|
||||||
|
|
||||||
shader->bind();
|
auto pathBuffer = generatePathBuffer(*path);
|
||||||
shader->setUniformValue("pathSize", (GLint)pathBuffer.size());
|
auto styleBuffer = generateStyleBuffer(baseStyles);
|
||||||
shader->setUniformValue("styleSize", (GLint)styleBuffer.size());
|
|
||||||
shader->setUniformValue("leftTop", leftTop);
|
GLuint ssbo[2];
|
||||||
shader->setUniformValue("pixelRatio", pixelRatio);
|
glCreateBuffers(2, ssbo);
|
||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 10, ssbo[0]);
|
glNamedBufferData(ssbo[0], pathBuffer.size() * sizeof(glm::vec2), pathBuffer.data(), GL_STATIC_READ);
|
||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 11, ssbo[1]);
|
glNamedBufferData(ssbo[1], styleBuffer.size() * sizeof(GLfloat), styleBuffer.data(), GL_STATIC_READ);
|
||||||
glBindImageTexture(0, fbo.texture(), 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
|
|
||||||
glDispatchCompute(ceil(size.width() / 8.), ceil(size.height() / 8.), 1);
|
auto fbo = QOpenGLFramebufferObject(size, QOpenGLFramebufferObject::NoAttachment, GL_TEXTURE_2D);
|
||||||
shader->release();
|
fbo.bind();
|
||||||
|
glClearColor(0, 0, 0, 0);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
fbo.release();
|
||||||
|
|
||||||
|
shader->bind();
|
||||||
|
shader->setUniformValue("pathSize", (GLint)pathBuffer.size());
|
||||||
|
shader->setUniformValue("styleSize", (GLint)styleBuffer.size());
|
||||||
|
shader->setUniformValue("leftTop", leftTop);
|
||||||
|
shader->setUniformValue("pixelRatio", pixelRatio);
|
||||||
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 10, ssbo[0]);
|
||||||
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 11, ssbo[1]);
|
||||||
|
glBindImageTexture(0, fbo.texture(), 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
|
||||||
|
glDispatchCompute(ceil(size.width() / 8.), ceil(size.height() / 8.), 1);
|
||||||
|
shader->release();
|
||||||
|
|
||||||
|
auto image = fbo.toImage(false);
|
||||||
|
glDeleteBuffers(2, ssbo);
|
||||||
|
result = { image, leftTop };
|
||||||
|
drawFinished = true;
|
||||||
|
}
|
||||||
|
draw.notify_all();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
while (!initialized)
|
||||||
|
std::this_thread::yield();
|
||||||
|
|
||||||
|
mainContext->makeCurrent(mainSurface);
|
||||||
|
|
||||||
auto image = fbo.toImage(false);
|
|
||||||
glDeleteBuffers(2, ssbo);
|
|
||||||
if (releaseContext) glWidget->doneCurrent();
|
|
||||||
return { image, leftTop };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<QImage, QPointF> Renderer::ElementRenderer::drawElement(const QPainterPath& path, const ElementStyle& style, float pixelRatio)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(drawMutex);
|
||||||
|
draw.wait(lock, [&] {return drawFinished; });
|
||||||
|
drawFinished = false;
|
||||||
|
this->path = &path;
|
||||||
|
this->style = &style;
|
||||||
|
this->pixelRatio = pixelRatio;
|
||||||
|
needDraw = true;
|
||||||
|
draw.notify_all();
|
||||||
|
draw.wait(lock, [&] {return drawFinished; });
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -3,6 +3,7 @@
|
||||||
#include <QOpenGLFunctions_4_5_Core>
|
#include <QOpenGLFunctions_4_5_Core>
|
||||||
#include <QOPenGLShaderProgram>
|
#include <QOPenGLShaderProgram>
|
||||||
#include "../Painting/ElementStyle.h"
|
#include "../Painting/ElementStyle.h"
|
||||||
|
#include <QOffscreenSurface>
|
||||||
|
|
||||||
namespace Renderer
|
namespace Renderer
|
||||||
{
|
{
|
||||||
|
@ -21,14 +22,26 @@ namespace Renderer
|
||||||
* @param path 图元几何数据
|
* @param path 图元几何数据
|
||||||
* @param style 图元样式
|
* @param style 图元样式
|
||||||
* @param pixelRatio path中的单位坐标对应的像素大小
|
* @param pixelRatio path中的单位坐标对应的像素大小
|
||||||
* @param releaseContext 若在initializeGL, resizeGL或paintGL中调用须传入false
|
|
||||||
* @return QImage 绘制得到的位图
|
* @return QImage 绘制得到的位图
|
||||||
* @return QPointF 位图原点(左上角)在QPainterPath坐标系下的坐标
|
* @return QPointF 位图原点(左上角)在QPainterPath坐标系下的坐标
|
||||||
*/
|
*/
|
||||||
std::pair<QImage, QPointF> drawElement(const QPainterPath& path, const ElementStyle& style, float pixelRatio, bool releaseContext = true);
|
std::pair<QImage, QPointF> drawElement(const QPainterPath& path, const ElementStyle& style, float pixelRatio);
|
||||||
protected:
|
protected:
|
||||||
QOpenGLWidget* glWidget;
|
QOpenGLWidget* glWidget;
|
||||||
std::unique_ptr<QOpenGLShaderProgram> shader;
|
std::unique_ptr<QOpenGLShaderProgram> shader;
|
||||||
|
std::jthread thread;
|
||||||
|
QOffscreenSurface surface;
|
||||||
|
QOpenGLContext context;
|
||||||
|
std::atomic<bool> initialized = false;
|
||||||
|
bool drawFinished = true;
|
||||||
|
bool needDraw = false;
|
||||||
|
std::condition_variable draw;
|
||||||
|
std::mutex drawMutex;
|
||||||
|
|
||||||
|
const QPainterPath* path;
|
||||||
|
const ElementStyle* style;
|
||||||
|
float pixelRatio;
|
||||||
|
std::pair<QImage, QPointF> result;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ int main(int argc, char* argv[])
|
||||||
//FramelessHelper::Core::setApplicationOSThemeAware();
|
//FramelessHelper::Core::setApplicationOSThemeAware();
|
||||||
FramelessConfig::instance()->set(Global::Option::ForceNonNativeBackgroundBlur);
|
FramelessConfig::instance()->set(Global::Option::ForceNonNativeBackgroundBlur);
|
||||||
//FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
|
//FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
|
||||||
FramelessConfig::instance()->set(Global::Option::CenterWindowBeforeShow);
|
//FramelessConfig::instance()->set(Global::Option::CenterWindowBeforeShow);
|
||||||
MainWindow w;
|
MainWindow w;
|
||||||
w.show();
|
w.show();
|
||||||
return a.exec();
|
return a.exec();
|
||||||
|
|
Loading…
Reference in New Issue