Move WindowVertex,WindowQuad,RenderGeometry out of effects.h
These are core scene abstractions and don't belong in effects.h.
This commit is contained in:
parent
86084d118c
commit
961bd00919
32 changed files with 624 additions and 581 deletions
|
@ -6,7 +6,7 @@
|
|||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#include "effect/effects.h"
|
||||
#include "scene/itemgeometry.h"
|
||||
#include <QTest>
|
||||
|
||||
Q_DECLARE_METATYPE(KWin::WindowQuadList)
|
||||
|
|
|
@ -160,6 +160,7 @@ target_sources(kwin PRIVATE
|
|||
scene/dndiconitem.cpp
|
||||
scene/imageitem.cpp
|
||||
scene/item.cpp
|
||||
scene/itemgeometry.cpp
|
||||
scene/itemrenderer.cpp
|
||||
scene/itemrenderer_opengl.cpp
|
||||
scene/itemrenderer_qpainter.cpp
|
||||
|
@ -461,6 +462,12 @@ install(FILES
|
|||
DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kwin/opengl COMPONENT Devel
|
||||
)
|
||||
|
||||
install(FILES
|
||||
scene/item.h
|
||||
scene/itemgeometry.h
|
||||
DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kwin/scene COMPONENT Devel
|
||||
)
|
||||
|
||||
set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/KWin")
|
||||
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/KWinConfig.cmake"
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "core/overlaywindow.h"
|
||||
#include "core/renderbackend.h"
|
||||
#include "core/renderlayer.h"
|
||||
#include "effect/effects.h"
|
||||
#include "opengl/glplatform.h"
|
||||
#include "options.h"
|
||||
#include "platformsupport/scenes/opengl/openglbackend.h"
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "compositor.h"
|
||||
#include "core/graphicsbufferview.h"
|
||||
#include "core/inputdevice.h"
|
||||
#include "effect/effects.h"
|
||||
#include "input_event.h"
|
||||
#include "internalwindow.h"
|
||||
#include "keyboard_input.h"
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "effect/animationeffect.h"
|
||||
#include "effect/effects.h"
|
||||
#include "effect/timeline.h"
|
||||
|
||||
#include <QEasingCurve>
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <config-kwin.h>
|
||||
// KWin
|
||||
#include "effect/effect.h"
|
||||
#include "effect/effects.h"
|
||||
#include "plugin.h"
|
||||
#include "scripting/scriptedeffect.h"
|
||||
#include "scripting/scriptedquicksceneeffect.h"
|
||||
|
@ -350,7 +351,7 @@ bool PluginEffectLoader::loadEffect(const KPluginMetaData &info, LoadEffectFlags
|
|||
return false;
|
||||
}
|
||||
|
||||
effects->makeOpenGLContextCurrent();
|
||||
effects->makeOpenGLContextCurrent(); // TODO: remove it
|
||||
if (!effectFactory->isSupported()) {
|
||||
qCDebug(KWIN_CORE) << "Effect is not supported: " << name;
|
||||
return false;
|
||||
|
|
|
@ -2119,299 +2119,6 @@ EffectWindowList EffectWindowGroup::members() const
|
|||
return ret;
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
WindowQuad
|
||||
***************************************************************/
|
||||
|
||||
WindowQuad WindowQuad::makeSubQuad(double x1, double y1, double x2, double y2) const
|
||||
{
|
||||
Q_ASSERT(x1 < x2 && y1 < y2 && x1 >= left() && x2 <= right() && y1 >= top() && y2 <= bottom());
|
||||
WindowQuad ret(*this);
|
||||
// vertices are clockwise starting from topleft
|
||||
ret.verts[0].px = x1;
|
||||
ret.verts[3].px = x1;
|
||||
ret.verts[1].px = x2;
|
||||
ret.verts[2].px = x2;
|
||||
ret.verts[0].py = y1;
|
||||
ret.verts[1].py = y1;
|
||||
ret.verts[2].py = y2;
|
||||
ret.verts[3].py = y2;
|
||||
|
||||
const double xOrigin = left();
|
||||
const double yOrigin = top();
|
||||
|
||||
const double widthReciprocal = 1 / (right() - xOrigin);
|
||||
const double heightReciprocal = 1 / (bottom() - yOrigin);
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
const double w1 = (ret.verts[i].px - xOrigin) * widthReciprocal;
|
||||
const double w2 = (ret.verts[i].py - yOrigin) * heightReciprocal;
|
||||
|
||||
// Use bilinear interpolation to compute the texture coords.
|
||||
ret.verts[i].tx = (1 - w1) * (1 - w2) * verts[0].tx + w1 * (1 - w2) * verts[1].tx + w1 * w2 * verts[2].tx + (1 - w1) * w2 * verts[3].tx;
|
||||
ret.verts[i].ty = (1 - w1) * (1 - w2) * verts[0].ty + w1 * (1 - w2) * verts[1].ty + w1 * w2 * verts[2].ty + (1 - w1) * w2 * verts[3].ty;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
WindowQuadList
|
||||
***************************************************************/
|
||||
|
||||
WindowQuadList WindowQuadList::splitAtX(double x) const
|
||||
{
|
||||
WindowQuadList ret;
|
||||
ret.reserve(count());
|
||||
for (const WindowQuad &quad : *this) {
|
||||
bool wholeleft = true;
|
||||
bool wholeright = true;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (quad[i].x() < x) {
|
||||
wholeright = false;
|
||||
}
|
||||
if (quad[i].x() > x) {
|
||||
wholeleft = false;
|
||||
}
|
||||
}
|
||||
if (wholeleft || wholeright) { // is whole in one split part
|
||||
ret.append(quad);
|
||||
continue;
|
||||
}
|
||||
if (quad.top() == quad.bottom() || quad.left() == quad.right()) { // quad has no size
|
||||
ret.append(quad);
|
||||
continue;
|
||||
}
|
||||
ret.append(quad.makeSubQuad(quad.left(), quad.top(), x, quad.bottom()));
|
||||
ret.append(quad.makeSubQuad(x, quad.top(), quad.right(), quad.bottom()));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
WindowQuadList WindowQuadList::splitAtY(double y) const
|
||||
{
|
||||
WindowQuadList ret;
|
||||
ret.reserve(count());
|
||||
for (const WindowQuad &quad : *this) {
|
||||
bool wholetop = true;
|
||||
bool wholebottom = true;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (quad[i].y() < y) {
|
||||
wholebottom = false;
|
||||
}
|
||||
if (quad[i].y() > y) {
|
||||
wholetop = false;
|
||||
}
|
||||
}
|
||||
if (wholetop || wholebottom) { // is whole in one split part
|
||||
ret.append(quad);
|
||||
continue;
|
||||
}
|
||||
if (quad.top() == quad.bottom() || quad.left() == quad.right()) { // quad has no size
|
||||
ret.append(quad);
|
||||
continue;
|
||||
}
|
||||
ret.append(quad.makeSubQuad(quad.left(), quad.top(), quad.right(), y));
|
||||
ret.append(quad.makeSubQuad(quad.left(), y, quad.right(), quad.bottom()));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
WindowQuadList WindowQuadList::makeGrid(int maxQuadSize) const
|
||||
{
|
||||
if (empty()) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Find the bounding rectangle
|
||||
double left = first().left();
|
||||
double right = first().right();
|
||||
double top = first().top();
|
||||
double bottom = first().bottom();
|
||||
|
||||
for (const WindowQuad &quad : std::as_const(*this)) {
|
||||
left = std::min(left, quad.left());
|
||||
right = std::max(right, quad.right());
|
||||
top = std::min(top, quad.top());
|
||||
bottom = std::max(bottom, quad.bottom());
|
||||
}
|
||||
|
||||
WindowQuadList ret;
|
||||
|
||||
for (const WindowQuad &quad : std::as_const(*this)) {
|
||||
const double quadLeft = quad.left();
|
||||
const double quadRight = quad.right();
|
||||
const double quadTop = quad.top();
|
||||
const double quadBottom = quad.bottom();
|
||||
|
||||
// sanity check, see BUG 390953
|
||||
if (quadLeft == quadRight || quadTop == quadBottom) {
|
||||
ret.append(quad);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Compute the top-left corner of the first intersecting grid cell
|
||||
const double xBegin = left + qFloor((quadLeft - left) / maxQuadSize) * maxQuadSize;
|
||||
const double yBegin = top + qFloor((quadTop - top) / maxQuadSize) * maxQuadSize;
|
||||
|
||||
// Loop over all intersecting cells and add sub-quads
|
||||
for (double y = yBegin; y < quadBottom; y += maxQuadSize) {
|
||||
const double y0 = std::max(y, quadTop);
|
||||
const double y1 = std::min(quadBottom, y + maxQuadSize);
|
||||
|
||||
for (double x = xBegin; x < quadRight; x += maxQuadSize) {
|
||||
const double x0 = std::max(x, quadLeft);
|
||||
const double x1 = std::min(quadRight, x + maxQuadSize);
|
||||
|
||||
ret.append(quad.makeSubQuad(x0, y0, x1, y1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
WindowQuadList WindowQuadList::makeRegularGrid(int xSubdivisions, int ySubdivisions) const
|
||||
{
|
||||
if (empty()) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Find the bounding rectangle
|
||||
double left = first().left();
|
||||
double right = first().right();
|
||||
double top = first().top();
|
||||
double bottom = first().bottom();
|
||||
|
||||
for (const WindowQuad &quad : *this) {
|
||||
left = std::min(left, quad.left());
|
||||
right = std::max(right, quad.right());
|
||||
top = std::min(top, quad.top());
|
||||
bottom = std::max(bottom, quad.bottom());
|
||||
}
|
||||
|
||||
double xIncrement = (right - left) / xSubdivisions;
|
||||
double yIncrement = (bottom - top) / ySubdivisions;
|
||||
|
||||
WindowQuadList ret;
|
||||
|
||||
for (const WindowQuad &quad : *this) {
|
||||
const double quadLeft = quad.left();
|
||||
const double quadRight = quad.right();
|
||||
const double quadTop = quad.top();
|
||||
const double quadBottom = quad.bottom();
|
||||
|
||||
// sanity check, see BUG 390953
|
||||
if (quadLeft == quadRight || quadTop == quadBottom) {
|
||||
ret.append(quad);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Compute the top-left corner of the first intersecting grid cell
|
||||
const double xBegin = left + qFloor((quadLeft - left) / xIncrement) * xIncrement;
|
||||
const double yBegin = top + qFloor((quadTop - top) / yIncrement) * yIncrement;
|
||||
|
||||
// Loop over all intersecting cells and add sub-quads
|
||||
for (double y = yBegin; y < quadBottom; y += yIncrement) {
|
||||
const double y0 = std::max(y, quadTop);
|
||||
const double y1 = std::min(quadBottom, y + yIncrement);
|
||||
|
||||
for (double x = xBegin; x < quadRight; x += xIncrement) {
|
||||
const double x0 = std::max(x, quadLeft);
|
||||
const double x1 = std::min(quadRight, x + xIncrement);
|
||||
|
||||
ret.append(quad.makeSubQuad(x0, y0, x1, y1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void RenderGeometry::copy(std::span<GLVertex2D> destination)
|
||||
{
|
||||
Q_ASSERT(int(destination.size()) >= size());
|
||||
std::copy(cbegin(), cend(), destination.begin());
|
||||
}
|
||||
|
||||
void RenderGeometry::appendWindowVertex(const WindowVertex &windowVertex, qreal deviceScale)
|
||||
{
|
||||
GLVertex2D glVertex;
|
||||
switch (m_vertexSnappingMode) {
|
||||
case VertexSnappingMode::None:
|
||||
glVertex.position = QVector2D(windowVertex.x(), windowVertex.y()) * deviceScale;
|
||||
break;
|
||||
case VertexSnappingMode::Round:
|
||||
glVertex.position = roundVector(QVector2D(windowVertex.x(), windowVertex.y()) * deviceScale);
|
||||
break;
|
||||
}
|
||||
glVertex.texcoord = QVector2D(windowVertex.u(), windowVertex.v());
|
||||
append(glVertex);
|
||||
}
|
||||
|
||||
void RenderGeometry::appendWindowQuad(const WindowQuad &quad, qreal deviceScale)
|
||||
{
|
||||
// Geometry assumes we're rendering triangles, so add the quad's
|
||||
// vertices as two triangles. Vertex order is top-left, bottom-left,
|
||||
// top-right followed by top-right, bottom-left, bottom-right.
|
||||
appendWindowVertex(quad[0], deviceScale);
|
||||
appendWindowVertex(quad[3], deviceScale);
|
||||
appendWindowVertex(quad[1], deviceScale);
|
||||
|
||||
appendWindowVertex(quad[1], deviceScale);
|
||||
appendWindowVertex(quad[3], deviceScale);
|
||||
appendWindowVertex(quad[2], deviceScale);
|
||||
}
|
||||
|
||||
void RenderGeometry::appendSubQuad(const WindowQuad &quad, const QRectF &subquad, qreal deviceScale)
|
||||
{
|
||||
std::array<GLVertex2D, 4> vertices;
|
||||
vertices[0].position = QVector2D(subquad.topLeft());
|
||||
vertices[1].position = QVector2D(subquad.topRight());
|
||||
vertices[2].position = QVector2D(subquad.bottomRight());
|
||||
vertices[3].position = QVector2D(subquad.bottomLeft());
|
||||
|
||||
const auto deviceQuad = QRectF{QPointF(std::round(quad.left() * deviceScale), std::round(quad.top() * deviceScale)),
|
||||
QPointF(std::round(quad.right() * deviceScale), std::round(quad.bottom() * deviceScale))};
|
||||
|
||||
const QPointF origin = deviceQuad.topLeft();
|
||||
const QSizeF size = deviceQuad.size();
|
||||
|
||||
#pragma GCC unroll 4
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
const double weight1 = (vertices[i].position.x() - origin.x()) / size.width();
|
||||
const double weight2 = (vertices[i].position.y() - origin.y()) / size.height();
|
||||
const double oneMinW1 = 1.0 - weight1;
|
||||
const double oneMinW2 = 1.0 - weight2;
|
||||
|
||||
const float u = oneMinW1 * oneMinW2 * quad[0].u() + weight1 * oneMinW2 * quad[1].u()
|
||||
+ weight1 * weight2 * quad[2].u() + oneMinW1 * weight2 * quad[3].u();
|
||||
const float v = oneMinW1 * oneMinW2 * quad[0].v() + weight1 * oneMinW2 * quad[1].v()
|
||||
+ weight1 * weight2 * quad[2].v() + oneMinW1 * weight2 * quad[3].v();
|
||||
vertices[i].texcoord = QVector2D(u, v);
|
||||
}
|
||||
|
||||
append(vertices[0]);
|
||||
append(vertices[3]);
|
||||
append(vertices[1]);
|
||||
|
||||
append(vertices[1]);
|
||||
append(vertices[3]);
|
||||
append(vertices[2]);
|
||||
}
|
||||
|
||||
void RenderGeometry::postProcessTextureCoordinates(const QMatrix4x4 &textureMatrix)
|
||||
{
|
||||
if (!textureMatrix.isIdentity()) {
|
||||
const QVector2D coeff(textureMatrix(0, 0), textureMatrix(1, 1));
|
||||
const QVector2D offset(textureMatrix(0, 3), textureMatrix(1, 3));
|
||||
|
||||
for (auto &vertex : (*this)) {
|
||||
vertex.texcoord = vertex.texcoord * coeff + offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#include "moc_effects.cpp"
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "effect/effect.h"
|
||||
#include "opengl/glvertexbuffer.h"
|
||||
|
||||
#include <QEasingCurve>
|
||||
#include <QIcon>
|
||||
|
@ -21,8 +20,6 @@
|
|||
#include <QRect>
|
||||
#include <QRegion>
|
||||
#include <QSet>
|
||||
#include <QVector2D>
|
||||
#include <QVector3D>
|
||||
|
||||
#include <QHash>
|
||||
#include <QList>
|
||||
|
@ -80,8 +77,6 @@ class TabletToolId;
|
|||
class Window;
|
||||
class WindowItem;
|
||||
class WindowPropertyNotifyX11Filter;
|
||||
class WindowQuad;
|
||||
class WindowQuadList;
|
||||
class WorkspaceScene;
|
||||
class VirtualDesktop;
|
||||
|
||||
|
@ -2067,289 +2062,11 @@ private:
|
|||
Group *m_group;
|
||||
};
|
||||
|
||||
/**
|
||||
* @short Vertex class
|
||||
*
|
||||
* A vertex is one position in a window. WindowQuad consists of four WindowVertex objects
|
||||
* and represents one part of a window.
|
||||
*/
|
||||
class KWIN_EXPORT WindowVertex
|
||||
{
|
||||
public:
|
||||
WindowVertex();
|
||||
WindowVertex(const QPointF &position, const QPointF &textureCoordinate);
|
||||
WindowVertex(double x, double y, double tx, double ty);
|
||||
|
||||
double x() const
|
||||
{
|
||||
return px;
|
||||
}
|
||||
double y() const
|
||||
{
|
||||
return py;
|
||||
}
|
||||
double u() const
|
||||
{
|
||||
return tx;
|
||||
}
|
||||
double v() const
|
||||
{
|
||||
return ty;
|
||||
}
|
||||
void move(double x, double y);
|
||||
void setX(double x);
|
||||
void setY(double y);
|
||||
|
||||
private:
|
||||
friend class WindowQuad;
|
||||
friend class WindowQuadList;
|
||||
double px, py; // position
|
||||
double tx, ty; // texture coords
|
||||
};
|
||||
|
||||
/**
|
||||
* @short Class representing one area of a window.
|
||||
*
|
||||
* WindowQuads consists of four WindowVertex objects and represents one part of a window.
|
||||
*/
|
||||
// NOTE: This class expects the (original) vertices to be in the clockwise order starting from topleft.
|
||||
class KWIN_EXPORT WindowQuad
|
||||
{
|
||||
public:
|
||||
WindowQuad();
|
||||
WindowQuad makeSubQuad(double x1, double y1, double x2, double y2) const;
|
||||
WindowVertex &operator[](int index);
|
||||
const WindowVertex &operator[](int index) const;
|
||||
double left() const;
|
||||
double right() const;
|
||||
double top() const;
|
||||
double bottom() const;
|
||||
QRectF bounds() const;
|
||||
|
||||
private:
|
||||
friend class WindowQuadList;
|
||||
WindowVertex verts[4];
|
||||
};
|
||||
|
||||
class KWIN_EXPORT WindowQuadList
|
||||
: public QList<WindowQuad>
|
||||
{
|
||||
public:
|
||||
WindowQuadList splitAtX(double x) const;
|
||||
WindowQuadList splitAtY(double y) const;
|
||||
WindowQuadList makeGrid(int maxquadsize) const;
|
||||
WindowQuadList makeRegularGrid(int xSubdivisions, int ySubdivisions) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* A helper class for render geometry in device coordinates.
|
||||
*
|
||||
* This mostly represents a vector of vertices, with some convenience methods
|
||||
* for easily converting from WindowQuad and related classes to lists of
|
||||
* GLVertex2D. This class assumes rendering happens as unindexed triangles.
|
||||
*/
|
||||
class KWIN_EXPORT RenderGeometry : public QList<GLVertex2D>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* In what way should vertices snap to integer device coordinates?
|
||||
*
|
||||
* Vertices are converted to device coordinates before being sent to the
|
||||
* rendering system. Depending on scaling factors, this may lead to device
|
||||
* coordinates with fractional parts. For some cases, this may not be ideal
|
||||
* as fractional coordinates need to be interpolated and can lead to
|
||||
* "blurry" rendering. To avoid that, we can snap the vertices to integer
|
||||
* device coordinates when they are added.
|
||||
*/
|
||||
enum class VertexSnappingMode {
|
||||
None, //< No rounding, device coordinates containing fractional parts
|
||||
// are passed directly to the rendering system.
|
||||
Round, //< Perform a simple rounding, device coordinates will not have
|
||||
// any fractional parts.
|
||||
};
|
||||
|
||||
/**
|
||||
* The vertex snapping mode to use for this geometry.
|
||||
*
|
||||
* By default, this is VertexSnappingMode::Round.
|
||||
*/
|
||||
inline VertexSnappingMode vertexSnappingMode() const
|
||||
{
|
||||
return m_vertexSnappingMode;
|
||||
}
|
||||
/**
|
||||
* Set the vertex snapping mode to use for this geometry.
|
||||
*
|
||||
* Note that this doesn't change vertices retroactively, so you should set
|
||||
* this before adding any vertices, or clear and rebuild the geometry after
|
||||
* setting it.
|
||||
*
|
||||
* @param mode The new rounding mode.
|
||||
*/
|
||||
void setVertexSnappingMode(VertexSnappingMode mode)
|
||||
{
|
||||
m_vertexSnappingMode = mode;
|
||||
}
|
||||
/**
|
||||
* Copy geometry data into another buffer.
|
||||
*
|
||||
* This is primarily intended for copying into a vertex buffer for rendering.
|
||||
*
|
||||
* @param destination The destination buffer. This needs to be at least large
|
||||
* enough to contain all elements.
|
||||
*/
|
||||
void copy(std::span<GLVertex2D> destination);
|
||||
/**
|
||||
* Append a WindowVertex as a geometry vertex.
|
||||
*
|
||||
* WindowVertex is assumed to be in logical coordinates. It will be converted
|
||||
* to device coordinates using the specified device scale and then rounded
|
||||
* so it fits correctly on the device pixel grid.
|
||||
*
|
||||
* @param windowVertex The WindowVertex instance to append.
|
||||
* @param deviceScale The scaling factor to use to go from logical to device
|
||||
* coordinates.
|
||||
*/
|
||||
void appendWindowVertex(const WindowVertex &windowVertex, qreal deviceScale);
|
||||
/**
|
||||
* Append a WindowQuad as two triangles.
|
||||
*
|
||||
* This will append the corners of the specified WindowQuad in the right
|
||||
* order so they make two triangles that can be rendered by OpenGL. The
|
||||
* corners are converted to device coordinates and rounded, just like
|
||||
* `appendWindowVertex()` does.
|
||||
*
|
||||
* @param quad The WindowQuad instance to append.
|
||||
* @param deviceScale The scaling factor to use to go from logical to device
|
||||
* coordinates.
|
||||
*/
|
||||
void appendWindowQuad(const WindowQuad &quad, qreal deviceScale);
|
||||
/**
|
||||
* Append a sub-quad of a WindowQuad as two triangles.
|
||||
*
|
||||
* This will append the sub-quad specified by `intersection` as two
|
||||
* triangles. The quad is expected to be in logical coordinates, while the
|
||||
* intersection is expected to be in device coordinates. The texture
|
||||
* coordinates of the resulting vertices are based upon those of the quad,
|
||||
* using bilinear interpolation for interpolating how much of the original
|
||||
* texture coordinates to use.
|
||||
*
|
||||
* @param quad The WindowQuad instance to use a sub-quad of.
|
||||
* @param subquad The sub-quad to append.
|
||||
* @param deviceScale The scaling factor used to convert from logical to
|
||||
* device coordinates.
|
||||
*/
|
||||
void appendSubQuad(const WindowQuad &quad, const QRectF &subquad, qreal deviceScale);
|
||||
/**
|
||||
* Modify this geometry's texture coordinates based on a matrix.
|
||||
*
|
||||
* This is primarily intended to convert from non-normalised to normalised
|
||||
* texture coordinates.
|
||||
*
|
||||
* @param textureMatrix The texture matrix to use for modifying the
|
||||
* texture coordinates. Note that only the 2D scale and
|
||||
* translation are used.
|
||||
*/
|
||||
void postProcessTextureCoordinates(const QMatrix4x4 &textureMatrix);
|
||||
|
||||
private:
|
||||
VertexSnappingMode m_vertexSnappingMode = VertexSnappingMode::Round;
|
||||
};
|
||||
|
||||
/**
|
||||
* Pointer to the global EffectsHandler object.
|
||||
*/
|
||||
extern KWIN_EXPORT EffectsHandler *effects;
|
||||
|
||||
/***************************************************************
|
||||
WindowVertex
|
||||
***************************************************************/
|
||||
|
||||
inline WindowVertex::WindowVertex()
|
||||
: px(0)
|
||||
, py(0)
|
||||
, tx(0)
|
||||
, ty(0)
|
||||
{
|
||||
}
|
||||
|
||||
inline WindowVertex::WindowVertex(double _x, double _y, double _tx, double _ty)
|
||||
: px(_x)
|
||||
, py(_y)
|
||||
, tx(_tx)
|
||||
, ty(_ty)
|
||||
{
|
||||
}
|
||||
|
||||
inline WindowVertex::WindowVertex(const QPointF &position, const QPointF &texturePosition)
|
||||
: px(position.x())
|
||||
, py(position.y())
|
||||
, tx(texturePosition.x())
|
||||
, ty(texturePosition.y())
|
||||
{
|
||||
}
|
||||
|
||||
inline void WindowVertex::move(double x, double y)
|
||||
{
|
||||
px = x;
|
||||
py = y;
|
||||
}
|
||||
|
||||
inline void WindowVertex::setX(double x)
|
||||
{
|
||||
px = x;
|
||||
}
|
||||
|
||||
inline void WindowVertex::setY(double y)
|
||||
{
|
||||
py = y;
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
WindowQuad
|
||||
***************************************************************/
|
||||
|
||||
inline WindowQuad::WindowQuad()
|
||||
{
|
||||
}
|
||||
|
||||
inline WindowVertex &WindowQuad::operator[](int index)
|
||||
{
|
||||
Q_ASSERT(index >= 0 && index < 4);
|
||||
return verts[index];
|
||||
}
|
||||
|
||||
inline const WindowVertex &WindowQuad::operator[](int index) const
|
||||
{
|
||||
Q_ASSERT(index >= 0 && index < 4);
|
||||
return verts[index];
|
||||
}
|
||||
|
||||
inline double WindowQuad::left() const
|
||||
{
|
||||
return std::min(verts[0].px, std::min(verts[1].px, std::min(verts[2].px, verts[3].px)));
|
||||
}
|
||||
|
||||
inline double WindowQuad::right() const
|
||||
{
|
||||
return std::max(verts[0].px, std::max(verts[1].px, std::max(verts[2].px, verts[3].px)));
|
||||
}
|
||||
|
||||
inline double WindowQuad::top() const
|
||||
{
|
||||
return std::min(verts[0].py, std::min(verts[1].py, std::min(verts[2].py, verts[3].py)));
|
||||
}
|
||||
|
||||
inline double WindowQuad::bottom() const
|
||||
{
|
||||
return std::max(verts[0].py, std::max(verts[1].py, std::max(verts[2].py, verts[3].py)));
|
||||
}
|
||||
|
||||
inline QRectF WindowQuad::bounds() const
|
||||
{
|
||||
return QRectF(QPointF(left(), top()), QPointF(right(), bottom()));
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
EffectWindow
|
||||
***************************************************************/
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "core/output.h"
|
||||
#include "core/rendertarget.h"
|
||||
#include "core/renderviewport.h"
|
||||
#include "effect/effects.h"
|
||||
#include "opengl/gltexture.h"
|
||||
#include "opengl/glutils.h"
|
||||
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "effect/effects.h"
|
||||
#include "effect/effect.h"
|
||||
#include "scene/itemgeometry.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
*/
|
||||
|
||||
#include "group.h"
|
||||
#include "effect/effects.h"
|
||||
#include "workspace.h"
|
||||
#include "x11window.h"
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "backends/libinput/device.h"
|
||||
#include "core/inputbackend.h"
|
||||
#include "core/session.h"
|
||||
#include "effect/effects.h"
|
||||
#include "gestures.h"
|
||||
#include "globalshortcuts.h"
|
||||
#include "hide_cursor_spy.h"
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "effect/effects.h"
|
||||
#include "effect/offscreeneffect.h"
|
||||
|
||||
namespace KWin
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
*/
|
||||
|
||||
#include "highlightwindow.h"
|
||||
#include "effect/effects.h"
|
||||
|
||||
#include <QDBusConnection>
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include "invert.h"
|
||||
|
||||
#include "effect/effects.h"
|
||||
#include "opengl/glplatform.h"
|
||||
#include "opengl/glutils.h"
|
||||
#include <KGlobalAccel>
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "effect/effects.h"
|
||||
#include "effect/offscreeneffect.h"
|
||||
#include "effect/timeline.h"
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "core/renderloop.h"
|
||||
#include "core/rendertarget.h"
|
||||
#include "core/renderviewport.h"
|
||||
#include "effect/effect.h"
|
||||
#include "opengl/gltexture.h"
|
||||
#include "opengl/glutils.h"
|
||||
#include "scene/itemrenderer.h"
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
*/
|
||||
|
||||
#include "wobblywindows.h"
|
||||
#include "effect/effects.h"
|
||||
#include "wobblywindowsconfig.h"
|
||||
|
||||
#include <cmath>
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "core/output.h"
|
||||
#include "cursorsource.h"
|
||||
#include "decorations/decoratedclient.h"
|
||||
#include "effect/effects.h"
|
||||
#include "input_event.h"
|
||||
#include "input_event_spy.h"
|
||||
#include "mousebuttons.h"
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "scene/cursoritem.h"
|
||||
#include "cursor.h"
|
||||
#include "cursorsource.h"
|
||||
#include "effect/effect.h"
|
||||
#include "scene/imageitem.h"
|
||||
#include "scene/itemrenderer.h"
|
||||
#include "scene/scene.h"
|
||||
|
|
|
@ -12,6 +12,7 @@ namespace KWin
|
|||
{
|
||||
|
||||
class ImageItem;
|
||||
class SurfaceInterface;
|
||||
class SurfaceItemWayland;
|
||||
|
||||
class CursorItem : public Item
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "core/output.h"
|
||||
#include "core/rendertarget.h"
|
||||
#include "core/renderviewport.h"
|
||||
#include "effect/effect.h"
|
||||
#include "scene/cursoritem.h"
|
||||
#include "scene/itemrenderer.h"
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ namespace KWin
|
|||
{
|
||||
|
||||
class DragAndDropIcon;
|
||||
class SurfaceInterface;
|
||||
class SurfaceItemWayland;
|
||||
class PresentationFeedback;
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
#include "scene/item.h"
|
||||
|
||||
#include <QImage>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "core/colorspace.h"
|
||||
#include "effect/effects.h"
|
||||
#include "effect/globals.h"
|
||||
#include "scene/itemgeometry.h"
|
||||
|
||||
#include <QList>
|
||||
#include <QMatrix4x4>
|
||||
|
|
301
src/scene/itemgeometry.cpp
Normal file
301
src/scene/itemgeometry.cpp
Normal file
|
@ -0,0 +1,301 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2006 Lubos Lunak <l.lunak@kde.org>
|
||||
SPDX-FileCopyrightText: 2022 Arjen Hiemstra <ahiemstra@heimr.nl>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "scene/itemgeometry.h"
|
||||
#include "effect/globals.h"
|
||||
|
||||
#include <QMatrix4x4>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
WindowQuad WindowQuad::makeSubQuad(double x1, double y1, double x2, double y2) const
|
||||
{
|
||||
Q_ASSERT(x1 < x2 && y1 < y2 && x1 >= left() && x2 <= right() && y1 >= top() && y2 <= bottom());
|
||||
WindowQuad ret(*this);
|
||||
// vertices are clockwise starting from topleft
|
||||
ret.verts[0].px = x1;
|
||||
ret.verts[3].px = x1;
|
||||
ret.verts[1].px = x2;
|
||||
ret.verts[2].px = x2;
|
||||
ret.verts[0].py = y1;
|
||||
ret.verts[1].py = y1;
|
||||
ret.verts[2].py = y2;
|
||||
ret.verts[3].py = y2;
|
||||
|
||||
const double xOrigin = left();
|
||||
const double yOrigin = top();
|
||||
|
||||
const double widthReciprocal = 1 / (right() - xOrigin);
|
||||
const double heightReciprocal = 1 / (bottom() - yOrigin);
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
const double w1 = (ret.verts[i].px - xOrigin) * widthReciprocal;
|
||||
const double w2 = (ret.verts[i].py - yOrigin) * heightReciprocal;
|
||||
|
||||
// Use bilinear interpolation to compute the texture coords.
|
||||
ret.verts[i].tx = (1 - w1) * (1 - w2) * verts[0].tx + w1 * (1 - w2) * verts[1].tx + w1 * w2 * verts[2].tx + (1 - w1) * w2 * verts[3].tx;
|
||||
ret.verts[i].ty = (1 - w1) * (1 - w2) * verts[0].ty + w1 * (1 - w2) * verts[1].ty + w1 * w2 * verts[2].ty + (1 - w1) * w2 * verts[3].ty;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
WindowQuadList WindowQuadList::splitAtX(double x) const
|
||||
{
|
||||
WindowQuadList ret;
|
||||
ret.reserve(count());
|
||||
for (const WindowQuad &quad : *this) {
|
||||
bool wholeleft = true;
|
||||
bool wholeright = true;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (quad[i].x() < x) {
|
||||
wholeright = false;
|
||||
}
|
||||
if (quad[i].x() > x) {
|
||||
wholeleft = false;
|
||||
}
|
||||
}
|
||||
if (wholeleft || wholeright) { // is whole in one split part
|
||||
ret.append(quad);
|
||||
continue;
|
||||
}
|
||||
if (quad.top() == quad.bottom() || quad.left() == quad.right()) { // quad has no size
|
||||
ret.append(quad);
|
||||
continue;
|
||||
}
|
||||
ret.append(quad.makeSubQuad(quad.left(), quad.top(), x, quad.bottom()));
|
||||
ret.append(quad.makeSubQuad(x, quad.top(), quad.right(), quad.bottom()));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
WindowQuadList WindowQuadList::splitAtY(double y) const
|
||||
{
|
||||
WindowQuadList ret;
|
||||
ret.reserve(count());
|
||||
for (const WindowQuad &quad : *this) {
|
||||
bool wholetop = true;
|
||||
bool wholebottom = true;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (quad[i].y() < y) {
|
||||
wholebottom = false;
|
||||
}
|
||||
if (quad[i].y() > y) {
|
||||
wholetop = false;
|
||||
}
|
||||
}
|
||||
if (wholetop || wholebottom) { // is whole in one split part
|
||||
ret.append(quad);
|
||||
continue;
|
||||
}
|
||||
if (quad.top() == quad.bottom() || quad.left() == quad.right()) { // quad has no size
|
||||
ret.append(quad);
|
||||
continue;
|
||||
}
|
||||
ret.append(quad.makeSubQuad(quad.left(), quad.top(), quad.right(), y));
|
||||
ret.append(quad.makeSubQuad(quad.left(), y, quad.right(), quad.bottom()));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
WindowQuadList WindowQuadList::makeGrid(int maxQuadSize) const
|
||||
{
|
||||
if (empty()) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Find the bounding rectangle
|
||||
double left = first().left();
|
||||
double right = first().right();
|
||||
double top = first().top();
|
||||
double bottom = first().bottom();
|
||||
|
||||
for (const WindowQuad &quad : std::as_const(*this)) {
|
||||
left = std::min(left, quad.left());
|
||||
right = std::max(right, quad.right());
|
||||
top = std::min(top, quad.top());
|
||||
bottom = std::max(bottom, quad.bottom());
|
||||
}
|
||||
|
||||
WindowQuadList ret;
|
||||
|
||||
for (const WindowQuad &quad : std::as_const(*this)) {
|
||||
const double quadLeft = quad.left();
|
||||
const double quadRight = quad.right();
|
||||
const double quadTop = quad.top();
|
||||
const double quadBottom = quad.bottom();
|
||||
|
||||
// sanity check, see BUG 390953
|
||||
if (quadLeft == quadRight || quadTop == quadBottom) {
|
||||
ret.append(quad);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Compute the top-left corner of the first intersecting grid cell
|
||||
const double xBegin = left + qFloor((quadLeft - left) / maxQuadSize) * maxQuadSize;
|
||||
const double yBegin = top + qFloor((quadTop - top) / maxQuadSize) * maxQuadSize;
|
||||
|
||||
// Loop over all intersecting cells and add sub-quads
|
||||
for (double y = yBegin; y < quadBottom; y += maxQuadSize) {
|
||||
const double y0 = std::max(y, quadTop);
|
||||
const double y1 = std::min(quadBottom, y + maxQuadSize);
|
||||
|
||||
for (double x = xBegin; x < quadRight; x += maxQuadSize) {
|
||||
const double x0 = std::max(x, quadLeft);
|
||||
const double x1 = std::min(quadRight, x + maxQuadSize);
|
||||
|
||||
ret.append(quad.makeSubQuad(x0, y0, x1, y1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
WindowQuadList WindowQuadList::makeRegularGrid(int xSubdivisions, int ySubdivisions) const
|
||||
{
|
||||
if (empty()) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Find the bounding rectangle
|
||||
double left = first().left();
|
||||
double right = first().right();
|
||||
double top = first().top();
|
||||
double bottom = first().bottom();
|
||||
|
||||
for (const WindowQuad &quad : *this) {
|
||||
left = std::min(left, quad.left());
|
||||
right = std::max(right, quad.right());
|
||||
top = std::min(top, quad.top());
|
||||
bottom = std::max(bottom, quad.bottom());
|
||||
}
|
||||
|
||||
double xIncrement = (right - left) / xSubdivisions;
|
||||
double yIncrement = (bottom - top) / ySubdivisions;
|
||||
|
||||
WindowQuadList ret;
|
||||
|
||||
for (const WindowQuad &quad : *this) {
|
||||
const double quadLeft = quad.left();
|
||||
const double quadRight = quad.right();
|
||||
const double quadTop = quad.top();
|
||||
const double quadBottom = quad.bottom();
|
||||
|
||||
// sanity check, see BUG 390953
|
||||
if (quadLeft == quadRight || quadTop == quadBottom) {
|
||||
ret.append(quad);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Compute the top-left corner of the first intersecting grid cell
|
||||
const double xBegin = left + qFloor((quadLeft - left) / xIncrement) * xIncrement;
|
||||
const double yBegin = top + qFloor((quadTop - top) / yIncrement) * yIncrement;
|
||||
|
||||
// Loop over all intersecting cells and add sub-quads
|
||||
for (double y = yBegin; y < quadBottom; y += yIncrement) {
|
||||
const double y0 = std::max(y, quadTop);
|
||||
const double y1 = std::min(quadBottom, y + yIncrement);
|
||||
|
||||
for (double x = xBegin; x < quadRight; x += xIncrement) {
|
||||
const double x0 = std::max(x, quadLeft);
|
||||
const double x1 = std::min(quadRight, x + xIncrement);
|
||||
|
||||
ret.append(quad.makeSubQuad(x0, y0, x1, y1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void RenderGeometry::copy(std::span<GLVertex2D> destination)
|
||||
{
|
||||
Q_ASSERT(int(destination.size()) >= size());
|
||||
std::copy(cbegin(), cend(), destination.begin());
|
||||
}
|
||||
|
||||
void RenderGeometry::appendWindowVertex(const WindowVertex &windowVertex, qreal deviceScale)
|
||||
{
|
||||
GLVertex2D glVertex;
|
||||
switch (m_vertexSnappingMode) {
|
||||
case VertexSnappingMode::None:
|
||||
glVertex.position = QVector2D(windowVertex.x(), windowVertex.y()) * deviceScale;
|
||||
break;
|
||||
case VertexSnappingMode::Round:
|
||||
glVertex.position = roundVector(QVector2D(windowVertex.x(), windowVertex.y()) * deviceScale);
|
||||
break;
|
||||
}
|
||||
glVertex.texcoord = QVector2D(windowVertex.u(), windowVertex.v());
|
||||
append(glVertex);
|
||||
}
|
||||
|
||||
void RenderGeometry::appendWindowQuad(const WindowQuad &quad, qreal deviceScale)
|
||||
{
|
||||
// Geometry assumes we're rendering triangles, so add the quad's
|
||||
// vertices as two triangles. Vertex order is top-left, bottom-left,
|
||||
// top-right followed by top-right, bottom-left, bottom-right.
|
||||
appendWindowVertex(quad[0], deviceScale);
|
||||
appendWindowVertex(quad[3], deviceScale);
|
||||
appendWindowVertex(quad[1], deviceScale);
|
||||
|
||||
appendWindowVertex(quad[1], deviceScale);
|
||||
appendWindowVertex(quad[3], deviceScale);
|
||||
appendWindowVertex(quad[2], deviceScale);
|
||||
}
|
||||
|
||||
void RenderGeometry::appendSubQuad(const WindowQuad &quad, const QRectF &subquad, qreal deviceScale)
|
||||
{
|
||||
std::array<GLVertex2D, 4> vertices;
|
||||
vertices[0].position = QVector2D(subquad.topLeft());
|
||||
vertices[1].position = QVector2D(subquad.topRight());
|
||||
vertices[2].position = QVector2D(subquad.bottomRight());
|
||||
vertices[3].position = QVector2D(subquad.bottomLeft());
|
||||
|
||||
const auto deviceQuad = QRectF{QPointF(std::round(quad.left() * deviceScale), std::round(quad.top() * deviceScale)),
|
||||
QPointF(std::round(quad.right() * deviceScale), std::round(quad.bottom() * deviceScale))};
|
||||
|
||||
const QPointF origin = deviceQuad.topLeft();
|
||||
const QSizeF size = deviceQuad.size();
|
||||
|
||||
#pragma GCC unroll 4
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
const double weight1 = (vertices[i].position.x() - origin.x()) / size.width();
|
||||
const double weight2 = (vertices[i].position.y() - origin.y()) / size.height();
|
||||
const double oneMinW1 = 1.0 - weight1;
|
||||
const double oneMinW2 = 1.0 - weight2;
|
||||
|
||||
const float u = oneMinW1 * oneMinW2 * quad[0].u() + weight1 * oneMinW2 * quad[1].u()
|
||||
+ weight1 * weight2 * quad[2].u() + oneMinW1 * weight2 * quad[3].u();
|
||||
const float v = oneMinW1 * oneMinW2 * quad[0].v() + weight1 * oneMinW2 * quad[1].v()
|
||||
+ weight1 * weight2 * quad[2].v() + oneMinW1 * weight2 * quad[3].v();
|
||||
vertices[i].texcoord = QVector2D(u, v);
|
||||
}
|
||||
|
||||
append(vertices[0]);
|
||||
append(vertices[3]);
|
||||
append(vertices[1]);
|
||||
|
||||
append(vertices[1]);
|
||||
append(vertices[3]);
|
||||
append(vertices[2]);
|
||||
}
|
||||
|
||||
void RenderGeometry::postProcessTextureCoordinates(const QMatrix4x4 &textureMatrix)
|
||||
{
|
||||
if (!textureMatrix.isIdentity()) {
|
||||
const QVector2D coeff(textureMatrix(0, 0), textureMatrix(1, 1));
|
||||
const QVector2D offset(textureMatrix(0, 3), textureMatrix(1, 3));
|
||||
|
||||
for (auto &vertex : (*this)) {
|
||||
vertex.texcoord = vertex.texcoord * coeff + offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace KWin
|
285
src/scene/itemgeometry.h
Normal file
285
src/scene/itemgeometry.h
Normal file
|
@ -0,0 +1,285 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2006 Lubos Lunak <l.lunak@kde.org>
|
||||
SPDX-FileCopyrightText: 2022 Arjen Hiemstra <ahiemstra@heimr.nl>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "opengl/glvertexbuffer.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
/**
|
||||
* @short Vertex class
|
||||
*
|
||||
* A vertex is one position in a window. WindowQuad consists of four WindowVertex objects
|
||||
* and represents one part of a window.
|
||||
*/
|
||||
class KWIN_EXPORT WindowVertex
|
||||
{
|
||||
public:
|
||||
WindowVertex();
|
||||
WindowVertex(const QPointF &position, const QPointF &textureCoordinate);
|
||||
WindowVertex(double x, double y, double tx, double ty);
|
||||
|
||||
double x() const
|
||||
{
|
||||
return px;
|
||||
}
|
||||
double y() const
|
||||
{
|
||||
return py;
|
||||
}
|
||||
double u() const
|
||||
{
|
||||
return tx;
|
||||
}
|
||||
double v() const
|
||||
{
|
||||
return ty;
|
||||
}
|
||||
void move(double x, double y);
|
||||
void setX(double x);
|
||||
void setY(double y);
|
||||
|
||||
private:
|
||||
friend class WindowQuad;
|
||||
friend class WindowQuadList;
|
||||
double px, py; // position
|
||||
double tx, ty; // texture coords
|
||||
};
|
||||
|
||||
/**
|
||||
* @short Class representing one area of a window.
|
||||
*
|
||||
* WindowQuads consists of four WindowVertex objects and represents one part of a window.
|
||||
*/
|
||||
// NOTE: This class expects the (original) vertices to be in the clockwise order starting from topleft.
|
||||
class KWIN_EXPORT WindowQuad
|
||||
{
|
||||
public:
|
||||
WindowQuad();
|
||||
WindowQuad makeSubQuad(double x1, double y1, double x2, double y2) const;
|
||||
WindowVertex &operator[](int index);
|
||||
const WindowVertex &operator[](int index) const;
|
||||
double left() const;
|
||||
double right() const;
|
||||
double top() const;
|
||||
double bottom() const;
|
||||
QRectF bounds() const;
|
||||
|
||||
private:
|
||||
friend class WindowQuadList;
|
||||
WindowVertex verts[4];
|
||||
};
|
||||
|
||||
class KWIN_EXPORT WindowQuadList
|
||||
: public QList<WindowQuad>
|
||||
{
|
||||
public:
|
||||
WindowQuadList splitAtX(double x) const;
|
||||
WindowQuadList splitAtY(double y) const;
|
||||
WindowQuadList makeGrid(int maxquadsize) const;
|
||||
WindowQuadList makeRegularGrid(int xSubdivisions, int ySubdivisions) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* A helper class for render geometry in device coordinates.
|
||||
*
|
||||
* This mostly represents a vector of vertices, with some convenience methods
|
||||
* for easily converting from WindowQuad and related classes to lists of
|
||||
* GLVertex2D. This class assumes rendering happens as unindexed triangles.
|
||||
*/
|
||||
class KWIN_EXPORT RenderGeometry : public QList<GLVertex2D>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* In what way should vertices snap to integer device coordinates?
|
||||
*
|
||||
* Vertices are converted to device coordinates before being sent to the
|
||||
* rendering system. Depending on scaling factors, this may lead to device
|
||||
* coordinates with fractional parts. For some cases, this may not be ideal
|
||||
* as fractional coordinates need to be interpolated and can lead to
|
||||
* "blurry" rendering. To avoid that, we can snap the vertices to integer
|
||||
* device coordinates when they are added.
|
||||
*/
|
||||
enum class VertexSnappingMode {
|
||||
None, //< No rounding, device coordinates containing fractional parts
|
||||
// are passed directly to the rendering system.
|
||||
Round, //< Perform a simple rounding, device coordinates will not have
|
||||
// any fractional parts.
|
||||
};
|
||||
|
||||
/**
|
||||
* The vertex snapping mode to use for this geometry.
|
||||
*
|
||||
* By default, this is VertexSnappingMode::Round.
|
||||
*/
|
||||
inline VertexSnappingMode vertexSnappingMode() const
|
||||
{
|
||||
return m_vertexSnappingMode;
|
||||
}
|
||||
/**
|
||||
* Set the vertex snapping mode to use for this geometry.
|
||||
*
|
||||
* Note that this doesn't change vertices retroactively, so you should set
|
||||
* this before adding any vertices, or clear and rebuild the geometry after
|
||||
* setting it.
|
||||
*
|
||||
* @param mode The new rounding mode.
|
||||
*/
|
||||
void setVertexSnappingMode(VertexSnappingMode mode)
|
||||
{
|
||||
m_vertexSnappingMode = mode;
|
||||
}
|
||||
/**
|
||||
* Copy geometry data into another buffer.
|
||||
*
|
||||
* This is primarily intended for copying into a vertex buffer for rendering.
|
||||
*
|
||||
* @param destination The destination buffer. This needs to be at least large
|
||||
* enough to contain all elements.
|
||||
*/
|
||||
void copy(std::span<GLVertex2D> destination);
|
||||
/**
|
||||
* Append a WindowVertex as a geometry vertex.
|
||||
*
|
||||
* WindowVertex is assumed to be in logical coordinates. It will be converted
|
||||
* to device coordinates using the specified device scale and then rounded
|
||||
* so it fits correctly on the device pixel grid.
|
||||
*
|
||||
* @param windowVertex The WindowVertex instance to append.
|
||||
* @param deviceScale The scaling factor to use to go from logical to device
|
||||
* coordinates.
|
||||
*/
|
||||
void appendWindowVertex(const WindowVertex &windowVertex, qreal deviceScale);
|
||||
/**
|
||||
* Append a WindowQuad as two triangles.
|
||||
*
|
||||
* This will append the corners of the specified WindowQuad in the right
|
||||
* order so they make two triangles that can be rendered by OpenGL. The
|
||||
* corners are converted to device coordinates and rounded, just like
|
||||
* `appendWindowVertex()` does.
|
||||
*
|
||||
* @param quad The WindowQuad instance to append.
|
||||
* @param deviceScale The scaling factor to use to go from logical to device
|
||||
* coordinates.
|
||||
*/
|
||||
void appendWindowQuad(const WindowQuad &quad, qreal deviceScale);
|
||||
/**
|
||||
* Append a sub-quad of a WindowQuad as two triangles.
|
||||
*
|
||||
* This will append the sub-quad specified by `intersection` as two
|
||||
* triangles. The quad is expected to be in logical coordinates, while the
|
||||
* intersection is expected to be in device coordinates. The texture
|
||||
* coordinates of the resulting vertices are based upon those of the quad,
|
||||
* using bilinear interpolation for interpolating how much of the original
|
||||
* texture coordinates to use.
|
||||
*
|
||||
* @param quad The WindowQuad instance to use a sub-quad of.
|
||||
* @param subquad The sub-quad to append.
|
||||
* @param deviceScale The scaling factor used to convert from logical to
|
||||
* device coordinates.
|
||||
*/
|
||||
void appendSubQuad(const WindowQuad &quad, const QRectF &subquad, qreal deviceScale);
|
||||
/**
|
||||
* Modify this geometry's texture coordinates based on a matrix.
|
||||
*
|
||||
* This is primarily intended to convert from non-normalised to normalised
|
||||
* texture coordinates.
|
||||
*
|
||||
* @param textureMatrix The texture matrix to use for modifying the
|
||||
* texture coordinates. Note that only the 2D scale and
|
||||
* translation are used.
|
||||
*/
|
||||
void postProcessTextureCoordinates(const QMatrix4x4 &textureMatrix);
|
||||
|
||||
private:
|
||||
VertexSnappingMode m_vertexSnappingMode = VertexSnappingMode::Round;
|
||||
};
|
||||
|
||||
inline WindowVertex::WindowVertex()
|
||||
: px(0)
|
||||
, py(0)
|
||||
, tx(0)
|
||||
, ty(0)
|
||||
{
|
||||
}
|
||||
|
||||
inline WindowVertex::WindowVertex(double _x, double _y, double _tx, double _ty)
|
||||
: px(_x)
|
||||
, py(_y)
|
||||
, tx(_tx)
|
||||
, ty(_ty)
|
||||
{
|
||||
}
|
||||
|
||||
inline WindowVertex::WindowVertex(const QPointF &position, const QPointF &texturePosition)
|
||||
: px(position.x())
|
||||
, py(position.y())
|
||||
, tx(texturePosition.x())
|
||||
, ty(texturePosition.y())
|
||||
{
|
||||
}
|
||||
|
||||
inline void WindowVertex::move(double x, double y)
|
||||
{
|
||||
px = x;
|
||||
py = y;
|
||||
}
|
||||
|
||||
inline void WindowVertex::setX(double x)
|
||||
{
|
||||
px = x;
|
||||
}
|
||||
|
||||
inline void WindowVertex::setY(double y)
|
||||
{
|
||||
py = y;
|
||||
}
|
||||
|
||||
inline WindowQuad::WindowQuad()
|
||||
{
|
||||
}
|
||||
|
||||
inline WindowVertex &WindowQuad::operator[](int index)
|
||||
{
|
||||
Q_ASSERT(index >= 0 && index < 4);
|
||||
return verts[index];
|
||||
}
|
||||
|
||||
inline const WindowVertex &WindowQuad::operator[](int index) const
|
||||
{
|
||||
Q_ASSERT(index >= 0 && index < 4);
|
||||
return verts[index];
|
||||
}
|
||||
|
||||
inline double WindowQuad::left() const
|
||||
{
|
||||
return std::min(verts[0].px, std::min(verts[1].px, std::min(verts[2].px, verts[3].px)));
|
||||
}
|
||||
|
||||
inline double WindowQuad::right() const
|
||||
{
|
||||
return std::max(verts[0].px, std::max(verts[1].px, std::max(verts[2].px, verts[3].px)));
|
||||
}
|
||||
|
||||
inline double WindowQuad::top() const
|
||||
{
|
||||
return std::min(verts[0].py, std::min(verts[1].py, std::min(verts[2].py, verts[3].py)));
|
||||
}
|
||||
|
||||
inline double WindowQuad::bottom() const
|
||||
{
|
||||
return std::max(verts[0].py, std::max(verts[1].py, std::max(verts[2].py, verts[3].py)));
|
||||
}
|
||||
|
||||
inline QRectF WindowQuad::bounds() const
|
||||
{
|
||||
return QRectF(QPointF(left(), top()), QPointF(right(), bottom()));
|
||||
}
|
||||
|
||||
} // namespace KWin
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "scene/itemrenderer_qpainter.h"
|
||||
#include "core/renderviewport.h"
|
||||
#include "effect/effect.h"
|
||||
#include "platformsupport/scenes/qpainter/qpaintersurfacetexture.h"
|
||||
#include "scene/imageitem.h"
|
||||
#include "scene/workspacescene_qpainter.h"
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
#include "scene/windowitem.h"
|
||||
#include "effect/effects.h"
|
||||
#include "internalwindow.h"
|
||||
#include "scene/decorationitem.h"
|
||||
#include "scene/shadowitem.h"
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "workspace_wrapper.h"
|
||||
|
||||
#include "core/output.h"
|
||||
#include "effect/effects.h"
|
||||
#include "input.h"
|
||||
#include "screenedge.h"
|
||||
#include "workspace.h"
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
class KConfigLoader;
|
||||
class KPluginMetaData;
|
||||
|
||||
class QAction;
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "core/renderbackend.h"
|
||||
#include "core/rendertarget.h"
|
||||
#include "core/renderviewport.h"
|
||||
#include "effect/effect.h"
|
||||
#include "scene/itemrenderer.h"
|
||||
#include "scene/windowitem.h"
|
||||
#include "scene/workspacescene.h"
|
||||
|
|
Loading…
Reference in a new issue