ElementRenderer改用独立Context

TaoZhang-Branch
wuyize 2023-03-08 12:37:14 +08:00
parent 7d4a191f02
commit f4f1547d21
5 changed files with 103 additions and 50 deletions

View File

@ -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);

View File

@ -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());
} }

View File

@ -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;
}

View File

@ -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, resizeGLpaintGLfalse
* @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;
}; };
} }

View File

@ -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();