libkwineffects/glvertexbuffer: add a better helper for uploading vertices
This commit is contained in:
parent
cbe8d21f07
commit
617f3b9000
9 changed files with 118 additions and 102 deletions
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -353,15 +353,6 @@ void GLTexture::render(const QRectF &source, const QRegion ®ion, 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 ®ion, 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);
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue