File indexing completed on 2024-05-19 05:32:19
0001 /* 0002 SPDX-FileCopyrightText: 2006 Lubos Lunak <l.lunak@kde.org> 0003 SPDX-FileCopyrightText: 2022 Arjen Hiemstra <ahiemstra@heimr.nl> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #pragma once 0009 0010 #include "opengl/glvertexbuffer.h" 0011 0012 namespace KWin 0013 { 0014 0015 /** 0016 * @short Vertex class 0017 * 0018 * A vertex is one position in a window. WindowQuad consists of four WindowVertex objects 0019 * and represents one part of a window. 0020 */ 0021 class KWIN_EXPORT WindowVertex 0022 { 0023 public: 0024 WindowVertex(); 0025 WindowVertex(const QPointF &position, const QPointF &textureCoordinate); 0026 WindowVertex(double x, double y, double tx, double ty); 0027 0028 double x() const 0029 { 0030 return px; 0031 } 0032 double y() const 0033 { 0034 return py; 0035 } 0036 double u() const 0037 { 0038 return tx; 0039 } 0040 double v() const 0041 { 0042 return ty; 0043 } 0044 void move(double x, double y); 0045 void setX(double x); 0046 void setY(double y); 0047 0048 private: 0049 friend class WindowQuad; 0050 friend class WindowQuadList; 0051 double px, py; // position 0052 double tx, ty; // texture coords 0053 }; 0054 0055 /** 0056 * @short Class representing one area of a window. 0057 * 0058 * WindowQuads consists of four WindowVertex objects and represents one part of a window. 0059 */ 0060 // NOTE: This class expects the (original) vertices to be in the clockwise order starting from topleft. 0061 class KWIN_EXPORT WindowQuad 0062 { 0063 public: 0064 WindowQuad(); 0065 WindowQuad makeSubQuad(double x1, double y1, double x2, double y2) const; 0066 WindowVertex &operator[](int index); 0067 const WindowVertex &operator[](int index) const; 0068 double left() const; 0069 double right() const; 0070 double top() const; 0071 double bottom() const; 0072 QRectF bounds() const; 0073 0074 private: 0075 friend class WindowQuadList; 0076 WindowVertex verts[4]; 0077 }; 0078 0079 class KWIN_EXPORT WindowQuadList 0080 : public QList<WindowQuad> 0081 { 0082 public: 0083 WindowQuadList splitAtX(double x) const; 0084 WindowQuadList splitAtY(double y) const; 0085 WindowQuadList makeGrid(int maxquadsize) const; 0086 WindowQuadList makeRegularGrid(int xSubdivisions, int ySubdivisions) const; 0087 }; 0088 0089 /** 0090 * A helper class for render geometry in device coordinates. 0091 * 0092 * This mostly represents a vector of vertices, with some convenience methods 0093 * for easily converting from WindowQuad and related classes to lists of 0094 * GLVertex2D. This class assumes rendering happens as unindexed triangles. 0095 */ 0096 class KWIN_EXPORT RenderGeometry : public QList<GLVertex2D> 0097 { 0098 public: 0099 /** 0100 * In what way should vertices snap to integer device coordinates? 0101 * 0102 * Vertices are converted to device coordinates before being sent to the 0103 * rendering system. Depending on scaling factors, this may lead to device 0104 * coordinates with fractional parts. For some cases, this may not be ideal 0105 * as fractional coordinates need to be interpolated and can lead to 0106 * "blurry" rendering. To avoid that, we can snap the vertices to integer 0107 * device coordinates when they are added. 0108 */ 0109 enum class VertexSnappingMode { 0110 None, //< No rounding, device coordinates containing fractional parts 0111 // are passed directly to the rendering system. 0112 Round, //< Perform a simple rounding, device coordinates will not have 0113 // any fractional parts. 0114 }; 0115 0116 /** 0117 * The vertex snapping mode to use for this geometry. 0118 * 0119 * By default, this is VertexSnappingMode::Round. 0120 */ 0121 inline VertexSnappingMode vertexSnappingMode() const 0122 { 0123 return m_vertexSnappingMode; 0124 } 0125 /** 0126 * Set the vertex snapping mode to use for this geometry. 0127 * 0128 * Note that this doesn't change vertices retroactively, so you should set 0129 * this before adding any vertices, or clear and rebuild the geometry after 0130 * setting it. 0131 * 0132 * @param mode The new rounding mode. 0133 */ 0134 void setVertexSnappingMode(VertexSnappingMode mode) 0135 { 0136 m_vertexSnappingMode = mode; 0137 } 0138 /** 0139 * Copy geometry data into another buffer. 0140 * 0141 * This is primarily intended for copying into a vertex buffer for rendering. 0142 * 0143 * @param destination The destination buffer. This needs to be at least large 0144 * enough to contain all elements. 0145 */ 0146 void copy(std::span<GLVertex2D> destination); 0147 /** 0148 * Append a WindowVertex as a geometry vertex. 0149 * 0150 * WindowVertex is assumed to be in logical coordinates. It will be converted 0151 * to device coordinates using the specified device scale and then rounded 0152 * so it fits correctly on the device pixel grid. 0153 * 0154 * @param windowVertex The WindowVertex instance to append. 0155 * @param deviceScale The scaling factor to use to go from logical to device 0156 * coordinates. 0157 */ 0158 void appendWindowVertex(const WindowVertex &windowVertex, qreal deviceScale); 0159 /** 0160 * Append a WindowQuad as two triangles. 0161 * 0162 * This will append the corners of the specified WindowQuad in the right 0163 * order so they make two triangles that can be rendered by OpenGL. The 0164 * corners are converted to device coordinates and rounded, just like 0165 * `appendWindowVertex()` does. 0166 * 0167 * @param quad The WindowQuad instance to append. 0168 * @param deviceScale The scaling factor to use to go from logical to device 0169 * coordinates. 0170 */ 0171 void appendWindowQuad(const WindowQuad &quad, qreal deviceScale); 0172 /** 0173 * Append a sub-quad of a WindowQuad as two triangles. 0174 * 0175 * This will append the sub-quad specified by `intersection` as two 0176 * triangles. The quad is expected to be in logical coordinates, while the 0177 * intersection is expected to be in device coordinates. The texture 0178 * coordinates of the resulting vertices are based upon those of the quad, 0179 * using bilinear interpolation for interpolating how much of the original 0180 * texture coordinates to use. 0181 * 0182 * @param quad The WindowQuad instance to use a sub-quad of. 0183 * @param subquad The sub-quad to append. 0184 * @param deviceScale The scaling factor used to convert from logical to 0185 * device coordinates. 0186 */ 0187 void appendSubQuad(const WindowQuad &quad, const QRectF &subquad, qreal deviceScale); 0188 /** 0189 * Modify this geometry's texture coordinates based on a matrix. 0190 * 0191 * This is primarily intended to convert from non-normalised to normalised 0192 * texture coordinates. 0193 * 0194 * @param textureMatrix The texture matrix to use for modifying the 0195 * texture coordinates. Note that only the 2D scale and 0196 * translation are used. 0197 */ 0198 void postProcessTextureCoordinates(const QMatrix4x4 &textureMatrix); 0199 0200 private: 0201 VertexSnappingMode m_vertexSnappingMode = VertexSnappingMode::Round; 0202 }; 0203 0204 inline WindowVertex::WindowVertex() 0205 : px(0) 0206 , py(0) 0207 , tx(0) 0208 , ty(0) 0209 { 0210 } 0211 0212 inline WindowVertex::WindowVertex(double _x, double _y, double _tx, double _ty) 0213 : px(_x) 0214 , py(_y) 0215 , tx(_tx) 0216 , ty(_ty) 0217 { 0218 } 0219 0220 inline WindowVertex::WindowVertex(const QPointF &position, const QPointF &texturePosition) 0221 : px(position.x()) 0222 , py(position.y()) 0223 , tx(texturePosition.x()) 0224 , ty(texturePosition.y()) 0225 { 0226 } 0227 0228 inline void WindowVertex::move(double x, double y) 0229 { 0230 px = x; 0231 py = y; 0232 } 0233 0234 inline void WindowVertex::setX(double x) 0235 { 0236 px = x; 0237 } 0238 0239 inline void WindowVertex::setY(double y) 0240 { 0241 py = y; 0242 } 0243 0244 inline WindowQuad::WindowQuad() 0245 { 0246 } 0247 0248 inline WindowVertex &WindowQuad::operator[](int index) 0249 { 0250 Q_ASSERT(index >= 0 && index < 4); 0251 return verts[index]; 0252 } 0253 0254 inline const WindowVertex &WindowQuad::operator[](int index) const 0255 { 0256 Q_ASSERT(index >= 0 && index < 4); 0257 return verts[index]; 0258 } 0259 0260 inline double WindowQuad::left() const 0261 { 0262 return std::min(verts[0].px, std::min(verts[1].px, std::min(verts[2].px, verts[3].px))); 0263 } 0264 0265 inline double WindowQuad::right() const 0266 { 0267 return std::max(verts[0].px, std::max(verts[1].px, std::max(verts[2].px, verts[3].px))); 0268 } 0269 0270 inline double WindowQuad::top() const 0271 { 0272 return std::min(verts[0].py, std::min(verts[1].py, std::min(verts[2].py, verts[3].py))); 0273 } 0274 0275 inline double WindowQuad::bottom() const 0276 { 0277 return std::max(verts[0].py, std::max(verts[1].py, std::max(verts[2].py, verts[3].py))); 0278 } 0279 0280 inline QRectF WindowQuad::bounds() const 0281 { 0282 return QRectF(QPointF(left(), top()), QPointF(right(), bottom())); 0283 } 0284 0285 } // namespace KWin