diff --git a/ArchitectureColoredPainting/src/Editor/GraphicElement.cpp b/ArchitectureColoredPainting/src/Editor/GraphicElement.cpp index eecb1fd..06de7ad 100644 --- a/ArchitectureColoredPainting/src/Editor/GraphicElement.cpp +++ b/ArchitectureColoredPainting/src/Editor/GraphicElement.cpp @@ -46,7 +46,7 @@ PixelPath GroupElement::getPaintObject() const PixelPath SimpleElement::getPaintObject(std::vector styles) const { PixelPath result; 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 << " ------"; result.addImage(img, mov); //result.addPath(painterPath); diff --git a/ArchitectureColoredPainting/src/MainWindow.cpp b/ArchitectureColoredPainting/src/MainWindow.cpp index 505f1dd..12b8bad 100644 --- a/ArchitectureColoredPainting/src/MainWindow.cpp +++ b/ArchitectureColoredPainting/src/MainWindow.cpp @@ -2,6 +2,7 @@ #include "Renderer/RendererGLWidget.h" #include "qslider.h" #include +#include #include "NavigationBarWidget.h" #include #include @@ -50,15 +51,15 @@ MainWindow::MainWindow(QWidget* parent, const Qt::WindowFlags flags) helper->setSystemButton(m_titleBar->maximizeButton(), Global::SystemButtonType::Maximize); helper->setSystemButton(m_titleBar->closeButton(), Global::SystemButtonType::Close); - /*connect(helper, &FramelessWidgetsHelper::ready, this, [this, helper]() { - helper->moveWindowToDesktopCenter(); - });*/ + //connect(helper, &FramelessWidgetsHelper::ready, this, [this, helper]() { + // helper->moveWindowToDesktopCenter(); + // }); setWindowIcon(QIcon(":/images/icon.png")); setWindowTitle("ArchitectureColoredPainting"); resize(m_central_widget->size()); - //move(QGuiApplication::primaryScreen()->availableGeometry().center() - rect().center()); + move(QGuiApplication::primaryScreen()->availableGeometry().center() - rect().center()); } diff --git a/ArchitectureColoredPainting/src/Renderer/Preview/ElementRenderer.cpp b/ArchitectureColoredPainting/src/Renderer/Preview/ElementRenderer.cpp index 19ea176..ccd742e 100644 --- a/ArchitectureColoredPainting/src/Renderer/Preview/ElementRenderer.cpp +++ b/ArchitectureColoredPainting/src/Renderer/Preview/ElementRenderer.cpp @@ -17,17 +17,6 @@ Renderer::ElementRenderer::ElementRenderer(QOpenGLWidget* glWidget) { } -void Renderer::ElementRenderer::initialize() -{ - initializeOpenGLFunctions(); - shader = std::make_unique(); - if (!shader->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/element.comp")) - qDebug() << "ERROR: " << shader->log(); - if (!shader->link()) - qDebug() << "ERROR: " << shader->log(); - -} - std::vector generatePathBuffer(const QPainterPath& path) { std::vector pathBuffer; @@ -130,42 +119,92 @@ QRectF calcBoundingRect(const QPainterPath& path, const std::vector& return QRectF(QPointF(leftTop.x, leftTop.y), QPointF(rightBottom.x, rightBottom.y)); } -std::pair Renderer::ElementRenderer::drawElement(const QPainterPath& path, const ElementStyle& style, float pixelRatio, bool releaseContext) +void Renderer::ElementRenderer::initialize() { - auto baseStyles = style.toBaseStyles(); - QRectF bound = calcBoundingRect(path, baseStyles); - QPointF leftTop = bound.topLeft(); - QSize size(ceil(bound.width() * pixelRatio), ceil(bound.height() * pixelRatio)); + auto mainContext = QOpenGLContext::currentContext(); + auto mainSurface = mainContext->surface(); + surface.setFormat(mainContext->format()); + surface.create(); + mainContext->doneCurrent(); - auto pathBuffer = generatePathBuffer(path); - auto styleBuffer = generateStyleBuffer(baseStyles); + thread = std::jthread([&] { + QOpenGLContext context; + context.setFormat(mainContext->format()); + context.setShareContext(mainContext); + context.create(); + context.makeCurrent(&surface); - if (releaseContext) glWidget->makeCurrent(); + initializeOpenGLFunctions(); + shader = std::make_unique(); + if (!shader->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/element.comp")) + qDebug() << "ERROR: " << shader->log(); + if (!shader->link()) + qDebug() << "ERROR: " << shader->log(); - GLuint ssbo[2]; - 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); + initialized = true; - auto fbo = QOpenGLFramebufferObject(size, QOpenGLFramebufferObject::NoAttachment, GL_TEXTURE_2D); - fbo.bind(); - glClearColor(0, 0, 0, 0); - glClear(GL_COLOR_BUFFER_BIT); - fbo.release(); + while (true) + { + std::unique_lock lock(drawMutex); + draw.wait(lock, [&] {return needDraw; }); + { + 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(); - 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 pathBuffer = generatePathBuffer(*path); + auto styleBuffer = generateStyleBuffer(baseStyles); + + GLuint ssbo[2]; + 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); + 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 Renderer::ElementRenderer::drawElement(const QPainterPath& path, const ElementStyle& style, float pixelRatio) +{ + std::unique_lock 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; +} \ No newline at end of file diff --git a/ArchitectureColoredPainting/src/Renderer/Preview/ElementRenderer.h b/ArchitectureColoredPainting/src/Renderer/Preview/ElementRenderer.h index ca88d44..6cf9410 100644 --- a/ArchitectureColoredPainting/src/Renderer/Preview/ElementRenderer.h +++ b/ArchitectureColoredPainting/src/Renderer/Preview/ElementRenderer.h @@ -3,6 +3,7 @@ #include #include #include "../Painting/ElementStyle.h" +#include namespace Renderer { @@ -21,14 +22,26 @@ namespace Renderer * @param path 图元几何数据 * @param style 图元样式 * @param pixelRatio path中的单位坐标对应的像素大小 - * @param releaseContext 若在initializeGL, resizeGL或paintGL中调用须传入false * @return QImage 绘制得到的位图 * @return QPointF 位图原点(左上角)在QPainterPath坐标系下的坐标 */ - std::pair drawElement(const QPainterPath& path, const ElementStyle& style, float pixelRatio, bool releaseContext = true); + std::pair drawElement(const QPainterPath& path, const ElementStyle& style, float pixelRatio); protected: QOpenGLWidget* glWidget; std::unique_ptr shader; + std::jthread thread; + QOffscreenSurface surface; + QOpenGLContext context; + std::atomic 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 result; }; } diff --git a/ArchitectureColoredPainting/src/main.cpp b/ArchitectureColoredPainting/src/main.cpp index 8f41fc4..e43c971 100644 --- a/ArchitectureColoredPainting/src/main.cpp +++ b/ArchitectureColoredPainting/src/main.cpp @@ -52,7 +52,7 @@ int main(int argc, char* argv[]) //FramelessHelper::Core::setApplicationOSThemeAware(); FramelessConfig::instance()->set(Global::Option::ForceNonNativeBackgroundBlur); //FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow); - FramelessConfig::instance()->set(Global::Option::CenterWindowBeforeShow); + //FramelessConfig::instance()->set(Global::Option::CenterWindowBeforeShow); MainWindow w; w.show(); return a.exec();