From 26a70498bdac5a3dc5cfed0bcc7f5fbd658dd981 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Wed, 3 Apr 2024 22:06:41 +0200 Subject: [PATCH 1/5] Improve headers of Paintable --- src/widget/paintable.cpp | 5 +++++ src/widget/paintable.h | 9 ++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/widget/paintable.cpp b/src/widget/paintable.cpp index 4bf5b4d0a34..e78fb82fabf 100644 --- a/src/widget/paintable.cpp +++ b/src/widget/paintable.cpp @@ -1,6 +1,11 @@ +#include "widget/paintable.h" + #include #include +#include +#include #include +#include #include #include "util/math.h" diff --git a/src/widget/paintable.h b/src/widget/paintable.h index 3dcb185cdf7..5ad755b482c 100644 --- a/src/widget/paintable.h +++ b/src/widget/paintable.h @@ -1,18 +1,17 @@ #pragma once -#include -#include -#include -#include #include #include -#include #include #include #include "skin/legacy/imgsource.h" #include "skin/legacy/pixmapsource.h" +class QPainter; +class QPixmap; +class QSvgRenderer; + // Wrapper around QImage and QSvgRenderer to support rendering SVG images in // high fidelity. class Paintable { From ec4bf17c3b0cdf6167c55851ef7f4c54b1283f11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Wed, 3 Apr 2024 22:24:05 +0200 Subject: [PATCH 2/5] Add missing null check when using m_pPlayPosMarkTexture --- src/waveform/renderers/allshader/waveformrendermark.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/waveform/renderers/allshader/waveformrendermark.cpp b/src/waveform/renderers/allshader/waveformrendermark.cpp index eac87b8e4c5..36f0fdcf0c5 100644 --- a/src/waveform/renderers/allshader/waveformrendermark.cpp +++ b/src/waveform/renderers/allshader/waveformrendermark.cpp @@ -225,11 +225,12 @@ void allshader::WaveformRenderMark::paintGL() { const float currentMarkPoint = std::floor( static_cast(m_waveformRenderer->getPlayMarkerPosition() * m_waveformRenderer->getLength())); + if (m_pPlayPosMarkTexture) { + const float markHalfWidth = m_pPlayPosMarkTexture->width() / devicePixelRatio / 2.f; + const float drawOffset = currentMarkPoint - markHalfWidth; - const float markHalfWidth = m_pPlayPosMarkTexture->width() / devicePixelRatio / 2.f; - const float drawOffset = currentMarkPoint - markHalfWidth; - - drawTexture(drawOffset, 0.f, m_pPlayPosMarkTexture.get()); + drawTexture(drawOffset, 0.f, m_pPlayPosMarkTexture.get()); + } } // Generate the texture used to draw the play position marker. From 07f05f1a0ef39e12b870718c9f1203f6f9335b14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Wed, 3 Apr 2024 22:26:07 +0200 Subject: [PATCH 3/5] Introduce OpenGLTexture2D to get around nested allocations when creating textures --- CMakeLists.txt | 2 +- src/util/opengltexture2d.cpp | 33 +++++++++ src/util/opengltexture2d.h | 16 +++++ src/util/texture.cpp | 37 ---------- src/util/texture.h | 12 ---- .../allshader/waveformrendererpreroll.cpp | 15 +++-- .../allshader/waveformrendererpreroll.h | 3 +- .../allshader/waveformrendermark.cpp | 30 +++++---- .../renderers/allshader/waveformrendermark.h | 9 +-- src/widget/wspinnyglsl.cpp | 67 +++++++------------ src/widget/wspinnyglsl.h | 16 ++--- src/widget/wvumeterglsl.cpp | 34 +++------- src/widget/wvumeterglsl.h | 8 +-- 13 files changed, 129 insertions(+), 153 deletions(-) create mode 100644 src/util/opengltexture2d.cpp create mode 100644 src/util/opengltexture2d.h delete mode 100644 src/util/texture.cpp delete mode 100644 src/util/texture.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 22a36bb9505..ce2508bb663 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1485,7 +1485,7 @@ else() src/shaders/textureshader.cpp src/shaders/unicolorshader.cpp src/shaders/vinylqualityshader.cpp - src/util/texture.cpp + src/util/opengltexture2d.cpp src/waveform/renderers/allshader/matrixforwidgetgeometry.cpp src/waveform/renderers/allshader/waveformrenderbackground.cpp src/waveform/renderers/allshader/waveformrenderbeat.cpp diff --git a/src/util/opengltexture2d.cpp b/src/util/opengltexture2d.cpp new file mode 100644 index 00000000000..fad793f689f --- /dev/null +++ b/src/util/opengltexture2d.cpp @@ -0,0 +1,33 @@ +#include "util/opengltexture2d.h" + +#include + +#include "widget/paintable.h" + +OpenGLTexture2D::OpenGLTexture2D() + : QOpenGLTexture(QOpenGLTexture::Target2D){}; + +void OpenGLTexture2D::setData(const QImage& image) { + destroy(); + if (!image.isNull()) { + QOpenGLTexture::setData(image); + setMinMagFilters(QOpenGLTexture::Linear, QOpenGLTexture::Linear); + setWrapMode(QOpenGLTexture::ClampToEdge); + } +}; + +void OpenGLTexture2D::setData(const QPixmap& pixmap) { + setData(pixmap.toImage()); +}; + +void OpenGLTexture2D::setData(const QSharedPointer& pPaintable) { + if (pPaintable) { + setData(pPaintable->toImage()); + } +}; + +void OpenGLTexture2D::setData(const std::shared_ptr& pImage) { + if (pImage) { + setData(*pImage); + } +}; diff --git a/src/util/opengltexture2d.h b/src/util/opengltexture2d.h new file mode 100644 index 00000000000..957e10db084 --- /dev/null +++ b/src/util/opengltexture2d.h @@ -0,0 +1,16 @@ +#pragma once + +#include +#include + +class Paintable; + +class OpenGLTexture2D : public QOpenGLTexture { + public: + OpenGLTexture2D(); + + void setData(const QImage& image); + void setData(const QPixmap& pixmap); + void setData(const QSharedPointer& pPaintable); + void setData(const std::shared_ptr& pImage); +}; diff --git a/src/util/texture.cpp b/src/util/texture.cpp deleted file mode 100644 index 03acd8afa36..00000000000 --- a/src/util/texture.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include "util/texture.h" - -#include -#include -#include - -#include "widget/paintable.h" - -std::unique_ptr createTexture(const QImage& image) { - if (image.isNull()) { - return nullptr; - } - auto pTexture = std::make_unique(image); - pTexture->setMinificationFilter(QOpenGLTexture::Linear); - pTexture->setMagnificationFilter(QOpenGLTexture::Linear); - pTexture->setWrapMode(QOpenGLTexture::ClampToEdge); - - return pTexture; -} - -std::unique_ptr createTexture(const QPixmap& pixmap) { - return createTexture(pixmap.toImage()); -} - -std::unique_ptr createTexture(const QSharedPointer& pPaintable) { - if (pPaintable.isNull()) { - return nullptr; - } - return createTexture(pPaintable->toImage()); -} - -std::unique_ptr createTexture(const std::shared_ptr& pImage) { - if (!pImage) { - return nullptr; - } - return createTexture(*pImage); -} diff --git a/src/util/texture.h b/src/util/texture.h deleted file mode 100644 index 89f4ea9e9ed..00000000000 --- a/src/util/texture.h +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include - -class QImage; -class QOpenGLTexture; -class QPixmap; -class Paintable; - -std::unique_ptr createTexture(const QImage& image); -std::unique_ptr createTexture(const QPixmap& pixmap); -std::unique_ptr createTexture(const QSharedPointer& pPaintable); -std::unique_ptr createTexture(const std::shared_ptr& pImage); diff --git a/src/waveform/renderers/allshader/waveformrendererpreroll.cpp b/src/waveform/renderers/allshader/waveformrendererpreroll.cpp index a54f4828285..b28d4cc353b 100644 --- a/src/waveform/renderers/allshader/waveformrendererpreroll.cpp +++ b/src/waveform/renderers/allshader/waveformrendererpreroll.cpp @@ -6,13 +6,13 @@ #include #include "skin/legacy/skincontext.h" -#include "util/texture.h" #include "waveform/renderers/allshader/matrixforwidgetgeometry.h" #include "waveform/renderers/waveformwidgetrenderer.h" #include "widget/wskincolor.h" namespace { -std::unique_ptr generateTexture(float markerLength, +void generateTexture(OpenGLTexture2D* pTexture, + float markerLength, float markerBreadth, float devicePixelRatio, QColor color) { @@ -54,7 +54,7 @@ std::unique_ptr generateTexture(float markerLength, painter.drawPath(path); painter.end(); - return createTexture(image); + pTexture->setData(image); } } // anonymous namespace @@ -120,13 +120,14 @@ void WaveformRendererPreroll::paintGL() { // has changed size last time. m_markerLength = markerLength; m_markerBreadth = markerBreadth; - m_pTexture = generateTexture(m_markerLength, + generateTexture(&m_texture, + m_markerLength, m_markerBreadth, m_waveformRenderer->getDevicePixelRatio(), m_color); } - if (!m_pTexture) { + if (!m_texture.isStorageAllocated()) { return; } @@ -146,7 +147,7 @@ void WaveformRendererPreroll::paintGL() { m_shader.setUniformValue(matrixLocation, matrix); m_shader.setUniformValue(textureLocation, 0); - m_pTexture->bind(); + m_texture.bind(); const float end = m_waveformRenderer->getLength(); @@ -191,7 +192,7 @@ void WaveformRendererPreroll::paintGL() { (end - x) / markerLength); } - m_pTexture->release(); + m_texture.release(); m_shader.disableAttributeArray(positionLocation); m_shader.disableAttributeArray(texcoordLocation); diff --git a/src/waveform/renderers/allshader/waveformrendererpreroll.h b/src/waveform/renderers/allshader/waveformrendererpreroll.h index c8163c2dc87..f12bce22b72 100644 --- a/src/waveform/renderers/allshader/waveformrendererpreroll.h +++ b/src/waveform/renderers/allshader/waveformrendererpreroll.h @@ -6,6 +6,7 @@ #include "shaders/patternshader.h" #include "util/class.h" +#include "util/opengltexture2d.h" #include "waveform/renderers/allshader/vertexdata.h" #include "waveform/renderers/allshader/waveformrenderer.h" @@ -33,7 +34,7 @@ class allshader::WaveformRendererPreroll final : public allshader::WaveformRende QColor m_color; float m_markerBreadth{}; float m_markerLength{}; - std::unique_ptr m_pTexture; + OpenGLTexture2D m_texture; DISALLOW_COPY_AND_ASSIGN(WaveformRendererPreroll); }; diff --git a/src/waveform/renderers/allshader/waveformrendermark.cpp b/src/waveform/renderers/allshader/waveformrendermark.cpp index 36f0fdcf0c5..bc98b5edf88 100644 --- a/src/waveform/renderers/allshader/waveformrendermark.cpp +++ b/src/waveform/renderers/allshader/waveformrendermark.cpp @@ -4,7 +4,6 @@ #include #include "util/colorcomponents.h" -#include "util/texture.h" #include "waveform/renderers/allshader/matrixforwidgetgeometry.h" #include "waveform/renderers/allshader/rgbadata.h" #include "waveform/renderers/allshader/vertexdata.h" @@ -20,15 +19,15 @@ // then used as textures to be drawn with a GLSL shader. class TextureGraphics : public WaveformMark::Graphics { - std::unique_ptr m_pTexture; - public: - TextureGraphics(std::unique_ptr&& pTexture) - : m_pTexture{std::move(pTexture)} { - } - QOpenGLTexture* texture() const { - return m_pTexture.get(); + TextureGraphics() = default; + + QOpenGLTexture* texture() { + return &m_texture; } + + private: + OpenGLTexture2D m_texture; }; // Both allshader::WaveformRenderMark and the non-GL ::WaveformRenderMark derive @@ -225,11 +224,12 @@ void allshader::WaveformRenderMark::paintGL() { const float currentMarkPoint = std::floor( static_cast(m_waveformRenderer->getPlayMarkerPosition() * m_waveformRenderer->getLength())); - if (m_pPlayPosMarkTexture) { - const float markHalfWidth = m_pPlayPosMarkTexture->width() / devicePixelRatio / 2.f; + + if (m_playPosMarkTexture.isStorageAllocated()) { + const float markHalfWidth = m_playPosMarkTexture.width() / devicePixelRatio / 2.f; const float drawOffset = currentMarkPoint - markHalfWidth; - drawTexture(drawOffset, 0.f, m_pPlayPosMarkTexture.get()); + drawTexture(drawOffset, 0.f, &m_playPosMarkTexture); } } @@ -297,7 +297,7 @@ void allshader::WaveformRenderMark::updatePlayPosMarkTexture() { } painter.end(); - m_pPlayPosMarkTexture = createTexture(image); + m_playPosMarkTexture.setData(image); } void allshader::WaveformRenderMark::drawTriangle(QPainter* painter, @@ -321,6 +321,8 @@ void allshader::WaveformRenderMark::resizeGL(int, int) { } void allshader::WaveformRenderMark::updateMarkImage(WaveformMarkPointer pMark) { - pMark->m_pGraphics = std::make_unique( - createTexture(pMark->generateImage(m_waveformRenderer->getDevicePixelRatio()))); + auto pTextureGraphics = std::make_unique(); + pTextureGraphics->texture()->setData( + pMark->generateImage(m_waveformRenderer->getDevicePixelRatio())); + pMark->m_pGraphics = std::move(pTextureGraphics); } diff --git a/src/waveform/renderers/allshader/waveformrendermark.h b/src/waveform/renderers/allshader/waveformrendermark.h index a06474cfc07..e5aef11fd8d 100644 --- a/src/waveform/renderers/allshader/waveformrendermark.h +++ b/src/waveform/renderers/allshader/waveformrendermark.h @@ -4,6 +4,7 @@ #include "shaders/rgbashader.h" #include "shaders/textureshader.h" +#include "util/opengltexture2d.h" #include "waveform/renderers/allshader/waveformrendererabstract.h" #include "waveform/renderers/waveformrendermarkbase.h" @@ -44,12 +45,12 @@ class allshader::WaveformRenderMark : public ::WaveformRenderMarkBase, QPointF p2, QPointF p3); - mixxx::RGBAShader m_rgbaShader; - mixxx::TextureShader m_textureShader; - std::unique_ptr m_pPlayPosMarkTexture; - void drawMark(const QRectF& rect, QColor color); void drawTexture(float x, float y, QOpenGLTexture* texture); + mixxx::RGBAShader m_rgbaShader; + mixxx::TextureShader m_textureShader; + OpenGLTexture2D m_playPosMarkTexture; + DISALLOW_COPY_AND_ASSIGN(WaveformRenderMark); }; diff --git a/src/widget/wspinnyglsl.cpp b/src/widget/wspinnyglsl.cpp index 17f20ef70e0..989e9c0044a 100644 --- a/src/widget/wspinnyglsl.cpp +++ b/src/widget/wspinnyglsl.cpp @@ -4,7 +4,6 @@ #include #include "moc_wspinnyglsl.cpp" -#include "util/texture.h" WSpinnyGLSL::WSpinnyGLSL( QWidget* parent, @@ -15,25 +14,10 @@ WSpinnyGLSL::WSpinnyGLSL( : WSpinnyBase(parent, group, pConfig, pVCMan, pPlayer) { } -WSpinnyGLSL::~WSpinnyGLSL() { - cleanupGL(); -} - -void WSpinnyGLSL::cleanupGL() { - makeCurrentIfNeeded(); - m_pBgTexture.reset(); - m_pMaskTexture.reset(); - m_pFgTextureScaled.reset(); - m_pGhostTextureScaled.reset(); - m_pLoadedCoverTextureScaled.reset(); - m_pQTexture.reset(); - doneCurrent(); -} - void WSpinnyGLSL::coverChanged() { if (isContextValid()) { makeCurrentIfNeeded(); - m_pLoadedCoverTextureScaled = createTexture(m_loadedCoverScaled); + m_loadedCoverTextureScaled.setData(m_loadedCoverScaled); doneCurrent(); } // otherwise this will happen in initializeGL @@ -55,11 +39,11 @@ void WSpinnyGLSL::resizeGL(int w, int h) { } void WSpinnyGLSL::updateTextures() { - m_pBgTexture = createTexture(m_pBgImage); - m_pMaskTexture = createTexture(m_pMaskImage); - m_pFgTextureScaled = createTexture(m_fgImageScaled); - m_pGhostTextureScaled = createTexture(m_ghostImageScaled); - m_pLoadedCoverTextureScaled = createTexture(m_loadedCoverScaled); + m_bgTexture.setData(m_pBgImage); + m_maskTexture.setData(m_pMaskImage); + m_fgTextureScaled.setData(m_fgImageScaled); + m_ghostTextureScaled.setData(m_ghostImageScaled); + m_loadedCoverTextureScaled.setData(m_loadedCoverScaled); } void WSpinnyGLSL::setupVinylSignalQuality() { @@ -69,9 +53,9 @@ void WSpinnyGLSL::updateVinylSignalQualityImage( const QColor& qual_color, const unsigned char* data) { m_vinylQualityColor = qual_color; m_vinylQualityColor.setAlphaF(0.75f); - if (m_pQTexture) { + if (m_qTexture.isStorageAllocated()) { makeCurrentIfNeeded(); - m_pQTexture->bind(); + m_qTexture.bind(); // Using a texture of one byte per pixel so we can store the vinyl // signal quality data directly. The VinylQualityShader will draw this // colorized with alpha transparency. @@ -84,7 +68,7 @@ void WSpinnyGLSL::updateVinylSignalQualityImage( GL_RED, GL_UNSIGNED_BYTE, data); - m_pQTexture->release(); + m_qTexture.release(); doneCurrent(); } } @@ -112,16 +96,16 @@ void WSpinnyGLSL::paintGL() { m_textureShader.setUniformValue(textureLocation, 0); - if (m_pBgTexture) { - drawTexture(m_pBgTexture.get()); + if (m_bgTexture.isStorageAllocated()) { + drawTexture(&m_bgTexture); } - if (m_bShowCover && m_pLoadedCoverTextureScaled) { - drawTexture(m_pLoadedCoverTextureScaled.get()); + if (m_bShowCover && m_loadedCoverTextureScaled.isStorageAllocated()) { + drawTexture(&m_loadedCoverTextureScaled); } - if (m_pMaskTexture) { - drawTexture(m_pMaskTexture.get()); + if (m_maskTexture.isStorageAllocated()) { + drawTexture(&m_maskTexture); } // Overlay the signal quality drawing if vinyl is active @@ -137,22 +121,22 @@ void WSpinnyGLSL::paintGL() { // and draw the image at the corner. // p.translate(width() / 2, height() / 2); - bool paintGhost = m_bGhostPlayback && m_pGhostTextureScaled; + bool paintGhost = m_bGhostPlayback && m_ghostTextureScaled.isStorageAllocated(); if (paintGhost) { QMatrix4x4 rotate; rotate.rotate(m_fGhostAngle, 0, 0, -1); m_textureShader.setUniformValue(matrixLocation, rotate); - drawTexture(m_pGhostTextureScaled.get()); + drawTexture(&m_ghostTextureScaled); } - if (m_pFgTextureScaled) { + if (m_fgTextureScaled.isStorageAllocated()) { QMatrix4x4 rotate; rotate.rotate(m_fAngle, 0, 0, -1); m_textureShader.setUniformValue(matrixLocation, rotate); - drawTexture(m_pFgTextureScaled.get()); + drawTexture(&m_fgTextureScaled); } m_textureShader.release(); @@ -163,11 +147,10 @@ void WSpinnyGLSL::initializeGL() { updateTextures(); - m_pQTexture.reset(new QOpenGLTexture(QOpenGLTexture::Target2D)); - m_pQTexture->setMinMagFilters(QOpenGLTexture::Linear, QOpenGLTexture::Linear); - m_pQTexture->setSize(m_iVinylScopeSize, m_iVinylScopeSize); - m_pQTexture->setFormat(QOpenGLTexture::R8_UNorm); - m_pQTexture->allocateStorage(QOpenGLTexture::Red, QOpenGLTexture::UInt8); + m_qTexture.setMinMagFilters(QOpenGLTexture::Linear, QOpenGLTexture::Linear); + m_qTexture.setSize(m_iVinylScopeSize, m_iVinylScopeSize); + m_qTexture.setFormat(QOpenGLTexture::R8_UNorm); + m_qTexture.allocateStorage(QOpenGLTexture::Red, QOpenGLTexture::UInt8); m_textureShader.init(); m_vinylQualityShader.init(); @@ -241,11 +224,11 @@ void WSpinnyGLSL::drawVinylQuality() { m_vinylQualityShader.setAttributeArray( texcoordLocation, GL_FLOAT, texarray.data(), 2); - m_pQTexture->bind(); + m_qTexture.bind(); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - m_pQTexture->release(); + m_qTexture.release(); m_vinylQualityShader.release(); } diff --git a/src/widget/wspinnyglsl.h b/src/widget/wspinnyglsl.h index 31e1cd099c6..56ee53a3a03 100644 --- a/src/widget/wspinnyglsl.h +++ b/src/widget/wspinnyglsl.h @@ -4,6 +4,7 @@ #include "shaders/textureshader.h" #include "shaders/vinylqualityshader.h" +#include "util/opengltexture2d.h" #include "widget/wspinnybase.h" class QOpenGLTexture; @@ -16,7 +17,7 @@ class WSpinnyGLSL : public WSpinnyBase, private QOpenGLFunctions { UserSettingsPointer pConfig, VinylControlManager* pVCMan, BaseTrackPlayer* pPlayer); - ~WSpinnyGLSL() override; + ~WSpinnyGLSL() override = default; private: void draw() override; @@ -26,7 +27,6 @@ class WSpinnyGLSL : public WSpinnyBase, private QOpenGLFunctions { void paintGL() override; void resizeGL(int w, int h) override; void drawTexture(QOpenGLTexture* texture); - void cleanupGL(); void updateTextures(); void setupVinylSignalQuality() override; @@ -36,11 +36,11 @@ class WSpinnyGLSL : public WSpinnyBase, private QOpenGLFunctions { mixxx::TextureShader m_textureShader; mixxx::VinylQualityShader m_vinylQualityShader; - std::unique_ptr m_pBgTexture; - std::unique_ptr m_pMaskTexture; - std::unique_ptr m_pFgTextureScaled; - std::unique_ptr m_pGhostTextureScaled; - std::unique_ptr m_pLoadedCoverTextureScaled; - std::unique_ptr m_pQTexture; + OpenGLTexture2D m_bgTexture; + OpenGLTexture2D m_maskTexture; + OpenGLTexture2D m_fgTextureScaled; + OpenGLTexture2D m_ghostTextureScaled; + OpenGLTexture2D m_loadedCoverTextureScaled; + OpenGLTexture2D m_qTexture; QColor m_vinylQualityColor; }; diff --git a/src/widget/wvumeterglsl.cpp b/src/widget/wvumeterglsl.cpp index cd1ff511eef..039651dccff 100644 --- a/src/widget/wvumeterglsl.cpp +++ b/src/widget/wvumeterglsl.cpp @@ -6,16 +6,11 @@ #include "moc_wvumeterglsl.cpp" #include "util/duration.h" #include "util/math.h" -#include "util/texture.h" WVuMeterGLSL::WVuMeterGLSL(QWidget* pParent) : WVuMeterBase(pParent) { } -WVuMeterGLSL::~WVuMeterGLSL() { - cleanupGL(); -} - void WVuMeterGLSL::draw() { if (shouldRender()) { makeCurrentIfNeeded(); @@ -27,8 +22,8 @@ void WVuMeterGLSL::draw() { void WVuMeterGLSL::initializeGL() { initializeOpenGLFunctions(); - m_pTextureBack = createTexture(m_pPixmapBack); - m_pTextureVu = createTexture(m_pPixmapVu); + m_textureBack.setData(m_pPixmapBack); + m_textureVu.setData(m_pPixmapVu); m_textureShader.init(); } @@ -62,17 +57,17 @@ void WVuMeterGLSL::paintGL() { m_textureShader.setUniformValue(textureLocation, 0); - if (m_pTextureBack) { + if (m_textureBack.isStorageAllocated()) { QRectF sourceRect(0, 0, m_pPixmapBack->width(), m_pPixmapBack->height()); - drawTexture(m_pTextureBack.get(), rect(), sourceRect); + drawTexture(&m_textureBack, rect(), sourceRect); } const double widgetWidth = width(); const double widgetHeight = height(); - if (m_pTextureVu) { - const double pixmapWidth = m_pTextureVu->width(); - const double pixmapHeight = m_pTextureVu->height(); + if (m_textureVu.isStorageAllocated()) { + const double pixmapWidth = m_textureVu.width(); + const double pixmapHeight = m_textureVu.height(); if (m_bHorizontal) { const double widgetPosition = math_clamp(widgetWidth * m_dParameter, 0.0, widgetWidth); QRectF targetRect(0, 0, widgetPosition, math_min(pixmapHeight, widgetHeight)); @@ -80,7 +75,7 @@ void WVuMeterGLSL::paintGL() { const double pixmapPosition = math_clamp( pixmapWidth * m_dParameter, 0.0, pixmapWidth); QRectF sourceRect(0, 0, pixmapPosition, pixmapHeight); - drawTexture(m_pTextureVu.get(), targetRect, sourceRect); + drawTexture(&m_textureVu, targetRect, sourceRect); if (m_iPeakHoldSize > 0 && m_dPeakParameter > 0.0 && m_dPeakParameter > m_dParameter) { @@ -102,7 +97,7 @@ void WVuMeterGLSL::paintGL() { 0, pixmapPeakHoldSize, pixmapHeight); - drawTexture(m_pTextureVu.get(), targetRect, sourceRect); + drawTexture(&m_textureVu, targetRect, sourceRect); } } else { // vertical @@ -113,7 +108,7 @@ void WVuMeterGLSL::paintGL() { const double pixmapPosition = math_clamp( pixmapHeight * m_dParameter, 0.0, pixmapHeight); QRectF sourceRect(0, pixmapHeight - pixmapPosition, pixmapWidth, pixmapPosition); - drawTexture(m_pTextureVu.get(), targetRect, sourceRect); + drawTexture(&m_textureVu, targetRect, sourceRect); if (m_iPeakHoldSize > 0 && m_dPeakParameter > 0.0 && m_dPeakParameter > m_dParameter) { @@ -134,7 +129,7 @@ void WVuMeterGLSL::paintGL() { pixmapHeight - pixmapPeakPosition, pixmapWidth, pixmapPeakHoldSize); - drawTexture(m_pTextureVu.get(), targetRect, sourceRect); + drawTexture(&m_textureVu, targetRect, sourceRect); } } } @@ -144,13 +139,6 @@ void WVuMeterGLSL::paintGL() { m_textureShader.release(); } -void WVuMeterGLSL::cleanupGL() { - makeCurrentIfNeeded(); - m_pTextureBack.reset(); - m_pTextureVu.reset(); - doneCurrent(); -} - void WVuMeterGLSL::drawTexture(QOpenGLTexture* texture, const QRectF& targetRect, const QRectF& sourceRect) { diff --git a/src/widget/wvumeterglsl.h b/src/widget/wvumeterglsl.h index 1dfec3342e5..3b3c3cb1b6b 100644 --- a/src/widget/wvumeterglsl.h +++ b/src/widget/wvumeterglsl.h @@ -4,6 +4,7 @@ #include #include "shaders/textureshader.h" +#include "util/opengltexture2d.h" #include "widget/wvumeterbase.h" class QOpenGLTexture; @@ -12,16 +13,15 @@ class WVuMeterGLSL : public WVuMeterBase, private QOpenGLFunctions { Q_OBJECT public: explicit WVuMeterGLSL(QWidget* pParent = nullptr); - ~WVuMeterGLSL() override; + ~WVuMeterGLSL() override = default; private: - std::unique_ptr m_pTextureBack; - std::unique_ptr m_pTextureVu; + OpenGLTexture2D m_textureBack; + OpenGLTexture2D m_textureVu; mixxx::TextureShader m_textureShader; void draw() override; void initializeGL() override; - void cleanupGL(); void paintGL() override; void drawTexture(QOpenGLTexture* texture, const QRectF& sourceRect, const QRectF& targetRect); }; From a0a0ddb110f6ded1d81279a3962c474f1cb70833 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Fri, 5 Apr 2024 07:33:31 +0200 Subject: [PATCH 4/5] Add a comment that explains the OpenGLTexture2D class --- src/util/opengltexture2d.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/util/opengltexture2d.h b/src/util/opengltexture2d.h index 957e10db084..bcf3ccbd9e5 100644 --- a/src/util/opengltexture2d.h +++ b/src/util/opengltexture2d.h @@ -5,6 +5,8 @@ class Paintable; +/// This is an QOpenGLTexture, with additional methods to set the texture data, +/// and default settings for 2D painting with lienar filtering and wrap mode. class OpenGLTexture2D : public QOpenGLTexture { public: OpenGLTexture2D(); From a0ef420a651176ff6a6ef1d5f297c7458a01a896 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Fri, 5 Apr 2024 07:43:00 +0200 Subject: [PATCH 5/5] Avoid to manipulate m_texture via pointer --- .../renderers/allshader/waveformrendererpreroll.cpp | 10 ++++------ .../renderers/allshader/waveformrendermark.cpp | 9 ++++----- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/waveform/renderers/allshader/waveformrendererpreroll.cpp b/src/waveform/renderers/allshader/waveformrendererpreroll.cpp index b28d4cc353b..89c657a156a 100644 --- a/src/waveform/renderers/allshader/waveformrendererpreroll.cpp +++ b/src/waveform/renderers/allshader/waveformrendererpreroll.cpp @@ -11,8 +11,7 @@ #include "widget/wskincolor.h" namespace { -void generateTexture(OpenGLTexture2D* pTexture, - float markerLength, +QImage drawPrerollImage(float markerLength, float markerBreadth, float devicePixelRatio, QColor color) { @@ -54,7 +53,7 @@ void generateTexture(OpenGLTexture2D* pTexture, painter.drawPath(path); painter.end(); - pTexture->setData(image); + return image; } } // anonymous namespace @@ -120,11 +119,10 @@ void WaveformRendererPreroll::paintGL() { // has changed size last time. m_markerLength = markerLength; m_markerBreadth = markerBreadth; - generateTexture(&m_texture, - m_markerLength, + m_texture.setData(drawPrerollImage(m_markerLength, m_markerBreadth, m_waveformRenderer->getDevicePixelRatio(), - m_color); + m_color)); } if (!m_texture.isStorageAllocated()) { diff --git a/src/waveform/renderers/allshader/waveformrendermark.cpp b/src/waveform/renderers/allshader/waveformrendermark.cpp index bc98b5edf88..17139ef939c 100644 --- a/src/waveform/renderers/allshader/waveformrendermark.cpp +++ b/src/waveform/renderers/allshader/waveformrendermark.cpp @@ -20,8 +20,9 @@ class TextureGraphics : public WaveformMark::Graphics { public: - TextureGraphics() = default; - + TextureGraphics(const QImage& image) { + m_texture.setData(image); + } QOpenGLTexture* texture() { return &m_texture; } @@ -321,8 +322,6 @@ void allshader::WaveformRenderMark::resizeGL(int, int) { } void allshader::WaveformRenderMark::updateMarkImage(WaveformMarkPointer pMark) { - auto pTextureGraphics = std::make_unique(); - pTextureGraphics->texture()->setData( + pMark->m_pGraphics = std::make_unique( pMark->generateImage(m_waveformRenderer->getDevicePixelRatio())); - pMark->m_pGraphics = std::move(pTextureGraphics); }