Skip to content

Commit

Permalink
use QOpenGLBuffer for color and vector data for waveformrenderers
Browse files Browse the repository at this point in the history
  • Loading branch information
m0dB authored and m0dB committed Jan 2, 2024
1 parent bff9a30 commit 6185ca0
Show file tree
Hide file tree
Showing 16 changed files with 351 additions and 97 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
#include <QVector>

namespace allshader {
class VertexData;
class VectorData;
}

class allshader::VertexData {
class allshader::VectorData {
QVector<QVector2D> mData;

public:
Expand Down
186 changes: 186 additions & 0 deletions src/waveform/renderers/allshader/vertexbuffer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
#pragma once

#include <QOpenGLBuffer>
#include <cassert>

namespace allshader {
class VertexBuffer;
class Vector2DVertexBuffer;
class Vector2DRGBVertexBuffer;
class Vector2DRGBAVertexBuffer;
}

class allshader::VertexBuffer : public QOpenGLBuffer {
public:
VertexBuffer(int tupleSize)
: QOpenGLBuffer(QOpenGLBuffer::VertexBuffer), m_tupleSize(tupleSize) {
}

void reserve(int count) {
int nBytes = count * stride() * sizeof(float);
if (nBytes > m_allocatedBytes) {
allocate(nBytes);
m_allocatedBytes = nBytes;
}
}

void mapForWrite() {
void* ptr = QOpenGLBuffer::map(QOpenGLBuffer::WriteOnly);
assert(ptr);
m_pMapped = static_cast<float*>(ptr);
m_valueIndex = 0;
}

void setIndex(int index) { // in amount of tuples
m_valueIndex = index * m_tupleSize;
}

int tupleSize() const { // in amount of floats
return m_tupleSize;
}

int size() const { // in tuples
return m_valueIndex / m_tupleSize;
}

int stride() const { // in bytes
return m_tupleSize * sizeof(float);
}

protected:
const int m_tupleSize;
int m_allocatedBytes{};
float* m_pMapped{};
int m_valueIndex{}; // index into m_pMapped, in amount of floats
};

class allshader::Vector2DVertexBuffer : public allshader::VertexBuffer {
public:
Vector2DVertexBuffer()
: VertexBuffer{2} {
}

constexpr int offset() const {
return 0;
}

void add(float x, float y) {
m_pMapped[m_valueIndex++] = x;
m_pMapped[m_valueIndex++] = y;
}

void addRectangle(float x1, float y1, float x2, float y2) {
add(x1, y1);
add(x2, y1);
add(x1, y2);

add(x1, y2);
add(x2, y2);
add(x2, y1);
}
};

class allshader::Vector2DRGBVertexBuffer : public VertexBuffer {
public:
Vector2DRGBVertexBuffer()
: VertexBuffer{positionTupleSize() + colorTupleSize()} {
}

constexpr int positionOffset() const {
return 0;
}

constexpr int positionTupleSize() const {
return 2;
}

constexpr int colorOffset() const {
return positionTupleSize() * sizeof(float);
}

constexpr int colorTupleSize() const {
return 3;
}

void add(float x, float y, float r, float g, float b) {
m_pMapped[m_valueIndex++] = x;
m_pMapped[m_valueIndex++] = y;

m_pMapped[m_valueIndex++] = r;
m_pMapped[m_valueIndex++] = g;
m_pMapped[m_valueIndex++] = b;
}

void addRectangle(float x1, float y1, float x2, float y2, float r, float g, float b) {
add(x1, y1, r, g, b);
add(x2, y1, r, g, b);
add(x1, y2, r, g, b);

add(x1, y2, r, g, b);
add(x2, y2, r, g, b);
add(x2, y1, r, g, b);
}
};

class allshader::Vector2DRGBAVertexBuffer : public VertexBuffer {
public:
Vector2DRGBAVertexBuffer()
: VertexBuffer{positionTupleSize() + colorTupleSize()} {
}

constexpr int positionOffset() const {
return 0;
}

constexpr int positionTupleSize() const {
return 2;
}

constexpr int colorOffset() const {
return positionTupleSize() * sizeof(float);
}

constexpr int colorTupleSize() const {
return 4;
}

void add(float x, float y, float r, float g, float b, float a) {
m_pMapped[m_valueIndex++] = x;
m_pMapped[m_valueIndex++] = y;

m_pMapped[m_valueIndex++] = r;
m_pMapped[m_valueIndex++] = g;
m_pMapped[m_valueIndex++] = b;
m_pMapped[m_valueIndex++] = a;
}

void addRectangle(float x1, float y1, float x2, float y2, float r, float g, float b, float a) {
add(x1, y1, r, g, b, a);
add(x2, y1, r, g, b, a);
add(x1, y2, r, g, b, a);

add(x1, y2, r, g, b, a);
add(x2, y2, r, g, b, a);
add(x2, y1, r, g, b, a);
}

void addRectangleGradient(float x1,
float y1,
float x2,
float y2,
float rA,
float gA,
float bA,
float aA,
float rB,
float gB,
float bB,
float aB) {
add(x1, y1, rA, gA, bA, aA);
add(x2, y1, rA, gA, bA, aA);
add(x1, y2, rB, gB, bB, aB);
add(x1, y2, rB, gB, bB, aB);
add(x2, y2, rB, gB, bB, aB);
add(x2, y1, rA, gA, bA, aA);
}
};
16 changes: 13 additions & 3 deletions src/waveform/renderers/allshader/waveformrenderbeat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ WaveformRenderBeat::WaveformRenderBeat(WaveformWidgetRenderer* waveformWidget)
void WaveformRenderBeat::initializeGL() {
WaveformRenderer::initializeGL();
m_shader.init();
m_vertices.create();
m_vertices.setUsagePattern(QOpenGLBuffer::DynamicDraw);
}

void WaveformRenderBeat::setup(const QDomNode& node, const SkinContext& context) {
Expand Down Expand Up @@ -81,8 +83,10 @@ void WaveformRenderBeat::paintGL() {
}

const int reserved = numBeatsInRange * numVerticesPerLine;
m_vertices.clear();

m_vertices.bind();
m_vertices.reserve(reserved);
m_vertices.mapForWrite();

for (auto it = trackBeats->iteratorFrom(startPosition);
it != trackBeats->cend() && *it <= endPosition;
Expand All @@ -101,6 +105,8 @@ void WaveformRenderBeat::paintGL() {
m_vertices.addRectangle(x1, 0.f, x2, rendererBreadth);
}

m_vertices.unmap();

DEBUG_ASSERT(reserved == m_vertices.size());

const int positionLocation = m_shader.positionLocation();
Expand All @@ -112,15 +118,19 @@ void WaveformRenderBeat::paintGL() {

const QMatrix4x4 matrix = matrixForWidgetGeometry(m_waveformRenderer, false);

m_shader.setAttributeArray(
positionLocation, GL_FLOAT, m_vertices.constData(), 2);
m_shader.setAttributeBuffer(positionLocation,
GL_FLOAT,
m_vertices.offset(),
m_vertices.tupleSize(),
m_vertices.stride());

m_shader.setUniformValue(matrixLocation, matrix);
m_shader.setUniformValue(colorLocation, m_color);

glDrawArrays(GL_TRIANGLES, 0, m_vertices.size());

m_shader.disableAttributeArray(positionLocation);
m_vertices.release();
m_shader.release();
}

Expand Down
4 changes: 2 additions & 2 deletions src/waveform/renderers/allshader/waveformrenderbeat.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

#include "shaders/unicolorshader.h"
#include "util/class.h"
#include "waveform/renderers/allshader/vertexdata.h"
#include "waveform/renderers/allshader/vertexbuffer.h"
#include "waveform/renderers/allshader/waveformrenderer.h"

class QDomNode;
Expand All @@ -25,7 +25,7 @@ class allshader::WaveformRenderBeat final : public allshader::WaveformRenderer {
private:
mixxx::UnicolorShader m_shader;
QColor m_color;
VertexData m_vertices;
Vector2DVertexBuffer m_vertices;

DISALLOW_COPY_AND_ASSIGN(WaveformRenderBeat);
};
52 changes: 39 additions & 13 deletions src/waveform/renderers/allshader/waveformrendererfiltered.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ void WaveformRendererFiltered::onSetup(const QDomNode& node) {
void WaveformRendererFiltered::initializeGL() {
WaveformRendererSignalBase::initializeGL();
m_shader.init();
m_vertices.create();
m_vertices.setUsagePattern(QOpenGLBuffer::DynamicDraw);
}

void WaveformRendererFiltered::paintGL() {
Expand Down Expand Up @@ -72,24 +74,37 @@ void WaveformRendererFiltered::paintGL() {

const int numVerticesPerLine = 6; // 2 triangles

int startIndex[4];
int endIndex[4];
int reserved[4];
int reservedTotal = 0;
// low, mid, high
for (int bandIndex = 0; bandIndex < 3; bandIndex++) {
m_vertices[bandIndex].clear();
startIndex[bandIndex] = reservedTotal;
endIndex[bandIndex] = reservedTotal;
reserved[bandIndex] = numVerticesPerLine * length;
m_vertices[bandIndex].reserve(reserved[bandIndex]);
reservedTotal += reserved[bandIndex];
qDebug() << startIndex[bandIndex] << endIndex[bandIndex]
<< reserved[bandIndex] << reservedTotal;
}

// the horizontal line
startIndex[3] = reservedTotal;
endIndex[3] = reservedTotal;
reserved[3] = numVerticesPerLine;
m_vertices[3].clear();
m_vertices[3].reserve(reserved[3]);
reservedTotal += reserved[3];

m_vertices[3].addRectangle(
m_vertices.bind();
m_vertices.reserve(reservedTotal);
m_vertices.mapForWrite();

m_vertices.setIndex(endIndex[3]);
m_vertices.addRectangle(
0.f,
halfBreadth - 0.5f * devicePixelRatio,
static_cast<float>(length),
halfBreadth + 0.5f * devicePixelRatio);
endIndex[3] += numVerticesPerLine;

const double maxSamplingRange = visualIncrementPerPixel / 2.0;

Expand Down Expand Up @@ -124,16 +139,20 @@ void WaveformRendererFiltered::paintGL() {
max[bandIndex][1] *= bandGain[bandIndex];

// lines are thin rectangles
m_vertices[bandIndex].addRectangle(
m_vertices.setIndex(endIndex[bandIndex]);
m_vertices.addRectangle(
fpos - 0.5f,
halfBreadth - heightFactor * max[bandIndex][0],
fpos + 0.5f,
halfBreadth + heightFactor * max[bandIndex][1]);
endIndex[bandIndex] += numVerticesPerLine;
}

xVisualFrame += visualIncrementPerPixel;
}

m_vertices.unmap();

const QMatrix4x4 matrix = matrixForWidgetGeometry(m_waveformRenderer, true);

const int matrixLocation = m_shader.matrixLocation();
Expand All @@ -160,18 +179,25 @@ void WaveformRendererFiltered::paintGL() {
static_cast<float>(m_axesColor_b),
static_cast<float>(m_axesColor_a));

// 3 bands + 1 extra for the horizontal line
m_shader.setAttributeBuffer(positionLocation,
GL_FLOAT,
m_vertices.offset(),
m_vertices.tupleSize(),
m_vertices.stride());

for (int i = 0; i < 4; i++) {
DEBUG_ASSERT(reserved[i] == m_vertices[i].size());
m_shader.setUniformValue(colorLocation, colors[i]);
m_shader.setAttributeArray(
positionLocation, GL_FLOAT, m_vertices[i].constData(), 2);
// 3 bands + 1 extra for the horizontal line
for (int bandIndex = 0; bandIndex < 4; bandIndex++) {
DEBUG_ASSERT(reserved[bandIndex] == endIndex[bandIndex] - startIndex[bandIndex]);
m_shader.setUniformValue(colorLocation, colors[bandIndex]);

glDrawArrays(GL_TRIANGLES, 0, m_vertices[i].size());
glDrawArrays(GL_TRIANGLES,
startIndex[bandIndex],
endIndex[bandIndex] - startIndex[bandIndex]);
}
DEBUG_ASSERT(reservedTotal == endIndex[3]);

m_shader.disableAttributeArray(positionLocation);
m_vertices.release();
m_shader.release();
}

Expand Down
4 changes: 2 additions & 2 deletions src/waveform/renderers/allshader/waveformrendererfiltered.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#include "shaders/unicolorshader.h"
#include "util/class.h"
#include "waveform/renderers/allshader/vertexdata.h"
#include "waveform/renderers/allshader/vertexbuffer.h"
#include "waveform/renderers/allshader/waveformrenderersignalbase.h"

namespace allshader {
Expand All @@ -21,7 +21,7 @@ class allshader::WaveformRendererFiltered final : public allshader::WaveformRend

private:
mixxx::UnicolorShader m_shader;
VertexData m_vertices[4];
Vector2DVertexBuffer m_vertices;

DISALLOW_COPY_AND_ASSIGN(WaveformRendererFiltered);
};
Loading

0 comments on commit 6185ca0

Please sign in to comment.