libkwineffects/glvertexbuffer: add a better helper for uploading vertices

This commit is contained in:
Xaver Hugl 2023-09-02 16:48:04 +02:00
parent cbe8d21f07
commit 617f3b9000
9 changed files with 118 additions and 102 deletions

View file

@ -456,23 +456,6 @@ void GLVertexBuffer::setData(const void *data, size_t size)
unmap();
}
void GLVertexBuffer::setData(int vertexCount, int dim, const float *vertices, const float *texcoords)
{
const GLVertexAttrib layout[] = {
{VA_Position, dim, GL_FLOAT, 0},
{VA_TexCoord, 2, GL_FLOAT, int(dim * sizeof(float))}};
int stride = (texcoords ? dim + 2 : dim) * sizeof(float);
int attribCount = texcoords ? 2 : 1;
setAttribLayout(layout, attribCount, stride);
setVertexCount(vertexCount);
GLvoid *ptr = map(vertexCount * stride);
d->interleaveArrays((float *)ptr, dim, vertices, texcoords, vertexCount);
unmap();
}
GLvoid *GLVertexBuffer::map(size_t size)
{
d->mappedSize = size;

View file

@ -9,12 +9,14 @@
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include "kwineffects.h"
#include "libkwineffects/kwinglutils_export.h"
#include <QColor>
#include <QRegion>
#include <epoxy/gl.h>
#include <optional>
#include <ranges>
#include <span>
namespace KWin
@ -104,15 +106,40 @@ public:
*/
void setVertexCount(int count);
/**
* Sets the vertex data.
* @param numberVertices The number of vertices in the arrays
* @param dim The dimension of the vertices: 2 for x/y, 3 for x/y/z
* @param vertices The vertices, size must equal @a numberVertices * @a dim
* @param texcoords The texture coordinates for each vertex.
* Size must equal 2 * @a numberVertices.
*/
void setData(int numberVertices, int dim, const float *vertices, const float *texcoords);
// clang-format off
template<std::ranges::contiguous_range T>
requires std::is_same<std::ranges::range_value_t<T>, GLVertex2D>::value
void setVertices(const T &range)
{
setData(range.data(), range.size() * sizeof(GLVertex2D));
setVertexCount(range.size());
setAttribLayout(GLVertex2DLayout, 2, sizeof(GLVertex2D));
}
template<std::ranges::contiguous_range T>
requires std::is_same<std::ranges::range_value_t<T>, GLVertex3D>::value
void setVertices(const T &range)
{
setData(range.data(), range.size() * sizeof(GLVertex3D));
setVertexCount(range.size());
setAttribLayout(GLVertex3DLayout, 2, sizeof(GLVertex3D));
}
template<std::ranges::contiguous_range T>
requires std::is_same<std::ranges::range_value_t<T>, QVector2D>::value
void setVertices(const T &range)
{
setData(range.data(), range.size() * sizeof(QVector2D));
setVertexCount(range.size());
static constexpr GLVertexAttrib layout{
.index = VA_Position,
.size = 2,
.type = GL_FLOAT,
.relativeOffset = 0,
};
setAttribLayout(&layout, 1, sizeof(QVector2D));
}
// clang-format on
/**
* Maps an unused range of the data store into the client's address space.

View file

@ -353,15 +353,6 @@ void GLTexture::render(const QRectF &source, const QRegion &region, const QSizeF
if (destinationSize != d->m_cachedSize || d->m_cachedSource != source) {
d->m_cachedSize = destinationSize;
d->m_cachedSource = source;
if (!d->m_vbo) {
d->m_vbo = std::make_unique<GLVertexBuffer>(KWin::GLVertexBuffer::Static);
}
const float verts[4 * 2] = {
0.0f, 0.0f,
0.0f, float(destinationSize.height()),
float(destinationSize.width()), 0.0f,
float(destinationSize.width()), float(destinationSize.height())};
const float texWidth = (target() == GL_TEXTURE_RECTANGLE_ARB) ? width() : 1.0f;
const float texHeight = (target() == GL_TEXTURE_RECTANGLE_ARB) ? height() : 1.0f;
@ -381,13 +372,28 @@ void GLTexture::render(const QRectF &source, const QRegion &region, const QSizeF
const QPointF p3 = textureMat.map(QPointF(source.x() + source.width(), source.y()));
const QPointF p4 = textureMat.map(QPointF(source.x() + source.width(), source.y() + source.height()));
const float texcoords[4 * 2] = {
float(p1.x()), float(p1.y()),
float(p2.x()), float(p2.y()),
float(p3.x()), float(p3.y()),
float(p4.x()), float(p4.y())};
d->m_vbo->setData(4, 2, verts, texcoords);
if (!d->m_vbo) {
d->m_vbo = std::make_unique<GLVertexBuffer>(KWin::GLVertexBuffer::Static);
}
const std::array<GLVertex2D, 4> data{
GLVertex2D{
.position = QVector2D(0, 0),
.texcoord = QVector2D(p1),
},
GLVertex2D{
.position = QVector2D(0, destinationSize.height()),
.texcoord = QVector2D(p2),
},
GLVertex2D{
.position = QVector2D(destinationSize.width(), 0),
.texcoord = QVector2D(p3),
},
GLVertex2D{
.position = QVector2D(destinationSize.width(), destinationSize.height()),
.texcoord = QVector2D(p4),
},
};
d->m_vbo->setVertices(data);
}
bind();
d->m_vbo->render(region, GL_TRIANGLE_STRIP, hardwareClipping);

View file

@ -138,37 +138,37 @@ void MagnifierEffect::paintScreen(const RenderTarget &renderTarget, const Render
QRectF areaF = scaledRect(area, scale);
const QRectF frame = scaledRect(area.adjusted(-FRAME_WIDTH, -FRAME_WIDTH, FRAME_WIDTH, FRAME_WIDTH), scale);
QVector<float> verts;
QVector<QVector2D> verts;
verts.reserve(4 * 6 * 2);
// top frame
verts << frame.right() << frame.top();
verts << frame.left() << frame.top();
verts << frame.left() << areaF.top();
verts << frame.left() << areaF.top();
verts << frame.right() << areaF.top();
verts << frame.right() << frame.top();
verts.push_back(QVector2D(frame.right(), frame.top()));
verts.push_back(QVector2D(frame.left(), frame.top()));
verts.push_back(QVector2D(frame.left(), areaF.top()));
verts.push_back(QVector2D(frame.left(), areaF.top()));
verts.push_back(QVector2D(frame.right(), areaF.top()));
verts.push_back(QVector2D(frame.right(), frame.top()));
// left frame
verts << areaF.left() << frame.top();
verts << frame.left() << frame.top();
verts << frame.left() << frame.bottom();
verts << frame.left() << frame.bottom();
verts << areaF.left() << frame.bottom();
verts << areaF.left() << frame.top();
verts.push_back(QVector2D(areaF.left(), frame.top()));
verts.push_back(QVector2D(frame.left(), frame.top()));
verts.push_back(QVector2D(frame.left(), frame.bottom()));
verts.push_back(QVector2D(frame.left(), frame.bottom()));
verts.push_back(QVector2D(areaF.left(), frame.bottom()));
verts.push_back(QVector2D(areaF.left(), frame.top()));
// right frame
verts << frame.right() << frame.top();
verts << areaF.right() << frame.top();
verts << areaF.right() << frame.bottom();
verts << areaF.right() << frame.bottom();
verts << frame.right() << frame.bottom();
verts << frame.right() << frame.top();
verts.push_back(QVector2D(frame.right(), frame.top()));
verts.push_back(QVector2D(areaF.right(), frame.top()));
verts.push_back(QVector2D(areaF.right(), frame.bottom()));
verts.push_back(QVector2D(areaF.right(), frame.bottom()));
verts.push_back(QVector2D(frame.right(), frame.bottom()));
verts.push_back(QVector2D(frame.right(), frame.top()));
// bottom frame
verts << frame.right() << areaF.bottom();
verts << frame.left() << areaF.bottom();
verts << frame.left() << frame.bottom();
verts << frame.left() << frame.bottom();
verts << frame.right() << frame.bottom();
verts << frame.right() << areaF.bottom();
vbo->setData(verts.size() / 2, 2, verts.constData(), nullptr);
verts.push_back(QVector2D(frame.right(), areaF.bottom()));
verts.push_back(QVector2D(frame.left(), areaF.bottom()));
verts.push_back(QVector2D(frame.left(), frame.bottom()));
verts.push_back(QVector2D(frame.left(), frame.bottom()));
verts.push_back(QVector2D(frame.right(), frame.bottom()));
verts.push_back(QVector2D(frame.right(), areaF.bottom()));
vbo->setVertices(verts);
ShaderBinder binder(ShaderTrait::UniformColor);
binder.shader()->setUniform(GLShader::ModelViewProjectionMatrix, viewport.projectionMatrix());

View file

@ -279,17 +279,17 @@ void MouseClickEffect::drawCircleGl(const RenderViewport &viewport, const QColor
vbo->reset();
vbo->setUseColor(true);
vbo->setColor(color);
QVector<float> verts;
QVector<QVector2D> verts;
verts.reserve(num_segments * 2);
for (int ii = 0; ii < num_segments; ++ii) {
verts << (x + cx) * scale << (y + cy) * scale; // output vertex
verts.push_back(QVector2D((x + cx) * scale, (y + cy) * scale)); // output vertex
// apply the rotation matrix
t = x;
x = c * x - s * y;
y = s * t + c * y;
}
vbo->setData(verts.size() / 2, 2, verts.data(), nullptr);
vbo->setVertices(verts);
vbo->render(GL_LINE_LOOP);
}

View file

@ -123,23 +123,23 @@ void MouseMarkEffect::paintScreen(const RenderTarget &renderTarget, const Render
ShaderBinder binder(ShaderTrait::UniformColor | ShaderTrait::TransformColorspace);
binder.shader()->setUniform(GLShader::ModelViewProjectionMatrix, viewport.projectionMatrix());
binder.shader()->setColorspaceUniformsFromSRGB(renderTarget.colorDescription());
QVector<float> verts;
QVector<QVector2D> verts;
for (const Mark &mark : std::as_const(marks)) {
verts.clear();
verts.reserve(mark.size() * 2);
for (const QPointF &p : std::as_const(mark)) {
verts << p.x() * scale << p.y() * scale;
verts.push_back(QVector2D(p.x() * scale, p.y() * scale));
}
vbo->setData(verts.size() / 2, 2, verts.data(), nullptr);
vbo->setVertices(verts);
vbo->render(GL_LINE_STRIP);
}
if (!drawing.isEmpty()) {
verts.clear();
verts.reserve(drawing.size() * 2);
for (const QPointF &p : std::as_const(drawing)) {
verts << p.x() * scale << p.y() * scale;
verts.push_back(QVector2D(p.x() * scale, p.y() * scale));
}
vbo->setData(verts.size() / 2, 2, verts.data(), nullptr);
vbo->setVertices(verts);
vbo->render(GL_LINE_STRIP);
}
glLineWidth(1.0);

View file

@ -75,18 +75,18 @@ void ShowPaintEffect::paintGL(const QMatrix4x4 &projection, qreal scale)
QColor color = s_colors[m_colorIndex];
color.setAlphaF(s_alpha);
vbo->setColor(color);
QVector<float> verts;
QVector<QVector2D> verts;
verts.reserve(m_painted.rectCount() * 12);
for (const QRect &r : m_painted) {
const auto deviceRect = scaledRect(r, scale);
verts << deviceRect.x() + deviceRect.width() << deviceRect.y();
verts << deviceRect.x() << deviceRect.y();
verts << deviceRect.x() << deviceRect.y() + deviceRect.height();
verts << deviceRect.x() << deviceRect.y() + deviceRect.height();
verts << deviceRect.x() + deviceRect.width() << deviceRect.y() + deviceRect.height();
verts << deviceRect.x() + deviceRect.width() << deviceRect.y();
verts.push_back(QVector2D(deviceRect.x() + deviceRect.width(), deviceRect.y()));
verts.push_back(QVector2D(deviceRect.x(), deviceRect.y()));
verts.push_back(QVector2D(deviceRect.x(), deviceRect.y() + deviceRect.height()));
verts.push_back(QVector2D(deviceRect.x(), deviceRect.y() + deviceRect.height()));
verts.push_back(QVector2D(deviceRect.x() + deviceRect.width(), deviceRect.y() + deviceRect.height()));
verts.push_back(QVector2D(deviceRect.x() + deviceRect.width(), deviceRect.y()));
}
vbo->setData(verts.count() / 2, 2, verts.data(), nullptr);
vbo->setVertices(verts);
vbo->render(GL_TRIANGLES);
glDisable(GL_BLEND);
}

View file

@ -117,7 +117,7 @@ void SnapHelperEffect::paintScreen(const RenderTarget &renderTarget, const Rende
vbo->setColor(color);
glLineWidth(s_lineWidth);
QVector<float> verts;
QVector<QVector2D> verts;
verts.reserve(screens.count() * 24);
for (EffectScreen *screen : screens) {
const QRectF rect = effects->clientArea(ScreenArea, screen, effects->currentDesktop());
@ -127,30 +127,30 @@ void SnapHelperEffect::paintScreen(const RenderTarget &renderTarget, const Rende
const int halfHeight = m_geometry.height() / 2;
// Center vertical line.
verts << (rect.x() + rect.width() / 2) * scale << rect.y() * scale;
verts << (rect.x() + rect.width() / 2) * scale << (rect.y() + rect.height()) * scale;
verts.push_back(QVector2D((rect.x() + rect.width() / 2) * scale, rect.y() * scale));
verts.push_back(QVector2D((rect.x() + rect.width() / 2) * scale, (rect.y() + rect.height()) * scale));
// Center horizontal line.
verts << rect.x() * scale << (rect.y() + rect.height() / 2) * scale;
verts << (rect.x() + rect.width()) * scale << (rect.y() + rect.height() / 2) * scale;
verts.push_back(QVector2D(rect.x() * scale, (rect.y() + rect.height() / 2) * scale));
verts.push_back(QVector2D((rect.x() + rect.width()) * scale, (rect.y() + rect.height() / 2) * scale));
// Top edge of the window outline.
verts << (midX - halfWidth - s_lineWidth / 2) * scale << (midY - halfHeight) * scale;
verts << (midX + halfWidth + s_lineWidth / 2) * scale << (midY - halfHeight) * scale;
verts.push_back(QVector2D((midX - halfWidth - s_lineWidth / 2) * scale, (midY - halfHeight) * scale));
verts.push_back(QVector2D((midX + halfWidth + s_lineWidth / 2) * scale, (midY - halfHeight) * scale));
// Right edge of the window outline.
verts << (midX + halfWidth) * scale << (midY - halfHeight + s_lineWidth / 2) * scale;
verts << (midX + halfWidth) * scale << (midY + halfHeight - s_lineWidth / 2) * scale;
verts.push_back(QVector2D((midX + halfWidth) * scale, (midY - halfHeight + s_lineWidth / 2) * scale));
verts.push_back(QVector2D((midX + halfWidth) * scale, (midY + halfHeight - s_lineWidth / 2) * scale));
// Bottom edge of the window outline.
verts << (midX + halfWidth + s_lineWidth / 2) * scale << (midY + halfHeight) * scale;
verts << (midX - halfWidth - s_lineWidth / 2) * scale << (midY + halfHeight) * scale;
verts.push_back(QVector2D((midX + halfWidth + s_lineWidth / 2) * scale, (midY + halfHeight) * scale));
verts.push_back(QVector2D((midX - halfWidth - s_lineWidth / 2) * scale, (midY + halfHeight) * scale));
// Left edge of the window outline.
verts << (midX - halfWidth) * scale << (midY + halfHeight - s_lineWidth / 2) * scale;
verts << (midX - halfWidth) * scale << (midY - halfHeight + s_lineWidth / 2) * scale;
verts.push_back(QVector2D((midX - halfWidth) * scale, (midY + halfHeight - s_lineWidth / 2) * scale));
verts.push_back(QVector2D((midX - halfWidth) * scale, (midY - halfHeight + s_lineWidth / 2) * scale));
}
vbo->setData(verts.count() / 2, 2, verts.data(), nullptr);
vbo->setVertices(verts);
vbo->render(GL_LINES);
glDisable(GL_BLEND);

View file

@ -205,17 +205,17 @@ void TouchPointsEffect::drawCircleGl(const RenderViewport &viewport, const QColo
vbo->reset();
vbo->setUseColor(true);
vbo->setColor(color);
QVector<float> verts;
verts.reserve(num_segments * 2);
QVector<QVector2D> verts;
verts.reserve(num_segments);
for (int ii = 0; ii < num_segments; ++ii) {
verts << (x + cx) * scale << (y + cy) * scale; // output vertex
verts.push_back(QVector2D((x + cx) * scale, (y + cy) * scale));
// apply the rotation matrix
t = x;
x = c * x - s * y;
y = s * t + c * y;
}
vbo->setData(verts.size() / 2, 2, verts.data(), nullptr);
vbo->setVertices(verts);
vbo->render(GL_LINE_LOOP);
}