From ae95ab0c4306f837b5a9347f4e484a375f250673 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Sun, 5 Dec 2010 09:13:46 +0100 Subject: [PATCH] Adding color to VBO. A color can be specified to render the geometry of the VBO. For legacy painting glColor is used, for shader a uniform is set. In order to allow rendering without texcoords, it is possible to pass a null pointer as texcoords. Shader added to scene which just renders a colored geometry without texturing. --- lib/kwinglutils.cpp | 60 +++++++++++++++++++++++++++++++++------ lib/kwinglutils.h | 27 ++++++++++++++++++ resources.qrc | 2 ++ scene-color-fragment.glsl | 11 +++++++ scene-color-vertex.glsl | 14 +++++++++ scene_opengl.cpp | 16 +++++++++++ scene_opengl.h | 3 +- scene_opengl_egl.cpp | 1 + scene_opengl_glx.cpp | 1 + 9 files changed, 125 insertions(+), 10 deletions(-) create mode 100644 scene-color-fragment.glsl create mode 100644 scene-color-vertex.glsl diff --git a/lib/kwinglutils.cpp b/lib/kwinglutils.cpp index 0d3efa9d91..8ab363f5cf 100644 --- a/lib/kwinglutils.cpp +++ b/lib/kwinglutils.cpp @@ -1229,6 +1229,8 @@ class GLVertexBufferPrivate , numberVertices( 0 ) , dimension( 2 ) , useShader( false ) + , useColor( false ) + , color( 0, 0, 0, 255 ) { if( GLVertexBufferPrivate::supported ) { @@ -1250,6 +1252,8 @@ class GLVertexBufferPrivate static bool supported; QVector legacyVertices; QVector legacyTexCoords; + bool useColor; + QColor color; void legacyPainting( QRegion region, GLenum primitiveMode ); void corePainting( const QRegion& region, GLenum primitiveMode ); @@ -1262,8 +1266,14 @@ void GLVertexBufferPrivate::legacyPainting( QRegion region, GLenum primitiveMode // Enable arrays glEnableClientState( GL_VERTEX_ARRAY ); glVertexPointer( dimension, GL_FLOAT, 0, legacyVertices.constData() ); - glEnableClientState( GL_TEXTURE_COORD_ARRAY ); - glTexCoordPointer( 2, GL_FLOAT, 0, legacyTexCoords.constData() ); + if (!legacyTexCoords.isEmpty()) { + glEnableClientState( GL_TEXTURE_COORD_ARRAY ); + glTexCoordPointer( 2, GL_FLOAT, 0, legacyTexCoords.constData() ); + } + + if (useColor) { + glColor4f(color.redF(), color.greenF(), color.blueF(), color.alphaF()); + } // Clip using scissoring PaintClipper pc( region ); @@ -1275,7 +1285,9 @@ void GLVertexBufferPrivate::legacyPainting( QRegion region, GLenum primitiveMode } glDisableClientState( GL_VERTEX_ARRAY ); - glDisableClientState( GL_TEXTURE_COORD_ARRAY ); + if (!legacyTexCoords.isEmpty()) { + glDisableClientState( GL_TEXTURE_COORD_ARRAY ); + } #endif } @@ -1296,6 +1308,13 @@ void GLVertexBufferPrivate::corePainting( const QRegion& region, GLenum primitiv glBindBuffer( GL_ARRAY_BUFFER, buffers[ 1 ] ); glVertexAttribPointer( texAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0 ); + if (useColor) { + GLint colorLocation = glGetUniformLocation(currentProgram, "geometryColor"); + if (colorLocation != 0) { + glUniform4f(currentProgram, color.redF(), color.greenF(), color.blueF(), color.alphaF()); + } + } + // TODO: reenable paint clipper // Clip using scissoring PaintClipper pc( region ); @@ -1339,11 +1358,12 @@ void GLVertexBuffer::setData( int numberVertices, int dim, const float* vertices d->legacyVertices << vertices[i]; } d->legacyTexCoords.clear(); - d->legacyTexCoords.reserve( numberVertices * 2 ); - for( int i=0; ilegacyTexCoords << texcoords[i]; + if (texcoords != NULL) { + d->legacyTexCoords.reserve( numberVertices * 2 ); + for (int i=0; ilegacyTexCoords << texcoords[i]; } + } return; } GLenum hint; @@ -1366,8 +1386,10 @@ void GLVertexBuffer::setData( int numberVertices, int dim, const float* vertices glBindBuffer( GL_ARRAY_BUFFER, d->buffers[ 0 ] ); glBufferData( GL_ARRAY_BUFFER, sizeof(GLfloat)*numberVertices*d->dimension, vertices, hint ); - glBindBuffer( GL_ARRAY_BUFFER, d->buffers[ 1 ] ); - glBufferData( GL_ARRAY_BUFFER, sizeof(GLfloat)*numberVertices*2, texcoords, hint ); + if (texcoords != NULL) { + glBindBuffer( GL_ARRAY_BUFFER, d->buffers[ 1 ] ); + glBufferData( GL_ARRAY_BUFFER, sizeof(GLfloat)*numberVertices*2, texcoords, hint ); + } glBindBuffer( GL_ARRAY_BUFFER, 0 ); } @@ -1398,6 +1420,10 @@ void GLVertexBuffer::render( const QRegion& region, GLenum primitiveMode ) glBindBuffer( GL_ARRAY_BUFFER, d->buffers[ 1 ] ); glTexCoordPointer( 2, GL_FLOAT, 0, 0 ); + if (d->useColor) { + glColor4f(d->color.redF(), d->color.greenF(), d->color.blueF(), d->color.alphaF()); + } + // Clip using scissoring PaintClipper pc( region ); for( PaintClipper::Iterator iterator; @@ -1429,6 +1455,22 @@ bool GLVertexBuffer::isSupported() return GLVertexBufferPrivate::supported; } +bool GLVertexBuffer::isUseColor() const +{ + return d->useColor; +} + +void GLVertexBuffer::setUseColor(bool enable) +{ + d->useColor = enable; +} + +void GLVertexBuffer::setColor(const QColor& color, bool enable) +{ + d->useColor = enable; + d->color = color; +} + void GLVertexBuffer::initStatic() { #ifdef KWIN_HAVE_OPENGLES diff --git a/lib/kwinglutils.h b/lib/kwinglutils.h index 1141bd938e..a7b64bdd18 100644 --- a/lib/kwinglutils.h +++ b/lib/kwinglutils.h @@ -404,6 +404,33 @@ class KWIN_EXPORT GLVertexBuffer * @since 4.7 **/ bool isUseShader() const; + /** + * Sets the color the geometry will be rendered with. + * For legacy rendering glColor is used before rendering the geometry. + * For core shader a uniform "geometryColor" is expected and is set. + * @param color The color to render the geometry + * @param enableColor Whether the geometry should be rendered with a color or not + * @see setUseColor + * @see isUseColor + * @since 4.7 + **/ + void setColor(const QColor& color, bool enableColor = true); + /** + * @return @c true if geometry will be painted with a color, @c false otherwise + * @see setUseColor + * @see setColor + * @since 4.7 + **/ + bool isUseColor() const; + /** + * Enables/Disables rendering the geometry with a color. + * If no color is set an opaque, black color is used. + * @param enable Enable/Disable rendering with color + * @see isUseColor + * @see setColor + * @since 4.7 + **/ + void setUseColor(bool enable); /** * @internal diff --git a/resources.qrc b/resources.qrc index 4ddc63a92d..b4e1fb62a8 100644 --- a/resources.qrc +++ b/resources.qrc @@ -4,6 +4,8 @@ lanczos-fragment.glsl scene-vertex.glsl scene-fragment.glsl + scene-color-vertex.glsl + scene-color-fragment.glsl scene-generic-vertex.glsl diff --git a/scene-color-fragment.glsl b/scene-color-fragment.glsl new file mode 100644 index 0000000000..d2b425053b --- /dev/null +++ b/scene-color-fragment.glsl @@ -0,0 +1,11 @@ +#ifdef GL_ES +precision highp float; +#endif +uniform vec4 geometryColor; + +// not used +varying vec2 varyingTexCoords; + +void main() { + gl_FragColor = geometryColor; +} diff --git a/scene-color-vertex.glsl b/scene-color-vertex.glsl new file mode 100644 index 0000000000..12a4672228 --- /dev/null +++ b/scene-color-vertex.glsl @@ -0,0 +1,14 @@ +#ifdef GL_ES +precision highp float; +#endif +// size of the complete display in pixels, x==width, y==height +uniform vec2 displaySize; +// geometry of the window/texture to be rendered: x, y, width, height in display geometry +uniform vec4 geometry; + +// passed in vertex - only x and y are used +attribute vec4 vertex; + +void main() { + gl_Position.xy = 2.0*vec2(geometry.x + vertex.x, displaySize.y - vertex.y - geometry.y)/displaySize - vertex.ww; +} diff --git a/scene_opengl.cpp b/scene_opengl.cpp index 4a9a375fed..7e0aab13dc 100644 --- a/scene_opengl.cpp +++ b/scene_opengl.cpp @@ -166,6 +166,22 @@ bool SceneOpenGL::setupSceneShaders() kDebug(1212) << "Generic Scene Shader is not valid"; return false; } + m_colorShader = new GLShader(":/resources/scene-color-vertex.glsl", ":/resources/scene-color-fragment.glsl"); + if (m_colorShader->isValid()) { + m_colorShader->bind(); + m_colorShader->setUniform("displaySize", QVector2D(displayWidth(), displayHeight())); + m_colorShader->unbind(); + kDebug(1212) << "Color Shader is valid"; + } else { + delete m_genericSceneShader; + m_genericSceneShader = NULL; + delete m_sceneShader; + m_sceneShader = NULL; + delete m_colorShader; + m_colorShader = NULL; + kDebug(1212) << "Color Scene Shader is not valid"; + return false; + } return true; } diff --git a/scene_opengl.h b/scene_opengl.h index 7e6190c9fe..3481dfe1db 100644 --- a/scene_opengl.h +++ b/scene_opengl.h @@ -53,7 +53,7 @@ class SceneOpenGL virtual void windowDeleted( Deleted* ); GLShader* sceneShader() const; bool hasSceneShader() const { - return m_sceneShader != NULL && m_genericSceneShader != NULL; + return m_sceneShader != NULL && m_genericSceneShader != NULL && m_colorShader != NULL; } protected: virtual void paintGenericScreen( int mask, ScreenPaintData data ); @@ -109,6 +109,7 @@ class SceneOpenGL bool selfCheckDone; GLShader* m_sceneShader; GLShader* m_genericSceneShader; + GLShader* m_colorShader; bool debug; }; diff --git a/scene_opengl_egl.cpp b/scene_opengl_egl.cpp index f6765d5b7a..39950828e8 100644 --- a/scene_opengl_egl.cpp +++ b/scene_opengl_egl.cpp @@ -33,6 +33,7 @@ SceneOpenGL::SceneOpenGL( Workspace* ws ) , selfCheckDone( true ) , m_sceneShader( NULL ) , m_genericSceneShader( NULL ) + , m_colorShader( NULL ) { if( !initRenderingContext() ) return; diff --git a/scene_opengl_glx.cpp b/scene_opengl_glx.cpp index 8193750948..5deb58108e 100644 --- a/scene_opengl_glx.cpp +++ b/scene_opengl_glx.cpp @@ -41,6 +41,7 @@ SceneOpenGL::SceneOpenGL( Workspace* ws ) , selfCheckDone( false ) , m_sceneShader( NULL ) , m_genericSceneShader( NULL ) + , m_colorShader( NULL ) { if( !Extensions::glxAvailable()) {