1 | /******************************************************************** |
2 | KWin - the KDE window manager |
3 | This file is part of the KDE project. |
4 | |
5 | Copyright (C) 2006-2007 Rivo Laks <rivolaks@hot.ee> |
6 | Copyright (C) 2010, 2011 Martin Gräßlin <mgraesslin@kde.org> |
7 | |
8 | This program is free software; you can redistribute it and/or modify |
9 | it under the terms of the GNU General Public License as published by |
10 | the Free Software Foundation; either version 2 of the License, or |
11 | (at your option) any later version. |
12 | |
13 | This program is distributed in the hope that it will be useful, |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | GNU General Public License for more details. |
17 | |
18 | You should have received a copy of the GNU General Public License |
19 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
20 | *********************************************************************/ |
21 | |
22 | #ifndef KWIN_GLUTILS_H |
23 | #define KWIN_GLUTILS_H |
24 | |
25 | // kwin |
26 | #include "kwinglutils_funcs.h" |
27 | #include "kwingltexture.h" |
28 | |
29 | // Qt |
30 | #include <QSize> |
31 | #include <QStack> |
32 | |
33 | /** @addtogroup kwineffects */ |
34 | /** @{ */ |
35 | |
36 | class QVector2D; |
37 | class QVector3D; |
38 | class QVector4D; |
39 | class QMatrix4x4; |
40 | |
41 | template< class K, class V > class QHash; |
42 | |
43 | |
44 | namespace KWin |
45 | { |
46 | |
47 | class GLVertexBuffer; |
48 | class GLVertexBufferPrivate; |
49 | |
50 | |
51 | // Initializes GLX function pointers |
52 | void KWIN_EXPORT initGLX(); |
53 | // Initializes OpenGL stuff. This includes resolving function pointers as |
54 | // well as checking for GL version and extensions |
55 | // Note that GL context has to be created by the time this function is called |
56 | void KWIN_EXPORT initGL(OpenGLPlatformInterface platformInterface); |
57 | // Initializes EGL function pointers |
58 | void KWIN_EXPORT initEGL(); |
59 | // Cleans up all resources hold by the GL Context |
60 | void KWIN_EXPORT cleanupGL(); |
61 | |
62 | // Number of supported texture units |
63 | extern KWIN_EXPORT int glTextureUnitsCount; |
64 | |
65 | |
66 | bool KWIN_EXPORT hasGLVersion(int major, int minor, int release = 0); |
67 | bool KWIN_EXPORT hasGLXVersion(int major, int minor, int release = 0); |
68 | bool KWIN_EXPORT hasEGLVersion(int major, int minor, int release = 0); |
69 | // use for both OpenGL and GLX extensions |
70 | bool KWIN_EXPORT hasGLExtension(const QString& extension); |
71 | |
72 | // detect OpenGL error (add to various places in code to pinpoint the place) |
73 | bool KWIN_EXPORT checkGLError(const char* txt); |
74 | |
75 | inline bool KWIN_EXPORT isPowerOfTwo(int x) |
76 | { |
77 | return ((x & (x - 1)) == 0); |
78 | } |
79 | /** |
80 | * @return power of two integer _greater or equal to_ x. |
81 | * E.g. nearestPowerOfTwo(513) = nearestPowerOfTwo(800) = 1024 |
82 | **/ |
83 | int KWIN_EXPORT nearestPowerOfTwo(int x); |
84 | |
85 | /** |
86 | * Push a new matrix on the GL matrix stack. |
87 | * In GLES this method is a noop. This method should be preferred over glPushMatrix |
88 | * as it also handles GLES. |
89 | * @since 4.7 |
90 | **/ |
91 | KWIN_EXPORT void pushMatrix(); |
92 | /** |
93 | * Multiplies current matrix on GL stack with @p matrix and pushes the result on the matrix stack. |
94 | * This method is the same as pushMatrix followed by multiplyMatrix. |
95 | * In GLES this method is a noop. This method should be preferred over glPushMatrix |
96 | * as it also handles GLES. |
97 | * @param matrix The matrix the current matrix on the stack should be multiplied with. |
98 | * @see pushMatrix |
99 | * @see multiplyMatrix |
100 | * @since 4.7 |
101 | **/ |
102 | KWIN_EXPORT void pushMatrix(const QMatrix4x4 &matrix); |
103 | /** |
104 | * Multiplies the current matrix on GL stack with @p matrix. |
105 | * In GLES this method is a noop. This method should be preferred over glMultMatrix |
106 | * as it also handles GLES. |
107 | * @param matrix The matrix the current matrix on the stack should be multiplied with. |
108 | * @since 4.7 |
109 | **/ |
110 | KWIN_EXPORT void multiplyMatrix(const QMatrix4x4 &matrix); |
111 | /** |
112 | * Replaces the current matrix on GL stack with @p matrix. |
113 | * In GLES this method is a no-op. This method should be preferred over glLoadMatrix |
114 | * as it also handles GLES. |
115 | * @param matrix The new matrix to replace the existing one on the GL stack. |
116 | * @since 4.7 |
117 | **/ |
118 | KWIN_EXPORT void loadMatrix(const QMatrix4x4 &matrix); |
119 | /** |
120 | * Pops the current matrix from the GL matrix stack. |
121 | * In GLES this method is a noop. This method should be preferred over glPopMatrix |
122 | * as it also handles GLES. |
123 | * @since 4.7 |
124 | **/ |
125 | KWIN_EXPORT void popMatrix(); |
126 | |
127 | class KWIN_EXPORT GLShader |
128 | { |
129 | public: |
130 | enum Flags { |
131 | NoFlags = 0, |
132 | ExplicitLinking = (1 << 0) |
133 | }; |
134 | |
135 | GLShader(const QString &vertexfile, const QString &fragmentfile, unsigned int flags = NoFlags); |
136 | ~GLShader(); |
137 | |
138 | bool isValid() const { |
139 | return mValid; |
140 | } |
141 | |
142 | void bindAttributeLocation(const char *name, int index); |
143 | void bindFragDataLocation(const char *name, int index); |
144 | |
145 | bool link(); |
146 | |
147 | int uniformLocation(const char* name); |
148 | |
149 | bool setUniform(const char* name, float value); |
150 | bool setUniform(const char* name, int value); |
151 | bool setUniform(const char* name, const QVector2D& value); |
152 | bool setUniform(const char* name, const QVector3D& value); |
153 | bool setUniform(const char* name, const QVector4D& value); |
154 | bool setUniform(const char* name, const QMatrix4x4& value); |
155 | bool setUniform(const char* name, const QColor& color); |
156 | |
157 | bool setUniform(int location, float value); |
158 | bool setUniform(int location, int value); |
159 | bool setUniform(int location, const QVector2D &value); |
160 | bool setUniform(int location, const QVector3D &value); |
161 | bool setUniform(int location, const QVector4D &value); |
162 | bool setUniform(int location, const QMatrix4x4 &value); |
163 | bool setUniform(int location, const QColor &value); |
164 | |
165 | int attributeLocation(const char* name); |
166 | bool setAttribute(const char* name, float value); |
167 | /** |
168 | * @return The value of the uniform as a matrix |
169 | * @since 4.7 |
170 | **/ |
171 | QMatrix4x4 getUniformMatrix4x4(const char* name); |
172 | |
173 | enum MatrixUniform { |
174 | TextureMatrix = 0, |
175 | ProjectionMatrix, |
176 | ModelViewMatrix, |
177 | WindowTransformation, |
178 | ScreenTransformation, |
179 | MatrixCount |
180 | }; |
181 | |
182 | enum Vec2Uniform { |
183 | Offset, |
184 | Vec2UniformCount |
185 | }; |
186 | |
187 | enum Vec4Uniform { |
188 | ModulationConstant, |
189 | Vec4UniformCount |
190 | }; |
191 | |
192 | enum FloatUniform { |
193 | Saturation, |
194 | FloatUniformCount |
195 | }; |
196 | |
197 | enum IntUniform { |
198 | AlphaToOne, ///< @deprecated no longer used |
199 | ColorCorrectionLookupTextureUnit, |
200 | IntUniformCount |
201 | }; |
202 | |
203 | enum ColorUniform { |
204 | Color, |
205 | ColorUniformCount |
206 | }; |
207 | |
208 | bool setUniform(MatrixUniform uniform, const QMatrix4x4 &matrix); |
209 | bool setUniform(Vec2Uniform uniform, const QVector2D &value); |
210 | bool setUniform(Vec4Uniform uniform, const QVector4D &value); |
211 | bool setUniform(FloatUniform uniform, float value); |
212 | bool setUniform(IntUniform uniform, int value); |
213 | bool setUniform(ColorUniform uniform, const QVector4D &value); |
214 | bool setUniform(ColorUniform uniform, const QColor &value); |
215 | |
216 | protected: |
217 | GLShader(unsigned int flags = NoFlags); |
218 | bool loadFromFiles(const QString& vertexfile, const QString& fragmentfile); |
219 | bool load(const QByteArray &vertexSource, const QByteArray &fragmentSource); |
220 | const QByteArray prepareSource(GLenum shaderType, const QByteArray &sourceCode) const; |
221 | bool compile(GLuint program, GLenum shaderType, const QByteArray &sourceCode) const; |
222 | void bind(); |
223 | void unbind(); |
224 | void resolveLocations(); |
225 | |
226 | private: |
227 | unsigned int mProgram; |
228 | bool mValid:1; |
229 | bool mLocationsResolved:1; |
230 | bool mExplicitLinking:1; |
231 | int mMatrixLocation[MatrixCount]; |
232 | int mVec2Location[Vec2UniformCount]; |
233 | int mVec4Location[Vec4UniformCount]; |
234 | int mFloatLocation[FloatUniformCount]; |
235 | int mIntLocation[IntUniformCount]; |
236 | int mColorLocation[ColorUniformCount]; |
237 | |
238 | static bool sColorCorrect; |
239 | |
240 | friend class ColorCorrection; |
241 | friend class ColorCorrectionPrivate; |
242 | friend class ShaderManager; |
243 | }; |
244 | |
245 | /** |
246 | * @short Manager for Shaders. |
247 | * |
248 | * This class provides some built-in shaders to be used by both compositing scene and effects. |
249 | * The ShaderManager provides methods to bind a built-in or a custom shader and keeps track of |
250 | * the shaders which have been bound. When a shader is unbound the previously bound shader |
251 | * will be rebound. |
252 | * |
253 | * @author Martin Gräßlin <mgraesslin@kde.org> |
254 | * @since 4.7 |
255 | **/ |
256 | class KWIN_EXPORT ShaderManager |
257 | { |
258 | public: |
259 | /** |
260 | * Identifiers for built-in shaders available for effects and scene |
261 | **/ |
262 | enum ShaderType { |
263 | /** |
264 | * An orthographic projection shader able to render textured geometries. |
265 | * Expects a @c vec2 uniform @c offset describing the offset from top-left corner |
266 | * and defaults to @c (0/0). Expects a @c vec2 uniform @c textureSize to calculate |
267 | * normalized texture coordinates. Defaults to @c (1.0/1.0). And expects a @c vec3 |
268 | * uniform @c colorManiuplation, with @c x being opacity, @c y being brightness and |
269 | * @c z being saturation. All three values default to @c 1.0. |
270 | * The sampler uniform is @c sample and defaults to @c 0. |
271 | * The shader uses two vertex attributes @c vertex and @c texCoord. |
272 | **/ |
273 | SimpleShader = 0, |
274 | /** |
275 | * A generic shader able to render transformed, textured geometries. |
276 | * This shader is mostly needed by the scene and not of much interest for effects. |
277 | * Effects can influence this shader through @link ScreenPaintData and @link WindowPaintData. |
278 | * The shader expects four @c mat4 uniforms @c projection, @c modelview, |
279 | * @c screenTransformation and @c windowTransformation. The fragment shader expect the |
280 | * same uniforms as the SimpleShader and the same vertex attributes are used. |
281 | **/ |
282 | GenericShader, |
283 | /** |
284 | * An orthographic shader to render simple colored geometries without texturing. |
285 | * Expects a @c vec2 uniform @c offset describing the offset from top-left corner |
286 | * and defaults to @c (0/0). The fragment shader expects a single @c vec4 uniform |
287 | * @c geometryColor, which defaults to fully opaque black. |
288 | * The Shader uses one vertex attribute @c vertex. |
289 | **/ |
290 | ColorShader |
291 | }; |
292 | |
293 | /** |
294 | * @return The currently bound shader or @c null if no shader is bound. |
295 | **/ |
296 | GLShader *getBoundShader() const; |
297 | |
298 | /** |
299 | * @return @c true if a shader is bound, @c false otherwise |
300 | **/ |
301 | bool isShaderBound() const; |
302 | /** |
303 | * Allows to query whether Shaders are supported by the compositor, that is |
304 | * whether the Shaders compiled successfully. |
305 | * |
306 | * With OpenGL 1 compositing this method will always return @c false. |
307 | * |
308 | * Do not use this method to check whether the compositor uses OpenGL 1 or 2, |
309 | * use @link EffectsHandler::compositingType instead. |
310 | * @return @c true if the built-in shaders are valid, @c false otherwise |
311 | **/ |
312 | bool isValid() const; |
313 | /** |
314 | * Is @c true if the environment variable KWIN_GL_DEBUG is set to 1. |
315 | * In that case shaders are compiled with KWIN_SHADER_DEBUG defined. |
316 | * @returns @c true if shaders are compiled with debug information |
317 | * @since 4.8 |
318 | **/ |
319 | bool isShaderDebug() const; |
320 | |
321 | /** |
322 | * Binds the shader of specified @p type. |
323 | * To unbind the shader use @link popShader. A previous bound shader will be rebound. |
324 | * @param type The built-in shader to bind |
325 | * @param reset Whether all uniforms should be reset to their default values |
326 | * @return The bound shader or @c NULL if shaders are not valid |
327 | * @see popShader |
328 | **/ |
329 | GLShader *pushShader(ShaderType type, bool reset = false); |
330 | /** |
331 | * Binds the @p shader. |
332 | * To unbind the shader use @link popShader. A previous bound shader will be rebound. |
333 | * To bind a built-in shader use the more specific method. |
334 | * @param shader The shader to be bound |
335 | * @see popShader |
336 | **/ |
337 | void pushShader(GLShader *shader); |
338 | |
339 | /** |
340 | * Unbinds the currently bound shader and rebinds a previous stored shader. |
341 | * If there is no previous shader, no shader will be rebound. |
342 | * It is not safe to call this method if there is no bound shader. |
343 | * @see pushShader |
344 | * @see getBoundShader |
345 | **/ |
346 | void popShader(); |
347 | |
348 | /** |
349 | * Resets all shaders to the default uniform values. |
350 | * Only built in shaders are changed. |
351 | * @since 4.8 |
352 | **/ |
353 | void resetAllShaders(); |
354 | |
355 | /** |
356 | * Resets ShaderType @p type uniforms of a custom shader |
357 | * @since 4.11.1 |
358 | */ |
359 | void resetShader(GLShader *shader, ShaderType type); |
360 | |
361 | /** |
362 | * Creates a GLShader with a built-in vertex shader and a custom fragment shader. |
363 | * @param vertex The generic vertex shader |
364 | * @param fragmentFile The path to the source code of the fragment shader |
365 | * @return The created shader |
366 | **/ |
367 | GLShader *loadFragmentShader(ShaderType vertex, const QString &fragmentFile); |
368 | /** |
369 | * Creates a GLShader with a built-in fragment shader and a custom vertex shader. |
370 | * @param fragment The generic fragment shader |
371 | * @param vertexFile The path to the source code of the vertex shader |
372 | * @return The created shader |
373 | **/ |
374 | GLShader *loadVertexShader(ShaderType fragment, const QString &vertexFile); |
375 | /** |
376 | * Creates a GLShader with the specified sources. |
377 | * The difference to GLShader is that it does not need to be loaded from files. |
378 | * @param vertexSource The source code of the vertex shader |
379 | * @param fragmentSource The source code of the fragment shader. |
380 | * @return The created shader |
381 | **/ |
382 | GLShader *loadShaderFromCode(const QByteArray &vertexSource, const QByteArray &fragmentSource); |
383 | |
384 | /** |
385 | * @return a pointer to the ShaderManager instance |
386 | **/ |
387 | static ShaderManager *instance(); |
388 | /** |
389 | * @brief Ensures that the ShaderManager is disabled. |
390 | * |
391 | * Used only by an OpenGL 1 Scene which does not use OpenGL 2 Shaders. |
392 | * |
393 | * @internal |
394 | * @since 4.10 |
395 | **/ |
396 | static void disable(); |
397 | |
398 | /** |
399 | * @internal |
400 | **/ |
401 | static void cleanup(); |
402 | |
403 | private: |
404 | ShaderManager(); |
405 | ~ShaderManager(); |
406 | |
407 | void initShaders(); |
408 | void resetShader(ShaderType type); |
409 | void bindFragDataLocations(GLShader *shader); |
410 | void bindAttributeLocations(GLShader *shader) const; |
411 | |
412 | QStack<GLShader*> m_boundShaders; |
413 | GLShader *m_shader[3]; |
414 | bool m_inited; |
415 | bool m_valid; |
416 | bool m_debug; |
417 | QByteArray m_shaderDir; |
418 | static ShaderManager *s_shaderManager; |
419 | }; |
420 | |
421 | /** |
422 | * An helper class to push a Shader on to ShaderManager's stack and ensuring that the Shader |
423 | * gets popped again from the stack automatically once the object goes out of life. |
424 | * |
425 | * How to use: |
426 | * @code |
427 | * { |
428 | * GLShader *myCustomShaderIWantToPush; |
429 | * ShaderBinder binder(myCustomShaderIWantToPush); |
430 | * // do stuff with the shader being pushed on the stack |
431 | * } |
432 | * // here the Shader is automatically popped as helper does no longer exist. |
433 | * @endcode |
434 | * |
435 | * This class takes care for the case that the Compositor uses OpenGL 1 and the ShaderManager is |
436 | * not valid. In that case the helper does not do anything. So this helper can be used to simplify |
437 | * the code to remove checks for OpenGL 1/2. |
438 | * @since 4.10 |
439 | **/ |
440 | class KWIN_EXPORT ShaderBinder |
441 | { |
442 | public: |
443 | /** |
444 | * @brief Pushes the Shader of the given @p type to the ShaderManager's stack. |
445 | * |
446 | * @param type The built-in Shader type |
447 | * @param reset Whether all uniforms should be reset to their default values. Defaults to false. |
448 | * @see ShaderManager::pushShader |
449 | **/ |
450 | explicit ShaderBinder(ShaderManager::ShaderType type, bool reset = false); |
451 | /** |
452 | * @brief Pushes the given @p shader to the ShaderManager's stack. |
453 | * |
454 | * @param shader The Shader to push on the stack |
455 | * @see ShaderManager::pushShader |
456 | **/ |
457 | explicit ShaderBinder(GLShader *shader); |
458 | ~ShaderBinder(); |
459 | |
460 | /** |
461 | * @return The Shader pushed to the Stack. On OpenGL 1 this returns a @c null pointer. |
462 | **/ |
463 | GLShader *shader(); |
464 | |
465 | private: |
466 | GLShader *m_shader; |
467 | }; |
468 | |
469 | inline |
470 | ShaderBinder::ShaderBinder(ShaderManager::ShaderType type, bool reset) |
471 | : m_shader(NULL) |
472 | { |
473 | #ifdef KWIN_HAVE_OPENGL_1 |
474 | if (!ShaderManager::instance()->isValid()) { |
475 | return; |
476 | } |
477 | #endif |
478 | m_shader = ShaderManager::instance()->pushShader(type, reset); |
479 | } |
480 | |
481 | inline |
482 | ShaderBinder::ShaderBinder(GLShader *shader) |
483 | : m_shader(shader) |
484 | { |
485 | #ifdef KWIN_HAVE_OPENGL_1 |
486 | if (!ShaderManager::instance()->isValid()) { |
487 | return; |
488 | } |
489 | #endif |
490 | ShaderManager::instance()->pushShader(shader); |
491 | } |
492 | |
493 | inline |
494 | ShaderBinder::~ShaderBinder() |
495 | { |
496 | #ifdef KWIN_HAVE_OPENGL_1 |
497 | if (!ShaderManager::instance()->isValid()) { |
498 | return; |
499 | } |
500 | #endif |
501 | ShaderManager::instance()->popShader(); |
502 | } |
503 | |
504 | inline |
505 | GLShader* ShaderBinder::shader() |
506 | { |
507 | return m_shader; |
508 | } |
509 | |
510 | /** |
511 | * @short Render target object |
512 | * |
513 | * Render target object enables you to render onto a texture. This texture can |
514 | * later be used to e.g. do post-processing of the scene. |
515 | * |
516 | * @author Rivo Laks <rivolaks@hot.ee> |
517 | **/ |
518 | class KWIN_EXPORT GLRenderTarget |
519 | { |
520 | public: |
521 | /** |
522 | * Constructs a GLRenderTarget |
523 | * @param color texture where the scene will be rendered onto |
524 | **/ |
525 | explicit GLRenderTarget(const GLTexture& color); |
526 | ~GLRenderTarget(); |
527 | |
528 | /** |
529 | * Enables this render target. |
530 | * All OpenGL commands from now on affect this render target until the |
531 | * @ref disable method is called |
532 | **/ |
533 | bool enable(); |
534 | /** |
535 | * Disables this render target, activating whichever target was active |
536 | * when @ref enable was called. |
537 | **/ |
538 | bool disable(); |
539 | |
540 | /** |
541 | * Sets the target texture |
542 | * @param target texture where the scene will be rendered on |
543 | * @since 4.8 |
544 | **/ |
545 | void attachTexture(const GLTexture& target); |
546 | |
547 | bool valid() const { |
548 | return mValid; |
549 | } |
550 | |
551 | static void initStatic(); |
552 | static bool supported() { |
553 | return sSupported; |
554 | } |
555 | static void pushRenderTarget(GLRenderTarget *target); |
556 | static GLRenderTarget *popRenderTarget(); |
557 | static bool isRenderTargetBound(); |
558 | /** |
559 | * Whether the GL_EXT_framebuffer_blit extension is supported. |
560 | * This functionality is not available in OpenGL ES 2.0. |
561 | * |
562 | * @returns whether framebuffer blitting is supported. |
563 | * @since 4.8 |
564 | **/ |
565 | static bool blitSupported(); |
566 | |
567 | /** |
568 | * Blits the content of the current draw framebuffer into the texture attached to this FBO. |
569 | * |
570 | * Be aware that framebuffer blitting may not be supported on all hardware. Use @link blitSupported to check whether |
571 | * it is supported. |
572 | * @param source Geometry in screen coordinates which should be blitted, if not specified complete framebuffer is used |
573 | * @param destination Geometry in attached texture, if not specified complete texture is used as destination |
574 | * @param filter The filter to use if blitted content needs to be scaled. |
575 | * @see blitSupported |
576 | * @since 4.8 |
577 | **/ |
578 | void blitFromFramebuffer(const QRect &source = QRect(), const QRect &destination = QRect(), GLenum filter = GL_LINEAR); |
579 | |
580 | |
581 | protected: |
582 | void initFBO(); |
583 | |
584 | |
585 | private: |
586 | static bool sSupported; |
587 | static bool s_blitSupported; |
588 | static QStack<GLRenderTarget*> s_renderTargets; |
589 | |
590 | GLTexture mTexture; |
591 | bool mValid; |
592 | |
593 | GLuint mFramebuffer; |
594 | }; |
595 | |
596 | enum VertexAttributeType { |
597 | VA_Position = 0, |
598 | VA_TexCoord = 1, |
599 | VertexAttributeCount = 2 |
600 | }; |
601 | |
602 | /** |
603 | * Describes the format of a vertex attribute stored in a buffer object. |
604 | * |
605 | * The attribute format consists of the attribute index, the number of |
606 | * vector components, the data type, and the offset of the first element |
607 | * relative to the start of the vertex data. |
608 | */ |
609 | struct GLVertexAttrib |
610 | { |
611 | int index; /** The attribute index */ |
612 | int size; /** The number of components [1..4] */ |
613 | GLenum type; /** The type (e.g. GL_FLOAT) */ |
614 | int relativeOffset; /** The relative offset of the attribute */ |
615 | }; |
616 | |
617 | /** |
618 | * @short Vertex Buffer Object |
619 | * |
620 | * This is a short helper class to use vertex buffer objects (VBO). A VBO can be used to buffer |
621 | * vertex data and to store them on graphics memory. It is the only allowed way to pass vertex |
622 | * data to the GPU in OpenGL ES 2 and OpenGL 3 with forward compatible mode. |
623 | * |
624 | * If VBOs are not supported on the used OpenGL profile this class falls back to legacy |
625 | * rendering using client arrays. Therefore this class should always be used for rendering geometries. |
626 | * |
627 | * @author Martin Gräßlin <mgraesslin@kde.org> |
628 | * @since 4.6 |
629 | */ |
630 | class KWIN_EXPORT GLVertexBuffer |
631 | { |
632 | public: |
633 | /** |
634 | * Enum to define how often the vertex data in the buffer object changes. |
635 | */ |
636 | enum UsageHint { |
637 | Dynamic, ///< frequent changes, but used several times for rendering |
638 | Static, ///< No changes to data |
639 | Stream ///< Data only used once for rendering, updated very frequently |
640 | }; |
641 | |
642 | explicit GLVertexBuffer(UsageHint hint); |
643 | ~GLVertexBuffer(); |
644 | |
645 | /** |
646 | * Specifies how interleaved vertex attributes are laid out in |
647 | * the buffer object. |
648 | * |
649 | * Note that the attributes and the stride should be 32 bit aligned |
650 | * or a performance penalty may be incurred. |
651 | * |
652 | * For some hardware the optimal stride is a multiple of 32 bytes. |
653 | * |
654 | * Example: |
655 | * |
656 | * struct Vertex { |
657 | * QVector3D position; |
658 | * QVector2D texcoord; |
659 | * }; |
660 | * |
661 | * const GLVertexAttrib attribs[] = { |
662 | * { VA_Position, 3, GL_FLOAT, offsetof(Vertex, position) }, |
663 | * { VA_TexCoord, 2, GL_FLOAT, offsetof(Vertex, texcoord) } |
664 | * }; |
665 | * |
666 | * Vertex vertices[6]; |
667 | * vbo->setAttribLayout(attribs, 2, sizeof(Vertex)); |
668 | * vbo->setData(vertices, sizeof(vertices)); |
669 | */ |
670 | void setAttribLayout(const GLVertexAttrib *attribs, int count, int stride); |
671 | |
672 | /** |
673 | * Uploads data into the buffer object's data store. |
674 | */ |
675 | void setData(const void *data, size_t sizeInBytes); |
676 | |
677 | /** |
678 | * Sets the number of vertices that will be drawn by the render() method. |
679 | */ |
680 | void setVertexCount(int count); |
681 | |
682 | /** |
683 | * Sets the vertex data. |
684 | * @param numberVertices The number of vertices in the arrays |
685 | * @param dim The dimension of the vertices: 2 for x/y, 3 for x/y/z |
686 | * @param vertices The vertices, size must equal @a numberVertices * @a dim |
687 | * @param texcoords The texture coordinates for each vertex. |
688 | * Size must equal 2 * @a numberVertices. |
689 | */ |
690 | void setData(int numberVertices, int dim, const float* vertices, const float* texcoords); |
691 | |
692 | /** |
693 | * Maps an unused range of the data store into the client's address space. |
694 | * |
695 | * The data store will be reallocated if it is smaller than the given size. |
696 | * |
697 | * The buffer object is mapped for writing, not reading. Attempts to read from |
698 | * the mapped buffer range may result in system errors, including program |
699 | * termination. The data in the mapped region is undefined until it has been |
700 | * written to. If subsequent GL calls access unwritten memory, the results are |
701 | * undefined and system errors, including program termination, may occur. |
702 | * |
703 | * No GL calls that access the buffer object must be made while the buffer |
704 | * object is mapped. The returned pointer must not be passed as a parameter |
705 | * value to any GL function. |
706 | * |
707 | * It is assumed that the GL_ARRAY_BUFFER_BINDING will not be changed while |
708 | * the buffer object is mapped. |
709 | */ |
710 | GLvoid *map(size_t size); |
711 | |
712 | /** |
713 | * Flushes the mapped buffer range and unmaps the buffer. |
714 | */ |
715 | void unmap(); |
716 | |
717 | /** |
718 | * Binds the vertex arrays to the context. |
719 | */ |
720 | void bindArrays(); |
721 | |
722 | /** |
723 | * Disables the vertex arrays. |
724 | */ |
725 | void unbindArrays(); |
726 | |
727 | /** |
728 | * Draws count vertices beginning with first. |
729 | */ |
730 | void draw(GLenum primitiveMode, int first, int count); |
731 | |
732 | /** |
733 | * Draws count vertices beginning with first. |
734 | */ |
735 | void draw(const QRegion ®ion, GLenum primitiveMode, int first, int count, bool hardwareClipping = false); |
736 | |
737 | /** |
738 | * Renders the vertex data in given @a primitiveMode. |
739 | * Please refer to OpenGL documentation of glDrawArrays or glDrawElements for allowed |
740 | * values for @a primitiveMode. Best is to use GL_TRIANGLES or similar to be future |
741 | * compatible. |
742 | */ |
743 | void render(GLenum primitiveMode); |
744 | /** |
745 | * Same as above restricting painting to @a region if @a hardwareClipping is true. |
746 | * It's within the caller's responsibility to enable GL_SCISSOR_TEST. |
747 | */ |
748 | void render(const QRegion& region, GLenum primitiveMode, bool hardwareClipping = false); |
749 | /** |
750 | * Sets the color the geometry will be rendered with. |
751 | * For legacy rendering glColor is used before rendering the geometry. |
752 | * For core shader a uniform "geometryColor" is expected and is set. |
753 | * @param color The color to render the geometry |
754 | * @param enableColor Whether the geometry should be rendered with a color or not |
755 | * @see setUseColor |
756 | * @see isUseColor |
757 | * @since 4.7 |
758 | **/ |
759 | void setColor(const QColor& color, bool enableColor = true); |
760 | /** |
761 | * @return @c true if geometry will be painted with a color, @c false otherwise |
762 | * @see setUseColor |
763 | * @see setColor |
764 | * @since 4.7 |
765 | **/ |
766 | bool isUseColor() const; |
767 | /** |
768 | * Enables/Disables rendering the geometry with a color. |
769 | * If no color is set an opaque, black color is used. |
770 | * @param enable Enable/Disable rendering with color |
771 | * @see isUseColor |
772 | * @see setColor |
773 | * @since 4.7 |
774 | **/ |
775 | void setUseColor(bool enable); |
776 | |
777 | /** |
778 | * Resets the instance to default values. |
779 | * Useful for shared buffers. |
780 | * @since 4.7 |
781 | **/ |
782 | void reset(); |
783 | |
784 | /** |
785 | * @internal |
786 | */ |
787 | static void initStatic(); |
788 | |
789 | /** |
790 | * @internal |
791 | */ |
792 | static void cleanup(); |
793 | |
794 | /** |
795 | * Returns true if VBOs are supported, it is save to use this class even if VBOs are not |
796 | * supported. |
797 | * @returns true if vertex buffer objects are supported |
798 | */ |
799 | static bool isSupported(); |
800 | |
801 | /** |
802 | * Returns true if indexed quad mode is supported, and false otherwise. |
803 | */ |
804 | static bool supportsIndexedQuads(); |
805 | |
806 | /** |
807 | * @return A shared VBO for streaming data |
808 | * @since 4.7 |
809 | **/ |
810 | static GLVertexBuffer *streamingBuffer(); |
811 | |
812 | private: |
813 | GLVertexBufferPrivate* const d; |
814 | }; |
815 | |
816 | } // namespace |
817 | |
818 | /** @} */ |
819 | |
820 | #endif |
821 | |