← Back to team overview

compiz team mailing list archive

[Merge] lp:~sil2100/compiz/missing_versions into lp:compiz

 

Łukasz Zemczak has proposed merging lp:~sil2100/compiz/missing_versions into lp:compiz.

Requested reviews:
  compiz packagers (compiz)

For more details, see:
https://code.launchpad.net/~sil2100/compiz/missing_versions/+merge/101386

Added the missing 1:0.9.7.4-0ubuntu2 and 1:0.9.7.4-0ubuntu3 from the precise PPA, introducing the armel/armhf linaro fixes. Sadly, the introduced patch doesn't seem to build properly for arm - but non-arm builds succeed normally, so everything should be fine.
-- 
https://code.launchpad.net/~sil2100/compiz/missing_versions/+merge/101386
Your team compiz packagers is requested to review the proposed merge of lp:~sil2100/compiz/missing_versions into lp:compiz.
=== modified file 'debian/changelog'
--- debian/changelog	2012-04-10 09:02:47 +0000
+++ debian/changelog	2012-04-10 14:55:03 +0000
@@ -20,6 +20,29 @@
 
  -- Didier Roche <didrocks@xxxxxxxxxx>  Thu, 05 Apr 2012 12:14:23 +0200
 
+compiz (1:0.9.7.4-0ubuntu3) precise; urgency=low
+
+  * fix typo in copying of the cmake files, so FindOpenGLES2.cmake ends up in
+    the right place for other packages (i.e. compiz-plugins-main on GLES2
+    capable arches)
+  * make copying the GLES2 cmake file architecture specifc instead of ignoring
+    if it is not found on arches that do not have it.
+
+ -- Oliver Grawert <ogra@xxxxxxxxxx>  Fri, 06 Apr 2012 13:55:13 +0200
+
+compiz (1:0.9.7.4-0ubuntu2) precise; urgency=low
+
+  * enable Linaros compiz-package-gles2.patch for armhf(/el) builds, thanks
+    to Alexandros Frantzis <alexandros.frantzis@xxxxxxxxxx> for creating it.
+  * enable quilt in debian/rules
+  * apply patches based on debian architecture via series.<arch> file
+    (stolen from eglibc)
+  * add build deps to libgl1-mesa-dev and libgl-dev for armhf builds
+  * add armel/armhf specific .install files since only a subset of modules can
+    be built yet.
+
+ -- Oliver Grawert <ogra@xxxxxxxxxx>  Thu, 05 Apr 2012 19:09:27 +0200
+
 compiz (1:0.9.7.4-0ubuntu1) precise; urgency=low
 
   * New upstream release

=== added file 'debian/compiz-core.install.armel'
--- debian/compiz-core.install.armel	1970-01-01 00:00:00 +0000
+++ debian/compiz-core.install.armel	2012-04-10 14:55:03 +0000
@@ -0,0 +1,8 @@
+debian/tmp/usr/bin/compiz*
+debian/tmp/usr/lib/libcompiz_core.so*
+debian/compiz-decorator usr/bin/
+debian/tmp/usr/share/compiz/*.png
+debian/tmp/usr/share/compiz/core.xml
+debian/source_compiz.py usr/share/apport/package-hooks
+debian/tmp/usr/share/locale
+debian/tmp/usr/share/applications/compiz.desktop

=== added file 'debian/compiz-core.install.armhf'
--- debian/compiz-core.install.armhf	1970-01-01 00:00:00 +0000
+++ debian/compiz-core.install.armhf	2012-04-10 14:55:03 +0000
@@ -0,0 +1,8 @@
+debian/tmp/usr/bin/compiz*
+debian/tmp/usr/lib/libcompiz_core.so*
+debian/compiz-decorator usr/bin/
+debian/tmp/usr/share/compiz/*.png
+debian/tmp/usr/share/compiz/core.xml
+debian/source_compiz.py usr/share/apport/package-hooks
+debian/tmp/usr/share/locale
+debian/tmp/usr/share/applications/compiz.desktop

=== added symlink 'debian/compiz-plugins.install.armel'
=== target is u'compiz-plugins.install.armhf'
=== added file 'debian/compiz-plugins.install.armhf'
--- debian/compiz-plugins.install.armhf	1970-01-01 00:00:00 +0000
+++ debian/compiz-plugins.install.armhf	2012-04-10 14:55:03 +0000
@@ -0,0 +1,11 @@
+debian/tmp/usr/*/compiz/*annotate.*
+debian/tmp/usr/*/compiz/*clone.*
+debian/tmp/usr/*/compiz/*commands.*
+debian/tmp/usr/*/compiz/*copytex.*
+debian/tmp/usr/*/compiz/*dbus.*
+debian/tmp/usr/*/compiz/*imgsvg.*
+debian/tmp/usr/*/compiz/*inotify.*
+debian/tmp/usr/*/compiz/*obs.*
+debian/tmp/usr/*/compiz/*screenshot.*
+debian/tmp/usr/*/compiz/*switcher.*
+debian/tmp/usr/*/compiz/*water.*

=== modified file 'debian/control'
--- debian/control	2012-03-30 11:26:17 +0000
+++ debian/control	2012-04-10 14:55:03 +0000
@@ -8,7 +8,9 @@
  debhelper (>= 7.0.50~), intltool, 
  libcairo2-dev,
  libdbus-glib-1-dev, libgconf2-dev, 
- libgl1-mesa-dev (>= 6.5.1) | libgl-dev, libglib2.0-dev, libboost-serialization1.46-dev,
+ libgl1-mesa-dev (>= 6.5.1) [!armhf !armel]| libgl-dev [!armhf !armel],
+ libegl1-mesa-dev [armhf armel], libgles2-mesa-dev [armhf armel],
+ libglib2.0-dev, libboost-serialization1.46-dev,
  libgtk2.0-dev, libgtk-3-dev, libice-dev (>= 1:1.0.1), 
  libmetacity-dev (>= 1:2.30.3-0ubuntu3), libpango1.0-dev, libpng12-dev | libpng-dev, librsvg2-dev, 
  libsm-dev (>= 1:1.0.1), libtool, libwnck-dev, libx11-dev, libxcomposite-dev (>= 1:0.3-2), libxext-dev,
@@ -18,7 +20,7 @@
  libxml2-dev, libxslt1-dev,
  libstartup-notification0-dev (>= 0.7),
  quilt (>= 0.40), x11proto-gl-dev (>= 1.4.8), xsltproc,
- libglu1-mesa-dev,
+ libglu1-mesa-dev [!armhf !armel],
  libglib2.0-dev,
  libglibmm-2.4-dev,
  kde-workspace-dev, kdelibs5-dev (>= 4:4.2.2),
@@ -73,7 +75,7 @@
 
 Package: compiz-dev
 Architecture: any
-Depends: compiz-core (= ${binary:Version}), ${misc:Depends}, libgl1-mesa-dev | libgl-dev, libpng-dev, libgtk-3-dev, libxcomposite-dev (>= 1:0.3-2), libxfixes-dev (>=1:4.0.1), libxdamage-dev (>= 1:1.0.3), libxinerama-dev, libxrandr-dev (>=2:1.1.0.2), libxcursor-dev, libice-dev (>= 1:1.0.1), libsm-dev (>= 1:1.0.1), libstartup-notification0-dev (>= 0.7), libxslt1-dev, libxml2-dev, libx11-xcb-dev, libglib2.0-dev, libglibmm-2.4-dev, compiz-plugins (= ${binary:Version}), libdecoration0-dev
+Depends: compiz-core (= ${binary:Version}), ${misc:Depends}, libgl1-mesa-dev [!armhf !armel]| libgl-dev [!armhf !armel], libegl1-mesa-dev [armhf armel], libgles2-mesa-dev [armhf armel], libpng-dev, libgtk-3-dev, libxcomposite-dev (>= 1:0.3-2), libxfixes-dev (>=1:4.0.1), libxdamage-dev (>= 1:1.0.3), libxinerama-dev, libxrandr-dev (>=2:1.1.0.2), libxcursor-dev, libice-dev (>= 1:1.0.1), libsm-dev (>= 1:1.0.1), libstartup-notification0-dev (>= 0.7), libxslt1-dev, libxml2-dev, libx11-xcb-dev, libglib2.0-dev, libglibmm-2.4-dev, compiz-plugins (= ${binary:Version}), libdecoration0-dev
 Description: OpenGL window and compositing manager - development files
  Compiz brings to life a variety of visual effects that make the Linux desktop
  easier to use, more powerful and intuitive, and more accessible for users

=== added file 'debian/patches/compiz-package-gles2.patch'
--- debian/patches/compiz-package-gles2.patch	1970-01-01 00:00:00 +0000
+++ debian/patches/compiz-package-gles2.patch	2012-04-10 14:55:03 +0000
@@ -0,0 +1,8943 @@
+--- compiz-0.9.7.6.orig/CMakeLists.txt
++++ compiz-0.9.7.6/CMakeLists.txt
+@@ -119,6 +119,12 @@ install (
+     DESTINATION ${COMPIZ_DESTDIR}${libdir}/pkgconfig
+ )
+ 
++# temporarily disable plugins that aren't ported yed
++set (COMPIZ_DISABLE_PLUGIN_BLUR ON)
++set (COMPIZ_DISABLE_PLUGIN_CUBE ON)
++set (COMPIZ_DISABLE_PLUGIN_ROTATE ON)
++set (COMPIZ_DISABLE_PLUGIN_WOBBLY ON)
++
+ # Build Google Test and make its headers known
+ find_package (GTest)
+ 
+@@ -183,6 +189,12 @@ _print_configure_results ()
+ 
+ _check_compiz_cmake_macro (${CMAKE_MODULE_PATH_ORIG})
+ 
++# temporarily disable plugins that aren't ported yed
++SET(COMPIZ_DISABLE_PLUGIN_BLUR "ON")
++SET(COMPIZ_DISABLE_PLUGIN_CUBE "ON")
++SET(COMPIZ_DISABLE_PLUGIN_ROTATE "ON")
++SET(COMPIZ_DISABLE_PLUGIN_WATER "ON")
++SET(COMPIZ_DISABLE_PLUGIN_WOBBLY "ON")
+ # Enable coverage reporting for compiz
+ enable_coverage_report()
+ 
+--- compiz-0.9.7.6.orig/plugins/wobbly/CMakeLists.txt
++++ compiz-0.9.7.6/plugins/wobbly/CMakeLists.txt
+@@ -2,4 +2,4 @@ find_package (Compiz REQUIRED)
+ 
+ include (CompizPlugin)
+ 
+-compiz_plugin(wobbly PLUGINDEPS composite opengl)
++#compiz_plugin(wobbly PLUGINDEPS composite opengl)
+--- compiz-0.9.7.6.orig/plugins/rotate/CMakeLists.txt
++++ compiz-0.9.7.6/plugins/rotate/CMakeLists.txt
+@@ -2,4 +2,4 @@ find_package (Compiz REQUIRED)
+ 
+ include (CompizPlugin)
+ 
+-compiz_plugin(rotate PLUGINDEPS composite opengl cube)
+\ No newline at end of file
++#compiz_plugin(rotate PLUGINDEPS composite opengl cube)
+--- compiz-0.9.7.6.orig/plugins/decor/decor.xml.in
++++ compiz-0.9.7.6/plugins/decor/decor.xml.in
+@@ -30,7 +30,7 @@
+ 		<option name="active_shadow_opacity" type="float">
+ 		    <_short>Shadow Opacity</_short>
+ 		    <_long>Drop shadow opacity</_long>
+-		    <default>0.8</default>
++		    <default>0.5</default>
+ 		    <min>0.01</min>
+ 		    <max>6.0</max>
+ 		    <precision>0.01</precision>
+@@ -65,7 +65,7 @@
+ 		<option name="inactive_shadow_radius" type="float">
+ 		    <_short>Shadow Radius</_short>
+ 		    <_long>Drop shadow radius</_long>
+-		    <default>5.0</default>
++		    <default>8.0</default>
+ 		    <min>0.1</min>
+ 		    <max>13.0</max>
+ 		    <precision>0.1</precision>
+@@ -73,7 +73,7 @@
+ 		<option name="inactive_shadow_opacity" type="float">
+ 		    <_short>Shadow Opacity</_short>
+ 		    <_long>Drop shadow opacity</_long>
+-		    <default>0.4</default>
++		    <default>0.5</default>
+ 		    <min>0.01</min>
+ 		    <max>6.0</max>
+ 		    <precision>0.01</precision>
+@@ -100,7 +100,6 @@
+ 	    <option name="command" type="string">
+ 		<_short>Command</_short>
+ 		<_long>Decorator command line that is executed if no decorator is already running</_long>
+-		<default>/usr/bin/compiz-decorator</default>
+ 	    </option>
+ 	    <option name="mipmap" type="bool">
+ 		<_short>Mipmap</_short>
+--- compiz-0.9.7.6.orig/plugins/decor/src/decor.cpp
++++ compiz-0.9.7.6/plugins/decor/src/decor.cpp
+@@ -177,15 +177,13 @@ isAncestorTo (CompWindow *window,
+  */
+ 
+ bool
+-DecorWindow::glDraw (const GLMatrix     &transform,
+-		     GLFragment::Attrib &attrib,
+-		     const CompRegion   &region,
+-		     unsigned int       mask)
++DecorWindow::glDraw (const GLMatrix            &transform,
++		     const GLWindowPaintAttrib &attrib,
++		     const CompRegion          &region,
++		     unsigned int              mask)
+ {
+     bool status;
+ 
+-    status = gWindow->glDraw (transform, attrib, region, mask);
+-
+     /* Don't render dock decorations (shadows) on just any old window */
+     if (!(window->type () & CompWindowTypeDockMask))
+     {
+@@ -205,16 +203,19 @@ DecorWindow::glDraw (const GLMatrix
+ 	}
+     }
+ 
++    status = gWindow->glDraw (transform, attrib, region, mask);
++
+     return status;
+ }
+ 
+ void
+-DecorWindow::glDecorate (const GLMatrix     &transform,
+-		         GLFragment::Attrib &attrib,
+-		         const CompRegion   &region,
+-		         unsigned int       mask)
++DecorWindow::glDecorate (const GLMatrix            &transform,
++			 const GLWindowPaintAttrib &attrib,
++			 const CompRegion          &region,
++			 unsigned int              mask)
+ {
+     const CompRegion *preg = NULL;
++    GLboolean isBlendingEnabled;
+ 
+     if ((mask & (PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK |
+ 		 PAINT_WINDOW_WITH_OFFSET_MASK)))
+@@ -241,7 +242,7 @@ DecorWindow::glDecorate (const GLMatrix
+ 	GLTexture::MatrixList ml (1);
+ 	mask |= PAINT_WINDOW_BLEND_MASK;
+ 
+-	gWindow->geometry ().reset ();
++	gWindow->vertexBuffer ()->begin ();
+ 
+ 	for (int i = 0; i < wd->nQuad; i++)
+ 	{
+@@ -258,9 +259,14 @@ DecorWindow::glDecorate (const GLMatrix
+ 	    }
+ 	}
+ 
+-	if (gWindow->geometry ().vCount)
+-	    gWindow->glDrawTexture (wd->decor->texture->textures[0],
+-				    attrib, mask);
++	gWindow->vertexBuffer ()->end ();
++
++	glGetBooleanv (GL_BLEND, &isBlendingEnabled);
++	glEnable (GL_BLEND);
++	gWindow->glDrawTexture (wd->decor->texture->textures[0], transform,
++	                        attrib, mask);
++	if (!isBlendingEnabled)
++	    glDisable (GL_BLEND);
+     }
+     else if (wd && !reg.isEmpty () &&
+ 	     wd->decor->type == WINDOW_DECORATION_TYPE_WINDOW)
+@@ -272,14 +278,18 @@ DecorWindow::glDecorate (const GLMatrix
+ 	if (gWindow->textures ().empty ())
+ 	    return;
+ 
++	glGetBooleanv (GL_BLEND, &isBlendingEnabled);
++	glEnable (GL_BLEND);
++
+ 	if (gWindow->textures ().size () == 1)
+ 	{
+ 	    ml[0] = gWindow->matrices ()[0];
+-	    gWindow->geometry ().reset ();
++	    gWindow->vertexBuffer ()->begin ();
+ 	    gWindow->glAddGeometry (ml, window->frameRegion (), reg);
++	    gWindow->vertexBuffer ()->end ();
+ 
+-	    if (gWindow->geometry ().vCount)
+-		gWindow->glDrawTexture (gWindow->textures ()[0], attrib, mask);
++	    gWindow->glDrawTexture (gWindow->textures ()[0], transform,
++	                            attrib, mask);
+ 	}
+ 	else
+ 	{
+@@ -288,14 +298,17 @@ DecorWindow::glDecorate (const GLMatrix
+ 	    for (unsigned int i = 0; i < gWindow->textures ().size (); i++)
+ 	    {
+ 		ml[0] = gWindow->matrices ()[i];
+-		gWindow->geometry ().reset ();
++		gWindow->vertexBuffer ()->begin ();
+ 		gWindow->glAddGeometry (ml, regions[i], reg);
++		gWindow->vertexBuffer ()->end ();
+ 
+-		if (gWindow->geometry ().vCount)
+-		    gWindow->glDrawTexture (gWindow->textures ()[i], attrib,
+-					    mask);
++		gWindow->glDrawTexture (gWindow->textures ()[i], transform,
++		                        attrib, mask);
+ 	    }
+ 	}
++
++	if (!isBlendingEnabled)
++	    glDisable (GL_BLEND);
+     }
+ }
+ 
+--- compiz-0.9.7.6.orig/plugins/decor/src/decor.h
++++ compiz-0.9.7.6/plugins/decor/src/decor.h
+@@ -252,10 +252,10 @@ class DecorWindow :
+ 
+ 	void computeShadowRegion ();
+ 
+-	bool glDraw (const GLMatrix &, GLFragment::Attrib &,
++	bool glDraw (const GLMatrix &, const GLWindowPaintAttrib &,
+ 		     const CompRegion &, unsigned int);
+-	void glDecorate (const GLMatrix &, GLFragment::Attrib &,
+-		         const CompRegion &, unsigned int);
++	void glDecorate (const GLMatrix &, const GLWindowPaintAttrib &,
++			 const CompRegion &, unsigned int);
+ 
+ 	void windowNotify (CompWindowNotify n);
+ 
+--- compiz-0.9.7.6.orig/plugins/cube/CMakeLists.txt
++++ compiz-0.9.7.6/plugins/cube/CMakeLists.txt
+@@ -2,4 +2,4 @@ find_package (Compiz REQUIRED)
+ 
+ include (CompizPlugin)
+ 
+-compiz_plugin(cube PLUGINDEPS composite opengl)
+\ No newline at end of file
++#compiz_plugin(cube PLUGINDEPS composite opengl)
+--- compiz-0.9.7.6.orig/plugins/cube/src/cube.cpp
++++ compiz-0.9.7.6/plugins/cube/src/cube.cpp
+@@ -1123,7 +1123,6 @@ CubeScreen::cubePaintTop (const GLScreen
+     if ((priv->mDesktopOpacity != OPAQUE) || (color[3] != OPAQUE))
+     {
+ 	priv->gScreen->setTexEnvMode (GL_MODULATE);
+-	glEnable (GL_BLEND);
+ 	glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+     }
+ 
+@@ -1149,7 +1148,6 @@ CubeScreen::cubePaintTop (const GLScreen
+     glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+ 
+     priv->gScreen->setTexEnvMode (GL_REPLACE);
+-    glDisable (GL_BLEND);
+     glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ }
+ 
+@@ -1190,7 +1188,6 @@ CubeScreen::cubePaintBottom (const GLScr
+     if ((priv->mDesktopOpacity != OPAQUE) || (color[3] != OPAQUE))
+     {
+ 	priv->gScreen->setTexEnvMode (GL_MODULATE);
+-	glEnable (GL_BLEND);
+ 	glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+     }
+ 
+@@ -1206,7 +1203,6 @@ CubeScreen::cubePaintBottom (const GLScr
+     glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+ 
+     priv->gScreen->setTexEnvMode (GL_REPLACE);
+-    glDisable (GL_BLEND);
+     glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ }
+ 
+--- compiz-0.9.7.6.orig/plugins/fade/fade.xml.in
++++ compiz-0.9.7.6/plugins/fade/fade.xml.in
+@@ -9,7 +9,6 @@
+ 	    </requirement>
+ 	    <relation type="after">
+ 		<plugin>decor</plugin>
+-		<plugin>staticswitcher</plugin>
+ 	    </relation>
+ 	    <relation type="before">
+ 		<plugin>cube</plugin>
+@@ -50,7 +49,7 @@
+ 	    <option name="window_match" type="match">
+ 		<_short>Fade windows</_short>
+ 		<_long>Windows that should be fading</_long>
+-                <default>any &amp; !(title=notify-osd)</default>
++		<default>any</default>
+ 	    </option>
+ 	    <option name="visual_bell" type="bell">
+ 		<_short>Visual Bell</_short>
+--- compiz-0.9.7.6.orig/plugins/screenshot/src/screenshot.cpp
++++ compiz-0.9.7.6/plugins/screenshot/src/screenshot.cpp
+@@ -249,6 +249,10 @@ ShotScreen::glPaintOutput (const GLScree
+ 			   CompOutput                *output,
+ 			   unsigned int               mask)
+ {
++    GLVertexBuffer *streamingBuffer = GLVertexBuffer::streamingBuffer ();
++    GLMatrix        transform (matrix);
++    GLfloat         vertexData[12];
++    GLushort        colorData[4];
+     bool status;
+ 
+     status = gScreen->glPaintOutput (attrib, matrix, region, output, mask);
+@@ -264,31 +268,54 @@ ShotScreen::glPaintOutput (const GLScree
+ 
+ 	if (mGrabIndex)
+ 	{
+-	    glPushMatrix ();
++	    vertexData[0]  = x1;
++	    vertexData[1]  = y1;
++	    vertexData[2]  = 0.0f;
++	    vertexData[3]  = x1;
++	    vertexData[4]  = y2;
++	    vertexData[5]  = 0.0f;
++	    vertexData[6]  = x2;
++	    vertexData[7]  = y1;
++	    vertexData[8]  = 0.0f;
++	    vertexData[9]  = x2;
++	    vertexData[10] = y2;
++	    vertexData[11] = 0.0f;
++
++	    colorData[0] = 0x2fff;
++	    colorData[1] = 0x2fff;
++	    colorData[2] = 0x4fff;
++	    colorData[3] = 0x4fff;
++
++
++	    transform.translate (-0.5f, -0.5f, -DEFAULT_Z_CAMERA);
++	    transform.scale (1.0f / output->width (),
++	                     -1.0f / output->height (),
++	                     1.0f);
++	    transform.translate (-output->region ()->extents.x1,
++	                         -output->region ()->extents.y2,
++	                         0.0f);
++
++	    streamingBuffer->begin (GL_TRIANGLE_STRIP);
++
++	    streamingBuffer->addColors (1, colorData);
++	    streamingBuffer->addVertices (4, vertexData);
++
++	    streamingBuffer->end ();
++	    streamingBuffer->render (transform);
++
++	    streamingBuffer->begin (GL_LINE_LOOP);
++
++	    vertexData[6]  = x2;
++	    vertexData[7]  = y2;
++	    vertexData[9]  = x2;
++	    vertexData[10] = y1;
++	    colorData [3]  = 0x9fff;
+ 
+-	    glTranslatef (-0.5f, -0.5f, -DEFAULT_Z_CAMERA);
+-	    glScalef (1.0f  / output->width (),
+-	    	      -1.0f / output->height (),
+-	    	      1.0f);
+-	    glTranslatef (-output->region ()->extents.x1,
+-	    		  -output->region ()->extents.y2,
+-	    		  0.0f);
+-
+-	    glDisableClientState (GL_TEXTURE_COORD_ARRAY);
+-	    glEnable (GL_BLEND);
+-	    glColor4us (0x2fff, 0x2fff, 0x4fff, 0x4fff);
+-	    glRecti (x1, y2, x2, y1);
+-	    glColor4us (0x2fff, 0x2fff, 0x4fff, 0x9fff);
+-	    glBegin (GL_LINE_LOOP);
+-	    glVertex2i (x1, y1);
+-	    glVertex2i (x2, y1);
+-	    glVertex2i (x2, y2);
+-	    glVertex2i (x1, y2);
+-	    glEnd ();
+-	    glColor4usv (defaultColor);
+-	    glDisable (GL_BLEND);
+-	    glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+-	    glPopMatrix ();
++	    streamingBuffer->addColors (1, colorData);
++	    streamingBuffer->addVertices (4, vertexData);
++
++	    streamingBuffer->end ();
++	    streamingBuffer->render (transform);
+ 	}
+     }
+ 
+--- compiz-0.9.7.6.orig/plugins/gnomecompat/gnomecompat.xml.in
++++ compiz-0.9.7.6/plugins/gnomecompat/gnomecompat.xml.in
+@@ -52,7 +52,6 @@
+ 		<option name="run_command_terminal_key" type="key">
+ 		    <_short>Open a terminal</_short>
+ 		    <_long>Open a terminal</_long>
+-		    <default>&lt;Control&gt;&lt;Alt&gt;T</default>
+ 		</option>
+ 	    </group>
+ 	</options>
+--- compiz-0.9.7.6.orig/plugins/place/place.xml.in
++++ compiz-0.9.7.6/plugins/place/place.xml.in
+@@ -19,8 +19,8 @@
+ 	    <option name="mode" type="int">
+ 		<_short>Placement Mode</_short>
+ 		<_long>Algorithm to use for window placement</_long>
+-		<default>2</default>
+-		<min>0</min>
++		<default>0</default>
++		<min>2</min>
+ 		<max>5</max>
+ 		<desc>
+ 		    <value>0</value>
+--- compiz-0.9.7.6.orig/plugins/scale/scale.xml.in
++++ compiz-0.9.7.6/plugins/scale/scale.xml.in
+@@ -18,14 +18,14 @@
+ 			<option name="spacing" type="int">
+ 				<_short>Spacing</_short>
+ 				<_long>Space between windows</_long>
+-				<default>68</default>
++				<default>10</default>
+ 				<min>0</min>
+ 				<max>250</max>
+ 			</option>
+ 			<option name="speed" type="float">
+ 				<_short>Speed</_short>
+ 				<_long>Scale speed</_long>
+-				<default>2.4</default>
++				<default>1.5</default>
+ 				<min>0.1</min>
+ 				<max>50</max>
+ 				<precision>0.1</precision>
+@@ -33,7 +33,7 @@
+ 			<option name="timestep" type="float">
+ 				<_short>Timestep</_short>
+ 				<_long>Scale timestep</_long>
+-				<default>0.1</default>
++				<default>1.2</default>
+ 				<min>0.1</min>
+ 				<max>50</max>
+ 				<precision>0.1</precision>
+@@ -46,7 +46,7 @@
+ 			<option name="opacity" type="int">
+ 				<_short>Opacity</_short>
+ 				<_long>Amount of opacity in percent</_long>
+-				<default>100</default>
++				<default>75</default>
+ 				<min>0</min>
+ 				<max>100</max>
+ 			</option>
+@@ -55,7 +55,7 @@
+ 				<_long>Overlay an icon on windows once they are scaled</_long>
+ 				<min>0</min>
+ 				<max>2</max>
+-				<default>0</default>
++				<default>1</default>
+ 				<desc>
+ 					<value>0</value>
+ 					<_name>None</_name>
+@@ -112,7 +112,7 @@
+ 			<option name="key_bindings_toggle" type="bool">
+ 			    <_short>Key Bindings Toggle Scale Mode</_short>
+ 			    <_long>Key bindings toggle scale mode instead of enabling it when pressed and disabling it when released.</_long>
+-			    <default>true</default>
++			    <default>false</default>
+ 			</option>
+ 			<option name="button_bindings_toggle" type="bool">
+ 			    <_short>Button Bindings Toggle Scale Mode</_short>
+@@ -122,6 +122,9 @@
+ 			<option name="initiate_edge" type="edge">
+ 				<_short>Initiate Window Picker</_short>
+ 				<_long>Layout and start transforming windows</_long>
++				<default>
++				<edge name="TopRight"/>
++				</default>
+ 				<allowed edgednd="true"/>
+ 			</option>
+ 			<option name="initiate_key" type="key">
+@@ -145,7 +148,6 @@
+ 			<option name="initiate_all_key" type="key">
+ 				<_short>Initiate Window Picker For All Windows</_short>
+ 				<_long>Layout and start transforming all windows</_long>
+-				<default>&lt;Super&gt;w</default>
+ 			</option>
+ 			<option name="initiate_group_edge" type="edge">
+ 				<_short>Initiate Window Picker For Window Group</_short>
+@@ -176,7 +178,7 @@
+ 			<option name="show_desktop" type="bool">
+ 				<_short>Click Desktop to Show Desktop</_short>
+ 				<_long>Enter Show Desktop mode when Desktop is clicked during Scale</_long>
+-				<default>false</default>
++				<default>true</default>
+ 			</option>
+ 	    </group>
+ 	</options>
+--- compiz-0.9.7.6.orig/plugins/scale/src/scale.cpp
++++ compiz-0.9.7.6/plugins/scale/src/scale.cpp
+@@ -226,26 +226,19 @@ ScaleWindow::scalePaintDecoration (const
+ 	    GLTexture::MatrixList ml (1);
+ 
+ 	    ml[0] = icon->matrix ();
+-	    priv->gWindow->geometry ().reset ();
++	    priv->gWindow->vertexBuffer ()->begin ();
+ 
+ 	    if (width && height)
+ 		priv->gWindow->glAddGeometry (ml, iconReg, iconReg);
+ 
+-	    if (priv->gWindow->geometry ().vCount)
+-	    {
+-		GLFragment::Attrib fragment (sAttrib);
+-		GLMatrix           wTransform (transform);
++	    priv->gWindow->vertexBuffer ()->end ();
+ 
+-		wTransform.scale (scale, scale, 1.0f);
+-		wTransform.translate (x / scale, y / scale, 0.0f);
+-
+-		glPushMatrix ();
+-		glLoadMatrixf (wTransform.getMatrix ());
++	    GLMatrix           wTransform (transform);
+ 
+-		priv->gWindow->glDrawTexture (icon, fragment, mask);
++	    wTransform.scale (scale, scale, 1.0f);
++	    wTransform.translate (x / scale, y / scale, 0.0f);
+ 
+-		glPopMatrix ();
+-	    }
++	    priv->gWindow->glDrawTexture (icon, wTransform, sAttrib, mask);
+ 	}
+     }
+ }
+@@ -392,13 +385,13 @@ PrivateScaleWindow::glPaint (const GLWin
+ 
+ 	if (scaled)
+ 	{
+-	    GLFragment::Attrib fragment (gWindow->lastPaintAttrib ());
++	    GLWindowPaintAttrib lastAttrib (gWindow->lastPaintAttrib ());
+ 	    GLMatrix           wTransform (transform);
+ 
+ 	    if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)
+ 		return false;
+ 
+-	    if (window->alpha () || fragment.getOpacity () != OPAQUE)
++	    if (window->alpha () || lastAttrib.opacity != OPAQUE)
+ 		mask |= PAINT_WINDOW_TRANSLUCENT_MASK;
+ 
+ 	    wTransform.translate (window->x (), window->y (), 0.0f);
+@@ -406,14 +399,9 @@ PrivateScaleWindow::glPaint (const GLWin
+ 	    wTransform.translate (tx / scale - window->x (),
+ 				  ty / scale - window->y (), 0.0f);
+ 
+-	    glPushMatrix ();
+-	    glLoadMatrixf (wTransform.getMatrix ());
+-
+-	    gWindow->glDraw (wTransform, fragment, region,
++	    gWindow->glDraw (wTransform, lastAttrib, region,
+ 			     mask | PAINT_WINDOW_TRANSFORMED_MASK);
+ 
+-	    glPopMatrix ();
+-
+ 	    sWindow->scalePaintDecoration (sAttrib, transform, region, mask);
+ 	}
+     }
+--- compiz-0.9.7.6.orig/plugins/clone/src/clone.cpp
++++ compiz-0.9.7.6/plugins/clone/src/clone.cpp
+@@ -295,9 +295,6 @@ CloneScreen::glPaintOutput (const GLScre
+ 			 0.0f);
+ 	sTransform.scale (zoomX, zoomY, 1.0f);
+ 
+-	glPushMatrix ();
+-	glLoadMatrixf (sTransform.getMatrix ());
+-
+ 	filter = gScreen->textureFilter ();
+ 
+ 	if (offset == 0.0f)
+@@ -325,8 +322,6 @@ CloneScreen::glPaintOutput (const GLScre
+ 	}
+ 
+ 	gScreen->setTextureFilter (filter);
+-
+-	glPopMatrix ();
+     }
+ 
+     return status;
+--- compiz-0.9.7.6.orig/plugins/opengl/compiz-opengl.pc.in
++++ compiz-0.9.7.6/plugins/opengl/compiz-opengl.pc.in
+@@ -8,5 +8,5 @@ Description: Opengl compositing plugin f
+ Version: @VERSION@
+ 
+ Requires: compiz compiz-composite
+-Libs: -lGL -L${libdir} -lopengl
+-Cflags: @COMPIZ_CFLAGS@ -I${includedir}/compiz
+\ No newline at end of file
++Libs: @PKGCONFIG_LIBS@ -L${libdir} -lopengl
++Cflags: @COMPIZ_CFLAGS@ -I${includedir}/compiz
+--- compiz-0.9.7.6.orig/plugins/opengl/opengl.xml.in
++++ compiz-0.9.7.6/plugins/opengl/opengl.xml.in
+@@ -36,7 +36,7 @@
+ 	    <option name="sync_to_vblank" type="bool">
+ 		<_short>Sync To VBlank</_short>
+ 		<_long>Only perform screen updates during vertical blanking period</_long>
+-		<default>true</default>
++		<default>false</default>
+ 	    </option>
+ 	    <option name="texture_compression" type="bool">
+ 		<_short>Texture Compression</_short>
+--- compiz-0.9.7.6.orig/plugins/opengl/CMakeLists.txt
++++ compiz-0.9.7.6/plugins/opengl/CMakeLists.txt
+@@ -2,7 +2,12 @@ find_package (Compiz REQUIRED)
+ 
+ include (CompizPlugin)
+ 
+-find_package (OpenGL)
+-if (OPENGL_FOUND)
+-    compiz_plugin(opengl PLUGINDEPS composite LIBRARIES ${OPENGL_gl_LIBRARY} INCDIRS ${OPENGL_INCLUDE_DIR})
+-endif ()
+\ No newline at end of file
++if (USE_GLES)
++    compiz_plugin(opengl PLUGINDEPS composite CFLAGSADD "-DUSE_GLES -std=c++0x" LIBRARIES ${OPENGLES2_LIBRARIES} INCDIRS ${OPENGLES2_INCLUDE_DIR})
++else (USE_GLES)
++    find_package (OpenGL)
++    if (OPENGL_FOUND)
++	compiz_plugin(opengl PLUGINDEPS composite CFLAGSADD -std=c++0x LIBRARIES ${OPENGL_gl_LIBRARY} INCDIRS ${OPENGL_INCLUDE_DIR})
++    endif (OPENGL_FOUND)
++endif (USE_GLES)
++
+--- compiz-0.9.7.6.orig/plugins/opengl/src/screen.cpp
++++ compiz-0.9.7.6/plugins/opengl/src/screen.cpp
+@@ -1,4 +1,5 @@
+ /*
++ * Copyright © 2011 Linaro Ltd.
+  * Copyright © 2008 Dennis Kasprzyk
+  * Copyright © 2007 Novell, Inc.
+  *
+@@ -23,6 +24,7 @@
+  *
+  * Authors: Dennis Kasprzyk <onestone@xxxxxxxxxxxxxxxxx>
+  *          David Reveman <davidr@xxxxxxxxxx>
++ *          Travis Watkins <travis.watkins@xxxxxxxxxx>
+  */
+ 
+ #ifndef _GNU_SOURCE
+@@ -36,6 +38,18 @@
+ #include <math.h>
+ 
+ namespace GL {
++    #ifdef USE_GLES
++    EGLCreateImageKHRProc  createImage;
++    EGLDestroyImageKHRProc destroyImage;
++
++    GLEGLImageTargetTexture2DOESProc eglImageTargetTexture;
++
++    EGLPostSubBufferNVProc postSubBuffer = NULL;
++    #else
++
++    typedef int (*GLXSwapIntervalProc) (int interval);
++
++    GLXSwapIntervalProc      swapInterval = NULL;
+     GLXBindTexImageProc      bindTexImage = NULL;
+     GLXReleaseTexImageProc   releaseTexImage = NULL;
+     GLXQueryDrawableProc     queryDrawable = NULL;
+@@ -47,18 +61,17 @@ namespace GL {
+     GLXGetFBConfigAttribProc getFBConfigAttrib = NULL;
+     GLXCreatePixmapProc      createPixmap = NULL;
+     GLXDestroyPixmapProc     destroyPixmap = NULL;
+-
+-    GLActiveTextureProc       activeTexture = NULL;
+-    GLClientActiveTextureProc clientActiveTexture = NULL;
+-    GLMultiTexCoord2fProc     multiTexCoord2f = NULL;
+-
+     GLGenProgramsProc	     genPrograms = NULL;
+     GLDeleteProgramsProc     deletePrograms = NULL;
+     GLBindProgramProc	     bindProgram = NULL;
+     GLProgramStringProc	     programString = NULL;
+     GLProgramParameter4fProc programEnvParameter4f = NULL;
+     GLProgramParameter4fProc programLocalParameter4f = NULL;
+-    GLGetProgramivProc       getProgramiv = NULL;
++    #endif
++
++    GLActiveTextureProc       activeTexture = NULL;
++    GLClientActiveTextureProc clientActiveTexture = NULL;
++    GLMultiTexCoord2fProc     multiTexCoord2f = NULL;
+ 
+     GLGenFramebuffersProc        genFramebuffers = NULL;
+     GLDeleteFramebuffersProc     deleteFramebuffers = NULL;
+@@ -67,16 +80,54 @@ namespace GL {
+     GLFramebufferTexture2DProc   framebufferTexture2D = NULL;
+     GLGenerateMipmapProc         generateMipmap = NULL;
+ 
++    GLBindBufferProc    bindBuffer = NULL;
++    GLDeleteBuffersProc deleteBuffers = NULL;
++    GLGenBuffersProc    genBuffers = NULL;
++    GLBufferDataProc    bufferData = NULL;
++    GLBufferSubDataProc bufferSubData = NULL;
++
++    GLGetShaderivProc        getShaderiv = NULL;
++    GLGetShaderInfoLogProc   getShaderInfoLog = NULL;
++    GLGetProgramivProc       getProgramiv = NULL;
++    GLGetProgramInfoLogProc  getProgramInfoLog = NULL;
++    GLCreateShaderProc       createShader = NULL;
++    GLShaderSourceProc       shaderSource = NULL;
++    GLCompileShaderProc      compileShader = NULL;
++    GLCreateProgramProc      createProgram = NULL;
++    GLAttachShaderProc       attachShader = NULL;
++    GLLinkProgramProc        linkProgram = NULL;
++    GLValidateProgramProc    validateProgram = NULL;
++    GLDeleteShaderProc       deleteShader = NULL;
++    GLDeleteProgramProc      deleteProgram = NULL;
++    GLUseProgramProc         useProgram = NULL;
++    GLGetUniformLocationProc getUniformLocation = NULL;
++    GLUniform1fProc          uniform1f = NULL;
++    GLUniform1iProc          uniform1i = NULL;
++    GLUniform2fProc          uniform2f = NULL;
++    GLUniform2iProc          uniform2i = NULL;
++    GLUniform3fProc          uniform3f = NULL;
++    GLUniform3iProc          uniform3i = NULL;
++    GLUniform4fProc          uniform4f = NULL;
++    GLUniform4iProc          uniform4i = NULL;
++    GLUniformMatrix4fvProc   uniformMatrix4fv = NULL;
++    GLGetAttribLocationProc  getAttribLocation = NULL;
++
++    GLEnableVertexAttribArrayProc  enableVertexAttribArray = NULL;
++    GLDisableVertexAttribArrayProc disableVertexAttribArray = NULL;
++    GLVertexAttribPointerProc      vertexAttribPointer = NULL;
++
+     bool  textureFromPixmap = true;
+     bool  textureRectangle = false;
+     bool  textureNonPowerOfTwo = false;
++    bool  textureNonPowerOfTwoMipmap = false;
+     bool  textureEnvCombine = false;
+     bool  textureEnvCrossbar = false;
+     bool  textureBorderClamp = false;
+     bool  textureCompression = false;
+     GLint maxTextureSize = 0;
+     bool  fbo = false;
+-    bool  fragmentProgram = false;
++    bool  vbo = false;
++    bool  shaders = false;
+     GLint maxTextureUnits = 1;
+ 
+     bool canDoSaturated = false;
+@@ -88,24 +139,234 @@ namespace GL {
+ 
+ CompOutput *targetOutput = NULL;
+ 
+-class DetectionWorkaround
++/**
++ * Callback object to create GLPrograms automatically when using GLVertexBuffer.
++ */
++class GLScreenAutoProgram : public GLVertexBuffer::AutoProgram
+ {
+-    public:
++public:
++    GLScreenAutoProgram (GLScreen *gScreen) : gScreen(gScreen) {}
+ 
+-        DetectionWorkaround ()
+-        {
+-            program_invocation_short_name[0] = 'C';
+-        }
+-        ~DetectionWorkaround ()
+-        {
+-            program_invocation_short_name[0] = 'c';
+-        }
++    GLProgram *getProgram (GLShaderParameters &params)
++    {
++        const GLShaderData *shaderData = gScreen->getShaderData (params);
++        std::list<const GLShaderData *> tempShaders;
++        tempShaders.push_back (shaderData);
++        return gScreen->getProgram (tempShaders);
++    }
++
++    GLScreen *gScreen;
+ };
+ 
+ bool
+ GLScreen::glInitContext (XVisualInfo *visinfo)
+ {
+-    DetectionWorkaround workaround;
++    #ifdef USE_GLES
++    Display             *xdpy;
++    Window               overlay;
++    EGLDisplay           dpy;
++    EGLConfig            config;
++    EGLint               major, minor;
++    const char		*eglExtensions, *glExtensions;
++    XWindowAttributes    attr;
++    EGLint               count, visualid;
++    EGLConfig            configs[1024];
++    CompOption::Vector   o (0);
++
++    const EGLint config_attribs[] = {
++	EGL_SURFACE_TYPE,         EGL_WINDOW_BIT,
++	EGL_RED_SIZE,             1,
++	EGL_GREEN_SIZE,           1,
++	EGL_BLUE_SIZE,            1,
++	EGL_ALPHA_SIZE,           0,
++	EGL_RENDERABLE_TYPE,      EGL_OPENGL_ES2_BIT,
++	EGL_CONFIG_CAVEAT,        EGL_NONE,
++	EGL_NONE,
++    };
++
++    const EGLint context_attribs[] = {
++        EGL_CONTEXT_CLIENT_VERSION, 2,
++        EGL_NONE
++    };
++
++    xdpy = screen->dpy ();
++    dpy = eglGetDisplay ((EGLNativeDisplayType)xdpy);
++    if (!eglInitialize (dpy, &major, &minor))
++    {
++	screen->handleCompizEvent ("opengl", "fatal_fallback", o);
++	return false;
++    }
++
++    eglBindAPI (EGL_OPENGL_ES_API);
++
++    if (!eglChooseConfig (dpy, config_attribs, configs, 1024, &count))
++    {
++	screen->handleCompizEvent ("opengl", "fatal_fallback", o);
++	return false;
++    }
++
++    if (!XGetWindowAttributes (xdpy, screen->root (), &attr))
++    {
++	screen->handleCompizEvent ("opengl", "fatal_fallback", o);
++	return false;
++    }
++
++    visualid = XVisualIDFromVisual (attr.visual);
++    config = configs[0];
++    for (int i = 0; i < count; i++) {
++        EGLint val;
++        eglGetConfigAttrib (dpy, configs[i], EGL_NATIVE_VISUAL_ID, &val);
++        if (visualid == val) {
++            config = configs[i];
++            break;
++        }
++    }
++
++    overlay = CompositeScreen::get (screen)->overlay ();
++    priv->surface = eglCreateWindowSurface (dpy, config, overlay, 0);
++    if (priv->surface == EGL_NO_SURFACE)
++    {
++	compLogMessage ("opengl", CompLogLevelFatal,
++	                "eglCreateWindowSurface failed");
++	screen->handleCompizEvent ("opengl", "fatal_fallback", o);
++	return false;
++    }
++
++    // Currently we rely unconditionally on preserving the buffer contents.
++    eglSurfaceAttrib (dpy, priv->surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED);
++
++    priv->ctx = eglCreateContext (dpy, config, EGL_NO_CONTEXT, context_attribs);
++    if (priv->ctx == EGL_NO_CONTEXT)
++    {
++	compLogMessage ("opengl", CompLogLevelFatal, "eglCreateContext failed");
++	screen->handleCompizEvent ("opengl", "fatal_fallback", o);
++	return false;
++    }
++
++    if (!eglMakeCurrent (dpy, priv->surface, priv->surface, priv->ctx))
++    {
++	compLogMessage ("opengl", CompLogLevelFatal,
++	                "eglMakeCurrent failed");
++	screen->handleCompizEvent ("opengl", "fatal_fallback", o);
++	return false;
++    }
++
++    eglExtensions = (const char *) eglQueryString (dpy, EGL_EXTENSIONS);
++    glExtensions = (const char *) glGetString (GL_EXTENSIONS);
++
++    if (!glExtensions || !eglExtensions)
++    {
++	compLogMessage ("opengl", CompLogLevelFatal,
++			"No valid GL extensions string found.");
++	screen->handleCompizEvent ("opengl", "fatal_fallback", o);
++	return false;
++    }
++
++    GL::textureFromPixmap = true;
++    GL::textureNonPowerOfTwo = true;
++    GL::fbo = true;
++    GL::vbo = true;
++    GL::shaders = true;
++    GL::maxTextureUnits = 4;
++    glGetIntegerv (GL_MAX_TEXTURE_SIZE, &GL::maxTextureSize);
++
++    GL::createImage = (GL::EGLCreateImageKHRProc)
++	eglGetProcAddress ("eglCreateImageKHR");
++    GL::destroyImage = (GL::EGLDestroyImageKHRProc)
++	eglGetProcAddress ("eglDestroyImageKHR");
++    GL::eglImageTargetTexture = (GL::GLEGLImageTargetTexture2DOESProc)
++	eglGetProcAddress ("glEGLImageTargetTexture2DOES");
++
++    if (!strstr (eglExtensions, "EGL_KHR_image_pixmap") ||
++        !strstr (glExtensions, "GL_OES_EGL_image") ||
++	!GL::createImage || !GL::destroyImage || !GL::eglImageTargetTexture)
++    {
++	compLogMessage ("opengl", CompLogLevelFatal,
++			"GL_OES_EGL_image is missing");
++	screen->handleCompizEvent ("opengl", "fatal_fallback", o);
++	return false;
++    }
++
++// work around efika supporting GL_BGRA directly instead of via this extension
++#ifndef GL_BGRA
++    if (!strstr (glExtensions, "GL_EXT_texture_format_BGRA8888"))
++    {
++	compLogMessage ("opengl", CompLogLevelFatal,
++			"GL_EXT_texture_format_BGRA8888 is missing");
++	screen->handleCompizEvent ("opengl", "fatal_fallback", o);
++	return false;
++    }
++#endif
++
++    if (strstr (glExtensions, "GL_OES_texture_npot"))
++	GL::textureNonPowerOfTwoMipmap = true;
++
++    if (strstr (eglExtensions, "EGL_NV_post_sub_buffer"))
++	GL::postSubBuffer = (GL::EGLPostSubBufferNVProc)
++	    eglGetProcAddress ("eglPostSubBufferNV");
++
++    GL::activeTexture = glActiveTexture;
++    GL::genFramebuffers = glGenFramebuffers;
++    GL::deleteFramebuffers = glDeleteFramebuffers;
++    GL::bindFramebuffer = glBindFramebuffer;
++    GL::checkFramebufferStatus = glCheckFramebufferStatus;
++    GL::framebufferTexture2D = glFramebufferTexture2D;
++    GL::generateMipmap = glGenerateMipmap;
++
++    GL::bindBuffer = glBindBuffer;
++    GL::deleteBuffers = glDeleteBuffers;
++    GL::genBuffers = glGenBuffers;
++    GL::bufferData = glBufferData;
++    GL::bufferSubData = glBufferSubData;
++
++    GL::getShaderiv = glGetShaderiv;
++    GL::getShaderInfoLog = glGetShaderInfoLog;
++    GL::getProgramiv = glGetProgramiv;
++    GL::getProgramInfoLog = glGetProgramInfoLog;
++    GL::createShader = glCreateShader;
++    GL::shaderSource = glShaderSource;
++    GL::compileShader = glCompileShader;
++    GL::createProgram = glCreateProgram;
++    GL::attachShader = glAttachShader;
++    GL::linkProgram = glLinkProgram;
++    GL::validateProgram = glValidateProgram;
++    GL::deleteShader = glDeleteShader;
++    GL::deleteProgram = glDeleteProgram;
++    GL::useProgram = glUseProgram;
++    GL::getUniformLocation = glGetUniformLocation;
++    GL::uniform1f = glUniform1f;
++    GL::uniform1i = glUniform1i;
++    GL::uniform2f = glUniform2f;
++    GL::uniform2i = glUniform2i;
++    GL::uniform3f = glUniform3f;
++    GL::uniform3i = glUniform3i;
++    GL::uniform4f = glUniform4f;
++    GL::uniform4i = glUniform4i;
++    GL::uniformMatrix4fv = glUniformMatrix4fv;
++    GL::getAttribLocation = glGetAttribLocation;
++
++    GL::enableVertexAttribArray = glEnableVertexAttribArray;
++    GL::disableVertexAttribArray = glDisableVertexAttribArray;
++    GL::vertexAttribPointer = glVertexAttribPointer;
++
++    glClearColor (0.0, 0.0, 0.0, 1.0);
++    glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
++    glEnable (GL_BLEND);
++    glEnable (GL_CULL_FACE);
++
++    priv->updateView ();
++
++    priv->lighting = false;
++
++    priv->filter[NOTHING_TRANS_FILTER] = GLTexture::Fast;
++    priv->filter[SCREEN_TRANS_FILTER]  = GLTexture::Good;
++    priv->filter[WINDOW_TRANS_FILTER]  = GLTexture::Good;
++
++    if (GL::textureFromPixmap)
++	registerBindPixmap (EglTexture::bindPixmapToTexture);
++
++    #else
++
+     Display		 *dpy = screen->dpy ();
+     const char		 *glExtensions;
+     GLfloat		 globalAmbient[]  = { 0.1f, 0.1f,  0.1f, 0.1f };
+@@ -165,6 +426,7 @@ GLScreen::glInitContext (XVisualInfo *vi
+ 
+     if (strstr (glExtensions, "GL_ARB_texture_non_power_of_two"))
+ 	GL::textureNonPowerOfTwo = true;
++    GL::textureNonPowerOfTwoMipmap = GL::textureNonPowerOfTwo;
+ 
+     glGetIntegerv (GL_MAX_TEXTURE_SIZE, &GL::maxTextureSize);
+ 
+@@ -221,33 +483,6 @@ GLScreen::glInitContext (XVisualInfo *vi
+ 	    glGetIntegerv (GL_MAX_TEXTURE_UNITS_ARB, &GL::maxTextureUnits);
+     }
+ 
+-    if (strstr (glExtensions, "GL_ARB_fragment_program"))
+-    {
+-	GL::genPrograms = (GL::GLGenProgramsProc)
+-	    getProcAddress ("glGenProgramsARB");
+-	GL::deletePrograms = (GL::GLDeleteProgramsProc)
+-	    getProcAddress ("glDeleteProgramsARB");
+-	GL::bindProgram = (GL::GLBindProgramProc)
+-	    getProcAddress ("glBindProgramARB");
+-	GL::programString = (GL::GLProgramStringProc)
+-	    getProcAddress ("glProgramStringARB");
+-	GL::programEnvParameter4f = (GL::GLProgramParameter4fProc)
+-	    getProcAddress ("glProgramEnvParameter4fARB");
+-	GL::programLocalParameter4f = (GL::GLProgramParameter4fProc)
+-	    getProcAddress ("glProgramLocalParameter4fARB");
+-	GL::getProgramiv = (GL::GLGetProgramivProc)
+-	    getProcAddress ("glGetProgramivARB");
+-
+-	if (GL::genPrograms             &&
+-	    GL::deletePrograms          &&
+-	    GL::bindProgram             &&
+-	    GL::programString           &&
+-	    GL::programEnvParameter4f   &&
+-	    GL::programLocalParameter4f &&
+-	    GL::getProgramiv)
+-	    GL::fragmentProgram = true;
+-    }
+-
+     if (strstr (glExtensions, "GL_EXT_framebuffer_object"))
+     {
+ 	GL::genFramebuffers = (GL::GLGenFramebuffersProc)
+@@ -272,6 +507,63 @@ GLScreen::glInitContext (XVisualInfo *vi
+ 	    GL::fbo = true;
+     }
+ 
++    if (strstr (glExtensions, "GL_ARB_vertex_buffer_object"))
++    {
++	GL::bindBuffer = (GL::GLBindBufferProc)
++	    getProcAddress ("glBindBufferARB");
++	GL::deleteBuffers = (GL::GLDeleteBuffersProc)
++	    getProcAddress ("glDeleteBuffersARB");
++	GL::genBuffers = (GL::GLGenBuffersProc)
++	    getProcAddress ("glGenBuffersARB");
++	GL::bufferData = (GL::GLBufferDataProc)
++	    getProcAddress ("glBufferDataARB");
++	GL::bufferSubData = (GL::GLBufferSubDataProc)
++	    getProcAddress ("glBufferSubDataARB");
++
++	if (GL::bindBuffer    &&
++	    GL::deleteBuffers &&
++	    GL::genBuffers    &&
++	    GL::bufferData    &&
++	    GL::bufferSubData)
++	    GL::vbo = true;
++    }
++
++    if (strstr (glExtensions, "GL_ARB_fragment_shader") &&
++        strstr (glExtensions, "GL_ARB_vertex_shader"))
++    {
++	GL::getShaderiv = (GL::GLGetShaderivProc) getProcAddress ("glGetShaderiv");
++	GL::getShaderInfoLog = (GL::GLGetShaderInfoLogProc) getProcAddress ("glGetShaderInfoLog");
++	GL::getProgramiv = (GL::GLGetProgramivProc) getProcAddress ("glGetProgramiv");
++	GL::getProgramInfoLog = (GL::GLGetProgramInfoLogProc) getProcAddress ("glGetProgramInfoLog");
++	GL::createShader = (GL::GLCreateShaderProc) getProcAddress ("glCreateShader");
++	GL::shaderSource = (GL::GLShaderSourceProc) getProcAddress ("glShaderSource");
++	GL::compileShader = (GL::GLCompileShaderProc) getProcAddress ("glCompileShader");
++	GL::createProgram = (GL::GLCreateProgramProc) getProcAddress ("glCreateProgram");
++	GL::attachShader = (GL::GLAttachShaderProc) getProcAddress ("glAttachShader");
++	GL::linkProgram = (GL::GLLinkProgramProc) getProcAddress ("glLinkProgram");
++	GL::validateProgram = (GL::GLValidateProgramProc) getProcAddress ("glValidateProgram");
++	GL::deleteShader = (GL::GLDeleteShaderProc) getProcAddress ("glDeleteShader");
++	GL::deleteProgram = (GL::GLDeleteProgramProc) getProcAddress ("glDeleteProgram");
++	GL::useProgram = (GL::GLUseProgramProc) getProcAddress ("glUseProgram");
++	GL::getUniformLocation = (GL::GLGetUniformLocationProc) getProcAddress ("glGetUniformLocation");
++	GL::uniform1f = (GL::GLUniform1fProc) getProcAddress ("glUniform1f");
++	GL::uniform1i = (GL::GLUniform1iProc) getProcAddress ("glUniform1i");
++	GL::uniform2f = (GL::GLUniform2fProc) getProcAddress ("glUniform2f");
++	GL::uniform2i = (GL::GLUniform2iProc) getProcAddress ("glUniform2i");
++	GL::uniform3f = (GL::GLUniform3fProc) getProcAddress ("glUniform3f");
++	GL::uniform3i = (GL::GLUniform3iProc) getProcAddress ("glUniform3i");
++	GL::uniform4f = (GL::GLUniform4fProc) getProcAddress ("glUniform4f");
++	GL::uniform4i = (GL::GLUniform4iProc) getProcAddress ("glUniform4i");
++	GL::uniformMatrix4fv = (GL::GLUniformMatrix4fvProc) getProcAddress ("glUniformMatrix4fv");
++	GL::getAttribLocation = (GL::GLGetAttribLocationProc) getProcAddress ("glGetAttribLocation");
++
++	GL::enableVertexAttribArray = (GL::GLEnableVertexAttribArrayProc) getProcAddress ("glEnableVertexAttribArray");
++	GL::disableVertexAttribArray = (GL::GLDisableVertexAttribArrayProc) getProcAddress ("glDisableVertexAttribArray");
++	GL::vertexAttribPointer = (GL::GLVertexAttribPointerProc) getProcAddress ("glVertexAttribPointer");
++
++	GL::shaders = true;
++    }
++
+     if (strstr (glExtensions, "GL_ARB_texture_compression"))
+ 	GL::textureCompression = true;
+ 
+@@ -313,6 +605,12 @@ GLScreen::glInitContext (XVisualInfo *vi
+ 
+     if (GL::textureFromPixmap)
+ 	registerBindPixmap (TfpTexture::bindPixmapToTexture);
++#endif
++
++    priv->scratchFbo = new GLFramebufferObject;
++    priv->scratchFbo->allocate (*screen, NULL, GL_BGRA);
++
++    GLVertexBuffer::streamingBuffer ()->setAutoProgram (priv->autoProgram);
+ 
+     return true;
+ }
+@@ -322,14 +620,14 @@ GLScreen::GLScreen (CompScreen *s) :
+     PluginClassHandler<GLScreen, CompScreen, COMPIZ_OPENGL_ABI> (s),
+     priv (new PrivateGLScreen (this))
+ {
++    XVisualInfo		 *visinfo = NULL;
++#ifndef USE_GLES
+     Display		 *dpy = s->dpy ();
+     XVisualInfo		 templ;
+-    XVisualInfo		 *visinfo;
+     GLXFBConfig		 *fbConfigs;
+     int			 defaultDepth, nvisinfo, nElements, value, i;
+     const char		 *glxExtensions;
+     XWindowAttributes    attr;
+-    DetectionWorkaround workaround;
+     CompOption::Vector o (0);
+ 
+     if (!XGetWindowAttributes (dpy, s->root (), &attr))
+@@ -574,6 +872,7 @@ GLScreen::GLScreen (CompScreen *s) :
+ 	setFailed ();
+     }
+ 
++#endif
+     if (!glInitContext (visinfo))
+ 	setFailed ();
+ }
+@@ -582,7 +881,22 @@ GLScreen::~GLScreen ()
+ {
+     if (priv->hasCompositing)
+ 	CompositeScreen::get (screen)->unregisterPaintHandler ();
++
++    #ifdef USE_GLES
++    Display *xdpy = screen->dpy ();
++    EGLDisplay dpy = eglGetDisplay (xdpy);
++
++    eglMakeCurrent (dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
++    eglDestroyContext (dpy, priv->ctx);
++    eglDestroySurface (dpy, priv->surface);
++    eglTerminate (dpy);
++    eglReleaseThread ();
++    #else
++
+     glXDestroyContext (screen->dpy (), priv->ctx);
++    #endif
++
++    delete priv->scratchFbo;
+     delete priv;
+ }
+ 
+@@ -593,14 +907,21 @@ PrivateGLScreen::PrivateGLScreen (GLScre
+     backgroundTextures (),
+     backgroundLoaded (false),
+     rasterPos (0, 0),
+-    fragmentStorage (),
++    projection (NULL),
+     clearBuffers (true),
+     lighting (false),
++    #ifndef USE_GLES
+     getProcAddress (0),
++    #endif
++    scratchFbo (NULL),
+     outputRegion (),
+     pendingCommands (false),
++    lastMask (0),
+     bindPixmap (),
+     hasCompositing (false),
++    programCache (new GLProgramCache (30)),
++    shaderCache (),
++    autoProgram (new GLScreenAutoProgram(gs)),
+     rootPixmapCopy (None),
+     rootPixmapSize ()
+ {
+@@ -609,6 +930,8 @@ PrivateGLScreen::PrivateGLScreen (GLScre
+ 
+ PrivateGLScreen::~PrivateGLScreen ()
+ {
++    delete programCache;
++    delete autoProgram;
+     if (rootPixmapCopy)
+ 	XFreePixmap (screen->dpy (), rootPixmapCopy);
+ 
+@@ -670,8 +993,13 @@ PrivateGLScreen::handleEvent (XEvent *ev
+ 	    {
+ 		XDamageNotifyEvent *de = (XDamageNotifyEvent *) event;
+ 
++		#ifdef USE_GLES
++		std::map<Damage, EglTexture*>::iterator it =
++		    boundPixmapTex.find (de->damage);
++		#else
+ 		std::map<Damage, TfpTexture*>::iterator it =
+ 		    boundPixmapTex.find (de->damage);
++		#endif
+ 		if (it != boundPixmapTex.end ())
+ 		{
+ 		    it->second->damaged = true;
+@@ -743,22 +1071,32 @@ perspective (GLfloat *m,
+ void
+ PrivateGLScreen::updateView ()
+ {
++    GLfloat projection_array[16];
++
++    #ifndef USE_GLES
+     glMatrixMode (GL_PROJECTION);
+     glLoadIdentity ();
+     glMatrixMode (GL_MODELVIEW);
+     glLoadIdentity ();
+     glDepthRange (0, 1);
+-    glViewport (-1, -1, 2, 2);
+     glRasterPos2f (0, 0);
++    #endif
++    glViewport (-1, -1, 2, 2);
+ 
+     rasterPos = CompPoint (0, 0);
+ 
+-    perspective (projection, 60.0f, 1.0f, 0.1f, 100.0f);
++    perspective (projection_array, 60.0f, 1.0f, 0.1f, 100.0f);
++
++    if (projection != NULL)
++	delete projection;
++    projection = new GLMatrix (projection_array);
+ 
++    #ifndef USE_GLES
+     glMatrixMode (GL_PROJECTION);
+     glLoadIdentity ();
+-    glMultMatrixf (projection);
++    glMultMatrixf (projection_array);
+     glMatrixMode (GL_MODELVIEW);
++    #endif
+ 
+     CompRegion region (screen->region ());
+     /* remove all output regions from visible screen region */
+@@ -777,9 +1115,11 @@ PrivateGLScreen::outputChangeNotify ()
+ {
+     screen->outputChangeNotify ();
+ 
++    scratchFbo->allocate (*screen, NULL, GL_BGRA);
+     updateView ();
+ }
+ 
++#ifndef USE_GLES
+ GL::FuncPtr
+ GLScreen::getProcAddress (const char *name)
+ {
+@@ -805,6 +1145,7 @@ GLScreen::getProcAddress (const char *na
+ 
+     return funcPtr;
+ }
++#endif
+ 
+ void
+ PrivateGLScreen::updateScreenBackground ()
+@@ -922,32 +1263,23 @@ PrivateGLScreen::updateScreenBackground
+ 
+ 	XFreeGC(dpy, gc);
+     }
+-
+-    if (!backgroundTextures.empty ())
+-    {
+-	foreach (GLTexture *t, backgroundTextures)
+-	    if (t->target () == GL_TEXTURE_2D)
+-	    {
+-		glBindTexture (t->target (), t->name ());
+-		glTexParameteri (t->target (), GL_TEXTURE_WRAP_S, GL_REPEAT);
+-		glTexParameteri (t->target (), GL_TEXTURE_WRAP_T, GL_REPEAT);
+-		glBindTexture (t->target (), 0);
+-	    }
+-    }
+ }
+ 
+ void
+ GLScreen::setTexEnvMode (GLenum mode)
+ {
++    #ifndef USE_GLES
+     if (priv->lighting)
+ 	glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+     else
+ 	glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, mode);
++    #endif
+ }
+ 
+ void
+ GLScreen::setLighting (bool lighting)
+ {
++    #ifndef USE_GLES
+     if (priv->lighting != lighting)
+     {
+ 	if (!priv->optionGetLighting ())
+@@ -968,6 +1300,7 @@ GLScreen::setLighting (bool lighting)
+ 
+ 	setTexEnvMode (GL_REPLACE);
+     }
++    #endif
+ }
+ 
+ bool
+@@ -1003,6 +1336,25 @@ void
+ GLScreenInterface::glDisableOutputClipping ()
+     WRAPABLE_DEF (glDisableOutputClipping)
+ 
++GLMatrix *
++GLScreenInterface::projectionMatrix ()
++    WRAPABLE_DEF (projectionMatrix)
++
++void
++GLScreenInterface::glPaintCompositedOutput (const CompRegion    &region,
++					    GLFramebufferObject *fbo,
++					    unsigned int         mask)
++    WRAPABLE_DEF (glPaintCompositedOutput, region, fbo, mask)
++
++
++GLMatrix *
++GLScreen::projectionMatrix ()
++{
++    WRAPABLE_HND_FUNCTN_RETURN (GLMatrix *, projectionMatrix)
++
++    return priv->projection;
++}
++
+ void
+ GLScreen::updateBackground ()
+ {
+@@ -1033,17 +1385,13 @@ GLScreen::setFilter (int num, GLTexture:
+     priv->filter[num] = filter;
+ }
+ 
+-GLFragment::Storage *
+-GLScreen::fragmentStorage ()
+-{
+-    return &priv->fragmentStorage;
+-}
+-
++#ifndef USE_GLES
+ GLFBConfig*
+ GLScreen::glxPixmapFBConfig (unsigned int depth)
+ {
+     return &priv->glxPixmapFBConfigs[depth];
+ }
++#endif
+ 
+ void
+ GLScreen::clearOutput (CompOutput   *output,
+@@ -1056,16 +1404,13 @@ GLScreen::clearOutput (CompOutput   *out
+ 	pBox->x2 != (int) screen->width () ||
+ 	pBox->y2 != (int) screen->height ())
+     {
+-	glPushAttrib (GL_SCISSOR_BIT);
+-
+ 	glEnable (GL_SCISSOR_TEST);
+ 	glScissor (pBox->x1,
+ 		   screen->height () - pBox->y2,
+ 		   pBox->x2 - pBox->x1,
+ 		   pBox->y2 - pBox->y1);
+ 	glClear (mask);
+-
+-	glPopAttrib ();
++	glDisable (GL_SCISSOR_TEST);
+     }
+     else
+     {
+@@ -1088,12 +1433,33 @@ GLScreen::setDefaultViewport ()
+ 		priv->lastViewport.height);
+ }
+ 
++#ifdef USE_GLES
++EGLContext
++GLScreen::getEGLContext ()
++{
++    return priv->ctx;
++}
++#endif
++
++GLProgram *
++GLScreen::getProgram (std::list<const GLShaderData*> shaders)
++{
++    return (*priv->programCache)(shaders);
++}
++
++const GLShaderData *
++GLScreen::getShaderData (GLShaderParameters &params)
++{
++    return &priv->shaderCache.getShaderData(params);
++}
++
+ namespace GL
+ {
+ 
+ void
+ waitForVideoSync ()
+ {
++#ifndef USE_GLES
+     GL::unthrottledFrames++;
+     if (GL::waitVideoSync)
+     {
+@@ -1118,11 +1484,13 @@ waitForVideoSync ()
+ 	if (GL::vsyncCount != oldCount)
+ 	    GL::unthrottledFrames = 0;
+     }
++#endif
+ }
+ 
+ void
+ controlSwapVideoSync (bool sync)
+ {
++#ifndef USE_GLES
+     // Docs: http://www.opengl.org/registry/specs/SGI/swap_control.txt
+     if (GL::swapInterval)
+     {
+@@ -1131,6 +1499,7 @@ controlSwapVideoSync (bool sync)
+     }
+     else if (sync)
+ 	waitForVideoSync ();
++#endif
+ }
+ 
+ } // namespace GL
+@@ -1149,6 +1518,35 @@ PrivateGLScreen::paintOutputs (CompOutpu
+ {
+     XRectangle r;
+ 
++    // Blending is disabled by default. Each operation/plugin
++    // should enable it (and reset it) as needed.
++    glDisable(GL_BLEND);
++
++    GLFramebufferObject *oldFbo = NULL;
++    bool useFbo = false;
++
++    oldFbo = scratchFbo->bind ();
++    useFbo = scratchFbo->checkStatus () && scratchFbo->tex ();
++    if (!useFbo) {
++printf ("bailing!");
++	GLFramebufferObject::rebind (oldFbo);
++    }
++
++    refreshSubBuffer = ((lastMask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) &&
++                        !(mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) &&
++                        (mask & COMPOSITE_SCREEN_DAMAGE_REGION_MASK));
++
++    if (refreshSubBuffer)
++    {
++	// FIXME: We shouldn't have to substract a 1X1 pixel region here !!
++	// This is an ugly workaround for what appears to be a bug in the SGX
++	// X11 driver (e.g. on Pandaboard OMAP4 platform).
++	// Posting a fullscreen damage region to the SGX seems to reset the
++	// framebuffer, causing the screen to blackout.
++	cScreen->damageRegion (CompRegion (screen->fullscreenOutput ()) -
++                               CompRegion (CompRect(0, 0, 1, 1)));
++    }
++
+     if (clearBuffers)
+     {
+ 	if (mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK)
+@@ -1175,7 +1573,11 @@ PrivateGLScreen::paintOutputs (CompOutpu
+ 	    lastViewport = r;
+ 	}
+ 
++#ifdef USE_GLES
++	if (mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK || !GL::postSubBuffer)
++#else
+ 	if (mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK)
++#endif
+ 	{
+ 	    GLMatrix identity;
+ 
+@@ -1189,6 +1591,9 @@ PrivateGLScreen::paintOutputs (CompOutpu
+ 	{
+ 	    GLMatrix identity;
+ 
++	    if (refreshSubBuffer)
++		tmpRegion = CompRegion (*output);
++
+ 	    outputRegion = tmpRegion & CompRegion (*output);
+ 
+ 	    if (!gScreen->glPaintOutput (defaultScreenPaintAttrib,
+@@ -1204,15 +1609,38 @@ PrivateGLScreen::paintOutputs (CompOutpu
+ 					PAINT_SCREEN_FULL_MASK);
+ 
+ 		tmpRegion += *output;
+-
+ 	    }
+ 	}
+     }
+ 
+     targetOutput = &screen->outputDevs ()[0];
++    glFlush ();
+ 
+-    if (mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK)
++    if (useFbo)
+     {
++	GLFramebufferObject::rebind (oldFbo);
++
++	// FIXME: does not work if screen dimensions exceed max texture size
++	gScreen->glPaintCompositedOutput (tmpRegion, scratchFbo, mask);
++    }
++
++    // FIXME: Actually fix the composite plugin to be more efficient;
++    // If GL::swapInterval == NULL && GL::waitVideoSync != NULL then the
++    // composite plugin should not be imposing any framerate restriction
++    // (ie. blocking the CPU) at all. Because the framerate will be controlled
++    // and optimized here:
++#ifdef USE_GLES
++    if (mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK || !GL::postSubBuffer)
++#else
++    if (mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK)
++#endif
++     {
++	#ifdef USE_GLES
++	Display *xdpy = screen->dpy ();
++	eglSwapBuffers (eglGetDisplay (xdpy), surface);
++	eglWaitGL ();
++	XFlush (xdpy);
++	#else
+ 	/*
+ 	 * controlSwapVideoSync is much faster than waitForVideoSync because
+ 	 * it won't block the CPU. The waiting is offloaded to the GPU.
+@@ -1220,6 +1648,7 @@ PrivateGLScreen::paintOutputs (CompOutpu
+ 	 */
+ 	GL::controlSwapVideoSync (optionGetSyncToVblank ());
+ 	glXSwapBuffers (screen->dpy (), cScreen->output ());
++	#endif
+     }
+     else
+     {
+@@ -1229,6 +1658,31 @@ PrivateGLScreen::paintOutputs (CompOutpu
+ 
+ 	waitForVideoSync ();
+ 
++	#ifdef USE_GLES
++	Display *xdpy = screen->dpy ();
++
++	if (GL::postSubBuffer)
++	{
++	    while (nBox--)
++	    {
++		y = screen->height () - pBox->y2;
++
++		(*GL::postSubBuffer) (eglGetDisplay (xdpy), surface,
++				      pBox->x1, y,
++				      pBox->x2 - pBox->x1,
++				      pBox->y2 - pBox->y1);
++		pBox++;
++	    }
++	}
++	else
++	{
++	    eglSwapBuffers (eglGetDisplay (xdpy), surface);
++	}
++
++	eglWaitGL ();
++	XFlush (xdpy);
++
++	#else
+ 	if (GL::copySubBuffer)
+ 	{
+ 	    while (nBox--)
+@@ -1275,14 +1729,21 @@ PrivateGLScreen::paintOutputs (CompOutpu
+ 	    glDisable (GL_SCISSOR_TEST);
+ 	    glFlush ();
+ 	}
++	#endif
+     }
++
++    lastMask = mask;
+ }
+ 
+ bool
+ PrivateGLScreen::hasVSync ()
+ {
++   #ifdef USE_GLES
++   return false;
++   #else
+     return GL::waitVideoSync && optionGetSyncToVblank () && 
+            GL::unthrottledFrames < 5;
++   #endif
+ }
+ 
+ bool
+@@ -1327,6 +1788,12 @@ GLScreen::unregisterBindPixmap (GLTextur
+     }
+ }
+ 
++GLFramebufferObject *
++GLScreen::fbo ()
++{
++    return priv->scratchFbo;
++}
++
+ GLTexture *
+ GLScreen::defaultIcon ()
+ {
+@@ -1359,13 +1826,10 @@ GLScreen::defaultIcon ()
+ void
+ GLScreen::resetRasterPos ()
+ {
++    #ifndef USE_GLES
+     glRasterPos2f (0, 0);
++    #endif
+     priv->rasterPos.setX (0);
+     priv->rasterPos.setY (0);
+ }
+ 
+-const float *
+-GLScreen::projectionMatrix ()
+-{
+-    return priv->projection;
+-}
+--- /dev/null
++++ compiz-0.9.7.6/plugins/opengl/src/program.cpp
+@@ -0,0 +1,262 @@
++/*
++ * Copyright © 2011 Linaro Ltd.
++ *
++ * Permission to use, copy, modify, distribute, and sell this software
++ * and its documentation for any purpose is hereby granted without
++ * fee, provided that the above copyright notice appear in all copies
++ * and that both that copyright notice and this permission notice
++ * appear in supporting documentation, and that the name of
++ * Linaro Ltd. not be used in advertising or publicity pertaining to
++ * distribution of the software without specific, written prior permission.
++ * Linaro Ltd. makes no representations about the suitability of this
++ * software for any purpose. It is provided "as is" without express or
++ * implied warranty.
++ *
++ * LINARO LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
++ * NO EVENT SHALL LINARO LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
++ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
++ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
++ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
++ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ *
++ * Authors: Travis Watkins <travis.watkins@xxxxxxxxxx>
++ */
++
++#include <iostream>
++#include <fstream>
++#include <opengl/opengl.h>
++
++class PrivateProgram
++{
++    public:
++	GLuint program;
++	bool valid;
++};
++
++
++void printShaderInfoLog (GLuint shader)
++{
++    GLint   length = 0;
++    GLint   chars  = 0;
++    GLchar *infoLog;
++
++    (*GL::getShaderiv) (shader, GL_INFO_LOG_LENGTH, &length);
++
++    if (length > 0)
++    {
++	infoLog = new GLchar[length];
++	(*GL::getShaderInfoLog) (shader, length, &chars, infoLog);
++	std::cout << infoLog << std::endl;
++	delete[] infoLog;
++    }
++}
++
++void printProgramInfoLog(GLuint program)
++{
++    GLint   length = 0;
++    GLint   chars  = 0;
++    GLchar *infoLog;
++
++    (*GL::getProgramiv) (program, GL_INFO_LOG_LENGTH, &length);
++
++    if (length > 0)
++    {
++	infoLog = new GLchar[length];
++	(*GL::getProgramInfoLog) (program, length, &chars, infoLog);
++	std::cout << infoLog << std::endl;
++	delete[] infoLog;
++    }
++}
++
++static bool compileShader (GLuint *shader, GLenum type, CompString &source)
++{
++    const GLchar *data;
++    GLint         status;
++
++    data = (GLchar *)source.c_str ();
++
++    *shader = (*GL::createShader) (type);
++    (*GL::shaderSource) (*shader, 1, &data, NULL);
++    (*GL::compileShader) (*shader);
++
++    (*GL::getShaderiv) (*shader, GL_COMPILE_STATUS, &status);
++    return (status == GL_TRUE);
++}
++
++GLProgram::GLProgram (CompString &vertexShader, CompString &fragmentShader) :
++    priv (new PrivateProgram ())
++{
++    GLuint vertex, fragment;
++    GLint status;
++
++    priv->valid = false;
++    priv->program = (*GL::createProgram) ();
++
++    if (!compileShader (&vertex, GL_VERTEX_SHADER, vertexShader))
++    {
++	printShaderInfoLog (vertex);
++	std::cout << vertexShader << std::endl << std::endl;
++	return;
++    }
++
++    if (!compileShader (&fragment, GL_FRAGMENT_SHADER, fragmentShader))
++    {
++	printShaderInfoLog (fragment);
++	std::cout << fragmentShader << std::endl << std::endl;
++	return;
++    }
++
++    (*GL::attachShader) (priv->program, vertex);
++    (*GL::attachShader) (priv->program, fragment);
++
++    (*GL::linkProgram) (priv->program);
++    (*GL::validateProgram) (priv->program);
++
++    (*GL::getProgramiv) (priv->program, GL_LINK_STATUS, &status);
++    if (status == GL_FALSE)
++    {
++	printProgramInfoLog (priv->program);
++	return;
++    }
++
++    (*GL::deleteShader) (vertex);
++    (*GL::deleteShader) (fragment);
++
++    priv->valid = true;
++}
++
++GLProgram::~GLProgram ()
++{
++    (*GL::deleteProgram) (priv->program);
++    delete priv;
++}
++
++bool GLProgram::valid ()
++{
++    return priv->valid;
++}
++
++void GLProgram::bind ()
++{
++    (*GL::useProgram) (priv->program);
++}
++
++void GLProgram::unbind ()
++{
++    (*GL::useProgram) (0);
++}
++
++bool GLProgram::setUniform (const char *name, GLfloat value)
++{
++    GLint location = (*GL::getUniformLocation) (priv->program, name);
++    if (location == -1)
++	return false;
++
++    (*GL::uniform1f) (location, value);
++    return true;
++}
++
++bool GLProgram::setUniform (const char *name, GLint value)
++{
++    GLint location = (*GL::getUniformLocation) (priv->program, name);
++    if (location == -1)
++	return false;
++
++    (*GL::uniform1i) (location, value);
++    return true;
++}
++
++bool GLProgram::setUniform (const char *name, const GLMatrix &value)
++{
++    GLint location = (*GL::getUniformLocation) (priv->program, name);
++    if (location == -1)
++	return false;
++
++    (*GL::uniformMatrix4fv) (location, 1, GL_FALSE, value.getMatrix ());
++    return true;
++}
++
++bool GLProgram::setUniform2f (const char *name,
++                              GLfloat x,
++                              GLfloat y)
++{
++    GLint location = (*GL::getUniformLocation) (priv->program, name);
++    if (location == -1)
++	return false;
++
++    (*GL::uniform2f) (location, x, y);
++    return true;
++}
++
++bool GLProgram::setUniform3f (const char *name,
++                              GLfloat x,
++                              GLfloat y,
++                              GLfloat z)
++{
++    GLint location = (*GL::getUniformLocation) (priv->program, name);
++    if (location == -1)
++	return false;
++
++    (*GL::uniform3f) (location, x, y, z);
++    return true;
++}
++
++bool GLProgram::setUniform4f (const char *name,
++                              GLfloat x,
++                              GLfloat y,
++                              GLfloat z,
++                              GLfloat w)
++{
++    GLint location = (*GL::getUniformLocation) (priv->program, name);
++    if (location == -1)
++	return false;
++
++    (*GL::uniform4f) (location, x, y, z, w);
++    return true;
++}
++
++bool GLProgram::setUniform2i (const char *name,
++                              GLint x,
++                              GLint y)
++{
++    GLint location = (*GL::getUniformLocation) (priv->program, name);
++    if (location == -1)
++	return false;
++
++    (*GL::uniform2i) (location, x, y);
++    return true;
++}
++
++bool GLProgram::setUniform3i (const char *name,
++                              GLint x,
++                              GLint y,
++                              GLint z)
++{
++    GLint location = (*GL::getUniformLocation) (priv->program, name);
++    if (location == -1)
++	return false;
++
++    (*GL::uniform3i) (location, x, y, z);
++    return true;
++}
++
++bool GLProgram::setUniform4i (const char *name,
++                              GLint x,
++                              GLint y,
++                              GLint z,
++                              GLint w)
++{
++    GLint location = (*GL::getUniformLocation) (priv->program, name);
++    if (location == -1)
++	return false;
++
++    (*GL::uniform4i) (location, x, y, z, w);
++    return true;
++}
++
++GLuint GLProgram::attributeLocation (const char *name)
++{
++    return (*GL::getAttribLocation) (priv->program, name);
++}
++
+--- /dev/null
++++ compiz-0.9.7.6/plugins/opengl/src/framebufferobject.cpp
+@@ -0,0 +1,191 @@
++/*
++ * Copyright (c) 2011 Collabora, Ltd.
++ *
++ * Permission to use, copy, modify, distribute, and sell this software
++ * and its documentation for any purpose is hereby granted without
++ * fee, provided that the above copyright notice appear in all copies
++ * and that both that copyright notice and this permission notice
++ * appear in supporting documentation, and that the name of
++ * Collabora Ltd. not be used in advertising or publicity pertaining to
++ * distribution of the software without specific, written prior permission.
++ * Collabora Ltd. makes no representations about the suitability of this
++ * software for any purpose. It is provided "as is" without express or
++ * implied warranty.
++ *
++ * COLLABORA LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
++ * NO EVENT SHALL COLLABORA LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
++ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
++ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
++ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
++ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ *
++ * Authors: Pekka Paalanen <ppaalanen@xxxxxxxxx>
++ */
++
++#include <map>
++#include <opengl/framebufferobject.h>
++#include <opengl/texture.h>
++
++struct PrivateGLFramebufferObject
++{
++    PrivateGLFramebufferObject () :
++	fboId (0),
++	glTex (NULL)
++    {
++    }
++
++    void pushFBO ();
++    void popFBO ();
++
++    GLuint fboId;
++    GLuint tmpId;
++    GLTexture *glTex;
++
++    static std::map<GLuint, GLFramebufferObject *> idMap;
++};
++
++std::map<GLuint, GLFramebufferObject *> PrivateGLFramebufferObject::idMap;
++
++void
++PrivateGLFramebufferObject::pushFBO ()
++{
++    GLint id = 0;
++    glGetIntegerv (GL_FRAMEBUFFER_BINDING, &id);
++    tmpId = id;
++    if (tmpId == fboId)
++	return;
++
++    (*GL::bindFramebuffer) (GL_FRAMEBUFFER, fboId);
++}
++
++void
++PrivateGLFramebufferObject::popFBO ()
++{
++    if (tmpId != fboId)
++	(*GL::bindFramebuffer) (GL_FRAMEBUFFER, tmpId);
++}
++
++GLFramebufferObject::GLFramebufferObject () :
++    priv (new PrivateGLFramebufferObject)
++{
++    (*GL::genFramebuffers) (1, &priv->fboId);
++    if (priv->fboId != 0)
++	PrivateGLFramebufferObject::idMap[priv->fboId] = this;
++}
++
++GLFramebufferObject::~GLFramebufferObject ()
++{
++    if (priv->glTex)
++	GLTexture::decRef (priv->glTex);
++
++    PrivateGLFramebufferObject::idMap.erase (priv->fboId);
++    (*GL::deleteFramebuffers) (1, &priv->fboId);
++
++    delete priv;
++}
++
++bool
++GLFramebufferObject::allocate (const CompSize &size, const char *image,
++			       GLenum format, GLenum type)
++{
++    if (!priv->glTex ||
++        size.width () != priv->glTex->width () ||
++        size.height () != priv->glTex->height ())
++    {
++	if (priv->glTex)
++	    GLTexture::decRef (priv->glTex);
++	priv->glTex = NULL;
++
++	GLTexture::List list = GLTexture::imageDataToTexture (image, size,
++							      format, type);
++	if (list.size () != 1 || list[0] == NULL)
++	    return false;
++
++	priv->glTex = list[0];
++	GLTexture::incRef (priv->glTex);
++    }
++
++    priv->pushFBO ();
++    (*GL::framebufferTexture2D) (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
++                                 priv->glTex->target (),
++                                 priv->glTex->name (), 0);
++    priv->popFBO ();
++    return true;
++}
++
++GLFramebufferObject *
++GLFramebufferObject::bind ()
++{
++    GLFramebufferObject *old = NULL;
++    GLint id = 0;
++
++    glGetIntegerv (GL_FRAMEBUFFER_BINDING, &id);
++    if (id != 0)
++    {
++	std::map<GLuint, GLFramebufferObject *>::iterator it;
++	it = PrivateGLFramebufferObject::idMap.find (id);
++
++	if (it != PrivateGLFramebufferObject::idMap.end ())
++	    old = it->second;
++	else
++	    compLogMessage ("opengl", CompLogLevelError,
++		"An FBO without GLFramebufferObject cannot be restored");
++    }
++
++    (*GL::bindFramebuffer) (GL_FRAMEBUFFER, priv->fboId);
++
++    return old;
++}
++
++// static
++void
++GLFramebufferObject::rebind (GLFramebufferObject *fbo)
++{
++    GLuint id = fbo ? fbo->priv->fboId : 0;
++    (*GL::bindFramebuffer) (GL_FRAMEBUFFER, id);
++}
++
++static const char *
++getFboErrorString (GLint status)
++{
++    switch (status)
++    {
++	case        GL_FRAMEBUFFER_COMPLETE:
++	    return "GL_FRAMEBUFFER_COMPLETE";
++	case        GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
++	    return "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
++	case        GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
++	    return "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
++#ifdef USE_GLES
++	case        GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
++	    return "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS";
++#endif
++	case        GL_FRAMEBUFFER_UNSUPPORTED:
++	    return "GL_FRAMEBUFFER_UNSUPPORTED";
++	default:
++	    return "unexpected status";
++    }
++}
++
++bool
++GLFramebufferObject::checkStatus ()
++{
++    priv->pushFBO ();
++    GLint status = (*GL::checkFramebufferStatus) (GL_FRAMEBUFFER);
++    priv->popFBO ();
++
++    if (status == GL_FRAMEBUFFER_COMPLETE)
++	return true;
++
++    compLogMessage ("opengl", CompLogLevelError,
++                    "FBO is incomplete: %s (0x%04x)",
++                    getFboErrorString (status), status);
++    return false;
++}
++
++GLTexture *
++GLFramebufferObject::tex ()
++{
++	return priv->glTex;
++}
+--- /dev/null
++++ compiz-0.9.7.6/plugins/opengl/src/privatevertexbuffer.h
+@@ -0,0 +1,138 @@
++/*
++ * Copyright © 2011 Linaro Ltd.
++ *
++ * Permission to use, copy, modify, distribute, and sell this software
++ * and its documentation for any purpose is hereby granted without
++ * fee, provided that the above copyright notice appear in all copies
++ * and that both that copyright notice and this permission notice
++ * appear in supporting documentation, and that the name of
++ * Linaro Ltd. not be used in advertising or publicity pertaining to
++ * distribution of the software without specific, written prior permission.
++ * Linaro Ltd. makes no representations about the suitability of this
++ * software for any purpose. It is provided "as is" without express or
++ * implied warranty.
++ *
++ * LINARO LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
++ * NO EVENT SHALL LINARO LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
++ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
++ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
++ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
++ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ *
++ * Authors: Travis Watkins <travis.watkins@xxxxxxxxxx>
++ *          Frederic Plourde <frederic.plourde@xxxxxxxxxxxxxxx>
++ */
++
++#ifndef _VERTEXBUFFER_PRIVATE_H
++#define _VERTEXBUFFER_PRIVATE_H
++
++#ifdef USE_GLES
++#include <GLES2/gl2.h>
++#else
++#include <GL/gl.h>
++#endif
++
++#include <opengl/program.h>
++#include <typeinfo>
++
++class GLVertexBuffer;
++
++class AbstractUniform
++{
++   public:
++       void virtual set(GLProgram* program) = 0;
++};
++
++template < typename T, int C >
++class Uniform: public AbstractUniform
++{
++    public:
++	Uniform(const char *_name, ... );
++	void set(GLProgram* program);
++
++    public:
++	T a[C];
++	std::string name;
++};
++
++template < typename T, int C >
++Uniform< T, C >::Uniform(const char *_name, ... )
++{
++    va_list arg_list;
++    va_start( arg_list, _name );
++    name = _name;
++    for( int i = 0; i < C; i++ )
++	a[i] = va_arg( arg_list, T );
++    va_end( arg_list );
++}
++
++template < typename T, int C >
++void Uniform< T, C >::set(GLProgram* prog)
++{
++    const char* n = name.c_str();
++
++    // This will only get called from privateVertexBuffer::render
++    // so we know we've got a valid, bound program here
++    if (typeid(a[0]) == typeid(double))
++    {
++	switch (C)
++	{
++	    case 1: prog->setUniform   (n, (GLfloat) a[0]); break;
++	    case 2: prog->setUniform2f (n, a[0], a[1]); break;
++	    case 3: prog->setUniform3f (n, a[0], a[1], a[2]); break;
++	    case 4: prog->setUniform4f (n, a[0], a[1], a[2], a[3]); break;
++	}
++    } else if (typeid(a[0]) == typeid(int))
++    {
++	switch (C)
++	{
++	    case 1: prog->setUniform   (n, (GLint) a[0]); break;
++	    case 2: prog->setUniform2i (n, a[0], a[1]); break;
++	    case 3: prog->setUniform3i (n, a[0], a[1], a[2]); break;
++	    case 4: prog->setUniform4i (n, a[0], a[1], a[2], a[3]); break;
++	}
++    } else
++    {
++	compLogMessage ("opengl", CompLogLevelError, "Unknown uniform type!");
++    }
++}
++
++class GLVertexBuffer;
++
++class PrivateVertexBuffer
++{
++    public:
++	PrivateVertexBuffer ();
++	~PrivateVertexBuffer ();
++
++	int render (const GLMatrix            *projection,
++	            const GLMatrix            *modelview,
++	            const GLWindowPaintAttrib *attrib);
++	int legacyRender (const GLMatrix            &projection,
++	                  const GLMatrix            &modelview,
++	                  const GLWindowPaintAttrib &attrib);
++
++    public:
++	static GLVertexBuffer *streamingBuffer;
++
++	std::vector<GLfloat> vertexData;
++	std::vector<GLfloat> normalData;
++	std::vector<GLfloat> colorData;
++	std::vector<std::vector<GLfloat> > textureData;
++
++	GLProgram *program;
++	GLenum primitiveType;
++	GLenum usage;
++
++	GLuint vertexBuffer;
++	GLuint normalBuffer;
++	GLuint colorBuffer;
++	GLuint textureBuffers[4];
++	std::vector<AbstractUniform*> uniforms;
++
++	GLVertexBuffer::AutoProgram *autoProgram;
++};
++
++#endif //_VERTEXBUFFER_PRIVATE_H
++
+--- compiz-0.9.7.6.orig/plugins/opengl/src/window.cpp
++++ compiz-0.9.7.6/plugins/opengl/src/window.cpp
+@@ -46,6 +46,28 @@ GLWindow::~GLWindow ()
+     delete priv;
+ }
+ 
++
++/**
++ * Callback object to create GLPrograms automatically when using GLVertexBuffer.
++ */
++class GLWindowAutoProgram : public GLVertexBuffer::AutoProgram
++{
++public:
++    GLWindowAutoProgram (PrivateGLWindow *pWindow) : pWindow(pWindow) {}
++
++    GLProgram *getProgram (GLShaderParameters &params)
++    {
++	GLScreen *gScreen = pWindow->gScreen;
++
++	const GLShaderData *shaderData = gScreen->getShaderData (params);
++	pWindow->shaders.push_back (shaderData);
++	return gScreen->getProgram (pWindow->shaders);
++    }
++
++    PrivateGLWindow *pWindow;
++
++};
++
+ PrivateGLWindow::PrivateGLWindow (CompWindow *w,
+ 				  GLWindow   *gw) :
+     window (w),
+@@ -57,7 +79,8 @@ PrivateGLWindow::PrivateGLWindow (CompWi
+     updateReg (true),
+     clip (),
+     bindFailed (false),
+-    geometry (),
++    vertexBuffer (new GLVertexBuffer ()),
++    autoProgram(new GLWindowAutoProgram(this)),
+     icons ()
+ {
+     paint.xScale	= 1.0f;
+@@ -67,10 +90,13 @@ PrivateGLWindow::PrivateGLWindow (CompWi
+ 
+     WindowInterface::setHandler (w);
+     CompositeWindowInterface::setHandler (cWindow);
++    vertexBuffer->setAutoProgram(autoProgram);
+ }
+ 
+ PrivateGLWindow::~PrivateGLWindow ()
+ {
++    delete vertexBuffer;
++    delete autoProgram;
+ }
+ 
+ void
+@@ -105,6 +131,21 @@ GLWindow::bind ()
+ 	compLogMessage ("opengl", CompLogLevelInfo,
+ 			"Couldn't bind redirected window 0x%x to "
+ 			"texture\n", (int) priv->window->id ());
++
++	if (priv->cWindow->size ().width () > GL::maxTextureSize ||
++	    priv->cWindow->size ().height ()  > GL::maxTextureSize)
++	{
++	    compLogMessage ("opengl", CompLogLevelWarn,
++			    "Bug in window 0x%x (identifying as %s)", (int) priv->window->id (), priv->window->resName ().size () ? priv->window->resName ().c_str () : "(none available)");
++	    compLogMessage ("opengl", CompLogLevelWarn,
++			    "This window tried to create an absurdly large window %i x %i\n", priv->cWindow->size ().width (), priv->cWindow->size ().height ());
++	    compLogMessage ("opengl", CompLogLevelWarn,
++			    "Unforunately, that's not supported on your hardware, because you have a maximum texture size of %i", GL::maxTextureSize);
++	    compLogMessage ("opengl", CompLogLevelWarn, "you should probably file a bug against that application");
++	    compLogMessage ("opengl", CompLogLevelWarn, "for now, we're going to hide tht window so that it doesn't break your desktop\n");
++
++	    XReparentWindow (screen->dpy (), priv->window->id (), GLScreen::get (screen)->priv->saveWindow, 0, 0);
++	}
+     }
+ 
+     priv->setWindowMatrix ();
+@@ -132,11 +173,11 @@ GLWindowInterface::glPaint (const GLWind
+     WRAPABLE_DEF (glPaint, attrib, transform, region, mask)
+ 
+ bool
+-GLWindowInterface::glDraw (const GLMatrix     &transform,
+-			   GLFragment::Attrib &fragment,
+-			   const CompRegion   &region,
+-			   unsigned int       mask)
+-    WRAPABLE_DEF (glDraw, transform, fragment, region, mask)
++GLWindowInterface::glDraw (const GLMatrix            &transform,
++			   const GLWindowPaintAttrib &attrib,
++			   const CompRegion          &region,
++			   unsigned int              mask)
++    WRAPABLE_DEF (glDraw, transform, attrib, region, mask)
+ 
+ void
+ GLWindowInterface::glAddGeometry (const GLTexture::MatrixList &matrix,
+@@ -148,14 +189,11 @@ GLWindowInterface::glAddGeometry (const
+ 		  maxGridWidth, maxGridHeight)
+ 
+ void
+-GLWindowInterface::glDrawTexture (GLTexture          *texture,
+-				  GLFragment::Attrib &fragment,
+-				  unsigned int       mask)
+-    WRAPABLE_DEF (glDrawTexture, texture, fragment, mask)
+-
+-void
+-GLWindowInterface::glDrawGeometry ()
+-    WRAPABLE_DEF (glDrawGeometry)
++GLWindowInterface::glDrawTexture (GLTexture                 *texture,
++                                  const GLMatrix            &transform,
++				  const GLWindowPaintAttrib &attrib,
++				  unsigned int              mask)
++    WRAPABLE_DEF (glDrawTexture, texture, transform, attrib, mask)
+ 
+ const CompRegion &
+ GLWindow::clip () const
+@@ -223,76 +261,10 @@ GLWindow::updatePaintAttribs ()
+     priv->paint.saturation = cw->saturation ();
+ }
+ 
+-GLWindow::Geometry &
+-GLWindow::geometry ()
+-{
+-    return priv->geometry;
+-}
+-
+-GLWindow::Geometry::Geometry () :
+-    vertices (NULL),
+-    vertexSize (0),
+-    vertexStride (0),
+-    indices (NULL),
+-    indexSize (0),
+-    vCount (0),
+-    texUnits (0),
+-    texCoordSize (0),
+-    indexCount (0)
+-{
+-}
+-
+-GLWindow::Geometry::~Geometry ()
+-{
+-    if (vertices)
+-	free (vertices);
+-
+-    if (indices)
+-	free (indices);
+-}
+-
+-void
+-GLWindow::Geometry::reset ()
+-{
+-    vCount = indexCount = 0;
+-}
+-
+-bool
+-GLWindow::Geometry::moreVertices (int newSize)
+-{
+-    if (newSize > vertexSize)
+-    {
+-	GLfloat *nVertices;
+-
+-	nVertices = (GLfloat *)
+-	    realloc (vertices, sizeof (GLfloat) * newSize);
+-	if (!nVertices)
+-	    return false;
+-
+-	vertices = nVertices;
+-	vertexSize = newSize;
+-    }
+-
+-    return true;
+-}
+-
+-bool
+-GLWindow::Geometry::moreIndices (int newSize)
++GLVertexBuffer *
++GLWindow::vertexBuffer ()
+ {
+-    if (newSize > indexSize)
+-    {
+-	GLushort *nIndices;
+-
+-	nIndices = (GLushort *)
+-	    realloc (indices, sizeof (GLushort) * newSize);
+-	if (!nIndices)
+-	    return false;
+-
+-	indices = nIndices;
+-	indexSize = newSize;
+-    }
+-
+-    return true;
++    return priv->vertexBuffer;
+ }
+ 
+ const GLTexture::List &
+@@ -335,6 +307,19 @@ GLWindow::getIcon (int width, int height
+ }
+ 
+ void
++GLWindow::addShaders (std::string name,
++                      std::string vertex_shader,
++                      std::string fragment_shader)
++{
++    GLShaderData *data = new GLShaderData;
++    data->name = name;
++    data->vertexShader = vertex_shader;
++    data->fragmentShader = fragment_shader;
++
++    priv->shaders.push_back(data);
++}
++
++void
+ PrivateGLWindow::updateFrameRegion (CompRegion &region)
+ {
+     window->updateFrameRegion (region);
+--- compiz-0.9.7.6.orig/plugins/opengl/src/privatetexture.h
++++ compiz-0.9.7.6/plugins/opengl/src/privatetexture.h
+@@ -1,6 +1,7 @@
+ /*
+  * Copyright © 2008 Dennis Kasprzyk
+  * Copyright © 2007 Novell, Inc.
++ * Copyright © 2011 Linaro Ltd.
+  *
+  * Permission to use, copy, modify, distribute, and sell this software
+  * and its documentation for any purpose is hereby granted without
+@@ -23,13 +24,21 @@
+  *
+  * Authors: Dennis Kasprzyk <onestone@xxxxxxxxxxxxxxxxx>
+  *          David Reveman <davidr@xxxxxxxxxx>
++ *          Travis Watkins <travis.watkins@xxxxxxxxxx>
+  */
+ 
+ #ifndef _PRIVATETEXTURE_H
+ #define _PRIVATETEXTURE_H
+ 
++#ifdef USE_GLES
++#define SUPPORT_X11
++#include <GLES2/gl2.h>
++#include <EGL/egl.h>
++#include <EGL/eglext.h>
++#else
+ #include <GL/gl.h>
+ #include <GL/glx.h>
++#endif
+ #include <opengl/texture.h>
+ #include <X11/extensions/Xdamage.h>
+ 
+@@ -62,6 +71,28 @@ class PrivateTexture {
+ 	int               refCount;
+ };
+ 
++#ifdef USE_GLES
++class EglTexture : public GLTexture {
++    public:
++	EglTexture ();
++	~EglTexture ();
++
++	void enable (Filter filter);
++
++	static List bindPixmapToTexture (Pixmap pixmap,
++					 int width,
++					 int height,
++					 int depth);
++
++    public:
++	bool        damaged;
++	Damage      damage;
++	bool        updateMipMap;
++};
++
++extern std::map<Damage, EglTexture*> boundPixmapTex;
++#else
++
+ class TfpTexture : public GLTexture {
+     public:
+ 	TfpTexture ();
+@@ -82,5 +113,6 @@ class TfpTexture : public GLTexture {
+ };
+ 
+ extern std::map<Damage, TfpTexture*> boundPixmapTex;
++#endif
+ 
+ #endif
+--- /dev/null
++++ compiz-0.9.7.6/plugins/opengl/src/programcache.cpp
+@@ -0,0 +1,175 @@
++/*
++ * Copyright © 2011 Linaro Ltd.
++ *
++ * Permission to use, copy, modify, distribute, and sell this software
++ * and its documentation for any purpose is hereby granted without
++ * fee, provided that the above copyright notice appear in all copies
++ * and that both that copyright notice and this permission notice
++ * appear in supporting documentation, and that the name of
++ * Linaro Ltd. not be used in advertising or publicity pertaining to
++ * distribution of the software without specific, written prior permission.
++ * Linaro Ltd. makes no representations about the suitability of this
++ * software for any purpose. It is provided "as is" without express or
++ * implied warranty.
++ *
++ * LINARO LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
++ * NO EVENT SHALL LINARO LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
++ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
++ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
++ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
++ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ *
++ * Authors: Travis Watkins <travis.watkins@xxxxxxxxxx>
++ */
++
++#include <opengl/programcache.h>
++#include "privates.h"
++
++typedef std::list<std::string> access_history_t;
++typedef std::pair<GLProgram*, access_history_t::iterator> value;
++
++static GLProgram *
++compileProgram (std::string name, std::list<const GLShaderData*> shaders)
++{
++    std::list<const GLShaderData*>::const_iterator it;
++    std::string vertex_shader;
++    std::string fragment_shader;
++    std::string vertex_functions = "";
++    std::string vertex_function_calls = "";
++    std::string fragment_functions = "";
++    std::string fragment_function_calls = "";
++    int vpos, vcallpos, fpos, fcallpos;
++
++    for (it = shaders.begin (); it != shaders.end (); it++)
++    {
++	//find the special shaders to put the rest in
++	if ((*it)->vertexShader.find ("@VERTEX_FUNCTIONS@") != std::string::npos)
++	{
++	    vertex_shader = (*it)->vertexShader;
++	}
++	else
++	{
++	    if ((*it)->vertexShader.length ())
++	    {
++		vertex_functions += (*it)->vertexShader;
++		vertex_function_calls += (*it)->name + "_vertex();\n";
++	    }
++	}
++
++	if ((*it)->fragmentShader.find ("@FRAGMENT_FUNCTIONS@") != std::string::npos)
++	{
++	    fragment_shader = (*it)->fragmentShader;
++	}
++	else
++	{
++	    if ((*it)->fragmentShader.length ())
++	    {
++		fragment_functions += (*it)->fragmentShader;
++		fragment_function_calls += (*it)->name + "_fragment();\n";
++	    }
++	}
++    }
++
++    // put shader functions and function calls into the main shader
++    vpos = vertex_shader.find ("@VERTEX_FUNCTIONS@");
++    vertex_shader.replace (vpos, 18, vertex_functions);
++
++    vcallpos = vertex_shader.find ("@VERTEX_FUNCTION_CALLS@");
++    vertex_shader.replace (vcallpos, 23, vertex_function_calls);
++
++    fpos = fragment_shader.find ("@FRAGMENT_FUNCTIONS@");
++    fragment_shader.replace (fpos, 20, fragment_functions);
++
++    fcallpos = fragment_shader.find ("@FRAGMENT_FUNCTION_CALLS@");
++    fragment_shader.replace (fcallpos, 25, fragment_function_calls);
++
++    return new GLProgram (vertex_shader, fragment_shader);
++}
++
++class PrivateProgramCache
++{
++    public:
++	PrivateProgramCache (size_t);
++
++	const size_t                 capacity;
++	access_history_t             access_history;
++	std::map<std::string, value> cache;
++
++	void insert (std::string, GLProgram *);
++	void evict ();
++};
++
++GLProgramCache::GLProgramCache (size_t capacity) :
++    priv (new PrivateProgramCache (capacity))
++{
++    assert (priv->capacity != 0);
++}
++
++GLProgramCache::~GLProgramCache ()
++{
++    delete priv;
++}
++ 
++GLProgram* GLProgramCache::operator () (std::list<const GLShaderData*> shaders)
++{
++    std::list<const GLShaderData*>::const_iterator name_it;
++    std::string name;
++
++    for (name_it = shaders.begin(); name_it != shaders.end(); name_it++)
++    {
++	if (name.length () == 0)
++	    name += (*name_it)->name;
++	else
++	    name += ":" + (*name_it)->name;
++    }
++
++    std::map<std::string, value>::iterator it = priv->cache.find (name);
++ 
++    if (it == priv->cache.end ())
++    {
++	GLProgram *program = compileProgram (name, shaders);
++	priv->insert (name, program);
++	return program;
++    }
++    else
++    {
++	priv->access_history.splice (priv->access_history.end (),
++	                             priv->access_history,
++	                             (*it).second.second);
++	(*it).second.second = priv->access_history.rbegin ().base ();
++
++	return (*it).second.first;
++    }
++}
++
++PrivateProgramCache::PrivateProgramCache (size_t c) :
++    capacity (c)
++{
++}
++
++void PrivateProgramCache::insert (std::string name, GLProgram *program)
++{
++    assert (cache.find (name) == cache.end ());
++
++    if (cache.size () == capacity)
++	evict ();
++
++    // update most recently used GLProgram
++    access_history_t::iterator it = access_history.insert (access_history.end (), name);
++
++    cache.insert (std::make_pair (name, std::make_pair (program, it)));
++}
++
++void PrivateProgramCache::evict ()
++{
++    assert (!access_history.empty ());
++
++    // find least recently used GLProgram
++    std::map<std::string, value>::iterator it = cache.find (access_history.front ());
++    assert (it != cache.end ());
++ 
++    cache.erase (it);
++    access_history.pop_front ();
++}
++
+--- compiz-0.9.7.6.orig/plugins/opengl/src/privates.h
++++ compiz-0.9.7.6/plugins/opengl/src/privates.h
+@@ -32,8 +32,12 @@
+ #include <opengl/opengl.h>
+ #include <core/atoms.h>
+ 
+-#include "privatefragment.h"
++#ifdef USE_GLES
++#include <opengl/framebufferobject.h>
++#endif
++
+ #include "privatetexture.h"
++#include "privatevertexbuffer.h"
+ #include "opengl_options.h"
+ 
+ extern CompOutput *targetOutput;
+@@ -75,8 +79,9 @@ class PrivateGLScreen :
+ 	void controlSwapVideoSync ();
+ 	void waitForVideoSync ();
+ 
+-	void paintBackground (const CompRegion &region,
+-			      bool             transformed);
++	void paintBackground (const GLMatrix   &transform,
++	                      const CompRegion &region,
++                              bool             transformed);
+ 
+ 	void paintOutputRegion (const GLMatrix   &transform,
+ 			        const CompRegion &region,
+@@ -94,7 +99,9 @@ class PrivateGLScreen :
+ 
+ 	GLenum textureFilter;
+ 
++	#ifndef USE_GLES
+ 	GLFBConfig      glxPixmapFBConfigs[MAX_DEPTH + 1];
++	#endif
+ 
+ 	GLTexture::List backgroundTextures;
+ 	bool            backgroundLoaded;
+@@ -103,28 +110,41 @@ class PrivateGLScreen :
+ 
+ 	CompPoint rasterPos;
+ 
+-	GLFragment::Storage fragmentStorage;
+-
+-	GLfloat projection[16];
++	GLMatrix *projection;
+ 
+ 	bool clearBuffers;
+ 	bool lighting;
+ 
+-	GL::GLXGetProcAddressProc getProcAddress;
+-
++	#ifdef USE_GLES
++	EGLContext ctx;
++	EGLSurface surface;
++	#else
+ 	GLXContext ctx;
+ 
++	GL::GLXGetProcAddressProc getProcAddress;
++	#endif
++
++	GLFramebufferObject *scratchFbo;
+ 	CompRegion outputRegion;
+ 
+ 	bool pendingCommands;
+ 
+ 	XRectangle lastViewport;
++	bool refreshSubBuffer;
++	unsigned int lastMask;
+ 
+ 	std::vector<GLTexture::BindPixmapProc> bindPixmap;
+ 	bool hasCompositing;
+ 
+ 	GLIcon defaultIcon;
+ 
++	Window saveWindow; // hack for broken applications, see:
++			   // https://bugs.launchpad.net/ubuntu/+source/compiz/+bug/807487
++
++	GLProgramCache *programCache;
++	GLShaderCache   shaderCache;
++	GLVertexBuffer::AutoProgram *autoProgram;
++
+ 	Pixmap rootPixmapCopy;
+ 	CompSize rootPixmapSize;
+ };
+@@ -169,10 +189,15 @@ class PrivateGLWindow :
+ 
+ 	unsigned int lastMask;
+ 
+-	GLWindow::Geometry geometry;
++	GLVertexBuffer *vertexBuffer;
++
++	// map of shaders, plugin name is key, pair of vertex and fragment
++	// shader source code is value
++	std::list<const GLShaderData*> shaders;
++	GLVertexBuffer::AutoProgram *autoProgram;
+ 
+ 	std::list<GLIcon> icons;
+ };
+ 
+-
+ #endif
++
+--- compiz-0.9.7.6.orig/plugins/opengl/src/matrix.cpp
++++ compiz-0.9.7.6/plugins/opengl/src/matrix.cpp
+@@ -163,6 +163,60 @@ operator* (const GLMatrix& lhs,
+ #undef B
+ #undef P
+ 
++/*
++** Invert 4x4 matrix.
++** Contributed by David Moore (See Mesa bug #6748)
++*/
++bool GLMatrix::invert ()
++{
++    float inv[16], det;
++    int i;
++
++    inv[0] =   m[5]*m[10]*m[15] - m[5]*m[11]*m[14] - m[9]*m[6]*m[15]
++             + m[9]*m[7]*m[14] + m[13]*m[6]*m[11] - m[13]*m[7]*m[10];
++    inv[4] =  -m[4]*m[10]*m[15] + m[4]*m[11]*m[14] + m[8]*m[6]*m[15]
++             - m[8]*m[7]*m[14] - m[12]*m[6]*m[11] + m[12]*m[7]*m[10];
++    inv[8] =   m[4]*m[9]*m[15] - m[4]*m[11]*m[13] - m[8]*m[5]*m[15]
++             + m[8]*m[7]*m[13] + m[12]*m[5]*m[11] - m[12]*m[7]*m[9];
++    inv[12] = -m[4]*m[9]*m[14] + m[4]*m[10]*m[13] + m[8]*m[5]*m[14]
++             - m[8]*m[6]*m[13] - m[12]*m[5]*m[10] + m[12]*m[6]*m[9];
++    inv[1] =  -m[1]*m[10]*m[15] + m[1]*m[11]*m[14] + m[9]*m[2]*m[15]
++             - m[9]*m[3]*m[14] - m[13]*m[2]*m[11] + m[13]*m[3]*m[10];
++    inv[5] =   m[0]*m[10]*m[15] - m[0]*m[11]*m[14] - m[8]*m[2]*m[15]
++             + m[8]*m[3]*m[14] + m[12]*m[2]*m[11] - m[12]*m[3]*m[10];
++    inv[9] =  -m[0]*m[9]*m[15] + m[0]*m[11]*m[13] + m[8]*m[1]*m[15]
++             - m[8]*m[3]*m[13] - m[12]*m[1]*m[11] + m[12]*m[3]*m[9];
++    inv[13] =  m[0]*m[9]*m[14] - m[0]*m[10]*m[13] - m[8]*m[1]*m[14]
++             + m[8]*m[2]*m[13] + m[12]*m[1]*m[10] - m[12]*m[2]*m[9];
++    inv[2] =   m[1]*m[6]*m[15] - m[1]*m[7]*m[14] - m[5]*m[2]*m[15]
++             + m[5]*m[3]*m[14] + m[13]*m[2]*m[7] - m[13]*m[3]*m[6];
++    inv[6] =  -m[0]*m[6]*m[15] + m[0]*m[7]*m[14] + m[4]*m[2]*m[15]
++             - m[4]*m[3]*m[14] - m[12]*m[2]*m[7] + m[12]*m[3]*m[6];
++    inv[10] =  m[0]*m[5]*m[15] - m[0]*m[7]*m[13] - m[4]*m[1]*m[15]
++             + m[4]*m[3]*m[13] + m[12]*m[1]*m[7] - m[12]*m[3]*m[5];
++    inv[14] = -m[0]*m[5]*m[14] + m[0]*m[6]*m[13] + m[4]*m[1]*m[14]
++             - m[4]*m[2]*m[13] - m[12]*m[1]*m[6] + m[12]*m[2]*m[5];
++    inv[3] =  -m[1]*m[6]*m[11] + m[1]*m[7]*m[10] + m[5]*m[2]*m[11]
++             - m[5]*m[3]*m[10] - m[9]*m[2]*m[7] + m[9]*m[3]*m[6];
++    inv[7] =   m[0]*m[6]*m[11] - m[0]*m[7]*m[10] - m[4]*m[2]*m[11]
++             + m[4]*m[3]*m[10] + m[8]*m[2]*m[7] - m[8]*m[3]*m[6];
++    inv[11] = -m[0]*m[5]*m[11] + m[0]*m[7]*m[9] + m[4]*m[1]*m[11]
++             - m[4]*m[3]*m[9] - m[8]*m[1]*m[7] + m[8]*m[3]*m[5];
++    inv[15] =  m[0]*m[5]*m[10] - m[0]*m[6]*m[9] - m[4]*m[1]*m[10]
++             + m[4]*m[2]*m[9] + m[8]*m[1]*m[6] - m[8]*m[2]*m[5];
++
++    det = m[0]*inv[0] + m[1]*inv[4] + m[2]*inv[8] + m[3]*inv[12];
++    if (det == 0)
++        return false;
++
++    det = 1.0f / det;
++
++    for (i = 0; i < 16; i++)
++        m[i] = inv[i] * det;
++
++    return true;
++}
++
+ /**
+  * Generate a 4x4 transformation matrix from glRotate parameters, and
+  * post-multiply the input matrix by it.
+--- compiz-0.9.7.6.orig/plugins/opengl/src/texture.cpp
++++ compiz-0.9.7.6/plugins/opengl/src/texture.cpp
+@@ -35,7 +35,11 @@
+ #include <privatetexture.h>
+ #include "privates.h"
+ 
++#ifdef USE_GLES
++std::map<Damage, EglTexture*> boundPixmapTex;
++#else
+ std::map<Damage, TfpTexture*> boundPixmapTex;
++#endif
+ 
+ static GLTexture::Matrix _identity_matrix = {
+     1.0f, 0.0f,
+@@ -150,7 +154,7 @@ GLTexture::matrix () const
+ bool
+ GLTexture::mipmap () const
+ {
+-    return priv->mipmap & priv->mipmapSupport;
++    return priv->mipmap && priv->mipmapSupport;
+ }
+ 
+ GLenum
+@@ -163,7 +167,9 @@ void
+ GLTexture::enable (GLTexture::Filter filter)
+ {
+     GLScreen *gs = GLScreen::get (screen);
++#ifndef USE_GLES
+     glEnable (priv->target);
++#endif
+     glBindTexture (priv->target, priv->name);
+ 
+     if (filter == Fast)
+@@ -184,7 +190,7 @@ GLTexture::enable (GLTexture::Filter fil
+     {
+ 	if (gs->textureFilter () == GL_LINEAR_MIPMAP_LINEAR)
+ 	{
+-	    if (GL::textureNonPowerOfTwo && GL::fbo && priv->mipmap)
++	    if (mipmap ())
+ 	    {
+ 		glTexParameteri (priv->target,
+ 				 GL_TEXTURE_MIN_FILTER,
+@@ -226,7 +232,7 @@ GLTexture::enable (GLTexture::Filter fil
+     {
+ 	if (priv->initial)
+ 	{
+-	    (*GL::generateMipmap) (priv->target);
++	    GL::generateMipmap (priv->target);
+ 	    priv->initial = false;
+ 	}
+     }
+@@ -236,7 +242,9 @@ void
+ GLTexture::disable ()
+ {
+     glBindTexture (priv->target, 0);
++#ifndef USE_GLES
+     glDisable (priv->target);
++#endif
+ }
+ 
+ void
+@@ -295,20 +303,26 @@ PrivateTexture::loadImageData (const cha
+     rv[0] = t;
+ 
+     GLTexture::Matrix matrix = _identity_matrix;
+-    CompOption        *opt;
+     GLint             internalFormat;
+     GLenum            target;
+     bool              mipmap;
++    bool              pot = POWER_OF_TWO (width) && POWER_OF_TWO (height);
+ 
++    #ifdef USE_GLES
++    target = GL_TEXTURE_2D;
++    matrix.xx = 1.0f / width;
++    matrix.yy = 1.0f / height;
++    matrix.y0 = 0.0f;
++    mipmap = GL::textureNonPowerOfTwoMipmap || pot;
++    #else
+ 
+-    if (GL::textureNonPowerOfTwo ||
+-	(POWER_OF_TWO (width) && POWER_OF_TWO (height)))
++    if (GL::textureNonPowerOfTwo || pot)
+     {
+ 	target = GL_TEXTURE_2D;
+ 	matrix.xx = 1.0f / width;
+ 	matrix.yy = 1.0f / height;
+ 	matrix.y0 = 0.0f;
+-	mipmap = true;
++	mipmap = GL::fbo && (GL::textureNonPowerOfTwoMipmap || pot);
+     }
+     else
+     {
+@@ -318,17 +332,26 @@ PrivateTexture::loadImageData (const cha
+ 	matrix.y0 = 0.0f;
+ 	mipmap = false;
+     }
++    #endif
+ 
+     t->setData (target, matrix, mipmap);
+     t->setGeometry (0, 0, width, height);
+ 
+     glBindTexture (target, t->name ());
+ 
++    #ifdef USE_GLES
++//    internalFormat = GL_BGRA;
++    internalFormat = GL_BGRA;
++    #else
++    internalFormat = GL_RGBA;
++    #endif
++
++    #ifndef USE_GLES
++    CompOption *opt;
+     opt = GLScreen::get (screen)->getOption ("texture_compression");
+     if (opt->value ().b () && GL::textureCompression)
+ 	internalFormat = GL_COMPRESSED_RGBA_ARB;
+-    else
+-	internalFormat =  GL_RGBA;
++    #endif
+ 
+     glTexImage2D (target, 0, internalFormat, width, height, 0,
+ 		  format, type, image);
+@@ -413,6 +436,106 @@ GLTexture::bindPixmapToTexture (Pixmap p
+     return GLTexture::List ();
+ }
+ 
++#ifdef USE_GLES
++EglTexture::EglTexture () :
++    damaged (true),
++    damage (None),
++    updateMipMap (true)
++{
++}
++
++EglTexture::~EglTexture ()
++{
++    GLuint temp = name ();
++    glBindTexture (target (), name ());
++
++    glDeleteTextures (1, &temp);
++
++    glBindTexture (target (), 0);
++
++    boundPixmapTex.erase (damage);
++    XDamageDestroy (screen->dpy (), damage);
++}
++
++GLTexture::List
++EglTexture::bindPixmapToTexture (Pixmap pixmap,
++				 int    width,
++				 int    height,
++				 int    depth)
++{
++    if ((int) width > GL::maxTextureSize || (int) height > GL::maxTextureSize ||
++        !GL::textureFromPixmap)
++	return GLTexture::List ();
++
++    GLTexture::List   rv (1);
++    EglTexture        *tex = NULL;
++    EGLImageKHR       eglImage = NULL;
++    GLTexture::Matrix matrix = _identity_matrix;
++
++    const EGLint img_attribs[] = {
++	EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
++	EGL_NONE
++    };
++
++    eglImage = GL::createImage (eglGetDisplay (screen->dpy ()),
++                                EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR,
++                                (EGLClientBuffer)pixmap, img_attribs);
++
++    if (eglImage == EGL_NO_IMAGE_KHR)
++    {
++	compLogMessage ("core", CompLogLevelWarn,
++			"eglCreateImageKHR failed");
++
++	return GLTexture::List ();
++    }
++
++    matrix.xx = 1.0f / width;
++    matrix.yy = 1.0f / height;
++    matrix.y0 = 0.0f;
++
++    tex = new EglTexture ();
++    tex->setData (GL_TEXTURE_2D, matrix,
++	GL::textureNonPowerOfTwoMipmap ||
++	(POWER_OF_TWO (width) && POWER_OF_TWO (height)));
++    tex->setGeometry (0, 0, width, height);
++
++    rv[0] = tex;
++
++    glBindTexture (GL_TEXTURE_2D, tex->name ());
++
++    GL::eglImageTargetTexture (GL_TEXTURE_2D, (GLeglImageOES)eglImage);
++    GL::destroyImage (eglGetDisplay (screen->dpy ()), eglImage);
++
++    tex->setFilter (GL_NEAREST);
++    tex->setWrap (GL_CLAMP_TO_EDGE);
++
++    glBindTexture (GL_TEXTURE_2D, 0);
++
++    tex->damage = XDamageCreate (screen->dpy (), pixmap,
++			         XDamageReportRawRectangles);
++    boundPixmapTex[tex->damage] = tex;
++
++    return rv;
++}
++
++void
++EglTexture::enable (GLTexture::Filter filter)
++{
++    glBindTexture (target (), name ());
++    GLTexture::enable (filter);
++    
++    if (damaged)
++	updateMipMap = true;
++
++    if (this->filter () == GL_LINEAR_MIPMAP_LINEAR && updateMipMap)
++    {
++	GL::generateMipmap (target ());
++	updateMipMap = false;
++    }
++    damaged = false;
++}
++#else
++
+ TfpTexture::TfpTexture () :
+     pixmap (0),
+     damaged (true),
+@@ -611,3 +734,5 @@ TfpTexture::enable (GLTexture::Filter fi
+     }
+     damaged = false;
+ }
++#endif
++
+--- /dev/null
++++ compiz-0.9.7.6/plugins/opengl/src/vertexbuffer.cpp
+@@ -0,0 +1,550 @@
++/*
++ * Copyright © 2011 Linaro Ltd.
++ *
++ * Permission to use, copy, modify, distribute, and sell this software
++ * and its documentation for any purpose is hereby granted without
++ * fee, provided that the above copyright notice appear in all copies
++ * and that both that copyright notice and this permission notice
++ * appear in supporting documentation, and that the name of
++ * Linaro Ltd. not be used in advertising or publicity pertaining to
++ * distribution of the software without specific, written prior permission.
++ * Linaro Ltd. makes no representations about the suitability of this
++ * software for any purpose. It is provided "as is" without express or
++ * implied warranty.
++ *
++ * LINARO LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
++ * NO EVENT SHALL LINARO LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
++ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
++ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
++ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
++ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ *
++ * Authors: Travis Watkins <travis.watkins@xxxxxxxxxx>
++ *          Frederic Plourde <frederic.plourde@xxxxxxxxxxxxxxx>
++ *          Alexandros Frantzis <alexandros.frantzis@xxxxxxxxxx>
++ */
++
++#include <vector>
++#include <iostream>
++
++#ifdef USE_GLES
++#include <GLES2/gl2.h>
++#else
++#include <GL/gl.h>
++#include <GL/glext.h>
++#endif
++
++#include <opengl/vertexbuffer.h>
++
++#include "privates.h"
++
++GLVertexBuffer *PrivateVertexBuffer::streamingBuffer = NULL;
++
++GLVertexBuffer::GLVertexBuffer () :
++    priv (new PrivateVertexBuffer ())
++{
++    priv->usage = GL_STATIC_DRAW;
++}
++
++GLVertexBuffer::GLVertexBuffer (GLenum usage) :
++    priv (new PrivateVertexBuffer ())
++{
++    priv->usage = usage;
++}
++
++GLVertexBuffer::~GLVertexBuffer ()
++{
++    delete priv;
++}
++
++GLVertexBuffer *GLVertexBuffer::streamingBuffer ()
++{
++    if (PrivateVertexBuffer::streamingBuffer == NULL)
++	PrivateVertexBuffer::streamingBuffer = new GLVertexBuffer
++	                                                      (GL_STREAM_DRAW);
++    return PrivateVertexBuffer::streamingBuffer;
++}
++
++void GLVertexBuffer::begin (GLenum primitiveType)
++{
++    priv->primitiveType = primitiveType;
++
++    priv->vertexData.clear ();
++    priv->normalData.clear ();
++    priv->colorData.clear ();
++    priv->textureData.clear ();
++    priv->uniforms.clear ();
++}
++
++void GLVertexBuffer::begin ()
++{
++    begin (GL_TRIANGLES);
++}
++
++int GLVertexBuffer::end ()
++{
++    if (!GL::vbo)
++	return 0;
++
++    if (!priv->vertexData.size ())
++	return -1;
++
++    GL::bindBuffer (GL_ARRAY_BUFFER, priv->vertexBuffer);
++    GL::bufferData (GL_ARRAY_BUFFER,
++                    sizeof(GLfloat) * priv->vertexData.size (),
++                    &priv->vertexData[0], priv->usage);
++
++    if (priv->normalData.size ())
++    {
++	GL::bindBuffer (GL_ARRAY_BUFFER, priv->normalBuffer);
++	GL::bufferData (GL_ARRAY_BUFFER,
++	                sizeof(GLfloat) * priv->normalData.size (),
++	                &priv->normalData[0], priv->usage);
++    }
++
++    if (priv->colorData.size ())
++    {
++	GL::bindBuffer (GL_ARRAY_BUFFER, priv->colorBuffer);
++	GL::bufferData (GL_ARRAY_BUFFER,
++	                sizeof(GLfloat) * priv->colorData.size (),
++	                &priv->colorData[0], priv->usage);
++    }
++
++    if (priv->textureData.size ())
++    {
++	for (unsigned int i = 0; i < priv->textureData.size (); i++)
++	{
++	    GL::bindBuffer (GL_ARRAY_BUFFER, priv->textureBuffers[i]);
++	    GL::bufferData (GL_ARRAY_BUFFER,
++	                    sizeof(GLfloat) * priv->textureData[i].size (),
++	                    &priv->textureData[i][0], priv->usage);
++	}
++    }
++
++    GL::bindBuffer (GL_ARRAY_BUFFER, 0);
++
++    return 0;
++}
++
++void GLVertexBuffer::addVertices (GLuint nVertices, GLfloat *vertices)
++{
++    priv->vertexData.reserve (priv->vertexData.size () + (nVertices * 3));
++
++    for (GLuint i = 0; i < nVertices * 3; i++)
++    {
++	priv->vertexData.push_back (vertices[i]);
++    }
++}
++
++void GLVertexBuffer::addNormals (GLuint nNormals, GLfloat *normals)
++{
++    priv->normalData.reserve (priv->normalData.size () + (nNormals * 3));
++
++    for (GLuint i = 0; i < nNormals * 3; i++)
++    {
++	priv->normalData.push_back (normals[i]);
++    }
++}
++
++void GLVertexBuffer::addColors (GLuint nColors, GLushort *colors)
++{
++    priv->colorData.reserve (priv->colorData.size () + (nColors * 4));
++
++    for (GLuint i = 0; i < nColors * 4; i++)
++    {
++	priv->colorData.push_back (colors[i] / 65535.0f);
++    }
++}
++
++void GLVertexBuffer::addTexCoords (GLuint texture,
++                                   GLuint nTexcoords,
++                                   GLfloat *texcoords)
++{
++    //four textures max (zero indexed)
++    if (texture > 3)
++	return;
++
++    while (texture >= priv->textureData.size ())
++    {
++	std::vector<GLfloat> temp;
++	priv->textureData.push_back (temp);
++    }
++
++    priv->textureData[texture].reserve (priv->textureData[texture].size () +
++                                        (nTexcoords * 2));
++
++    for (GLuint i = 0; i < nTexcoords * 2; i++)
++    {
++	priv->textureData[texture].push_back (texcoords[i]);
++    }
++}
++
++void GLVertexBuffer::addUniform (const char *name, GLfloat value)
++{
++    // we're casting to double here to make our template va_arg happy
++    Uniform<double, 1>* uniform = new Uniform<double, 1>(name, (double)value);
++    priv->uniforms.push_back (uniform);
++}
++
++void GLVertexBuffer::addUniform (const char *name, GLint value)
++{
++    Uniform<GLint, 1>* uniform = new Uniform<GLint, 1>(name, value);
++    priv->uniforms.push_back (uniform);
++}
++
++bool GLVertexBuffer::addUniform (const char *name, const GLMatrix &value)
++{
++    //#warning Add 'addUniform' support to GLMatrix type !
++    return true;
++}
++
++void GLVertexBuffer::addUniform2f (const char *name,
++                                   GLfloat x,
++                                   GLfloat y)
++{
++    // we're casting to double here to make our template va_arg happy
++    Uniform<double, 2>* uniform = new Uniform<double, 2>(name,
++							 (double)x,
++							 (double)y);
++    priv->uniforms.push_back (uniform);
++}
++
++void GLVertexBuffer::addUniform3f (const char *name,
++                                   GLfloat x,
++                                   GLfloat y,
++                                   GLfloat z)
++{
++     // we're casting to double here to make our template va_arg happy
++    Uniform<double, 3>* uniform = new Uniform<double, 3>(name,
++							 (double)x,
++							 (double)y,
++							 (double)z);
++    priv->uniforms.push_back (uniform);
++}
++
++void GLVertexBuffer::addUniform4f (const char *name,
++                                   GLfloat x,
++                                   GLfloat y,
++                                   GLfloat z,
++                                   GLfloat w)
++{
++    // we're casting to double here to make our template va_arg happy
++    Uniform<double, 4>* uniform = new Uniform<double, 4>(name,
++							 (double)x,
++							 (double)y,
++							 (double)z,
++							 (double)w);
++    priv->uniforms.push_back (uniform);
++}
++
++void GLVertexBuffer::addUniform2i (const char *name,
++                                   GLint x,
++                                   GLint y)
++{
++    Uniform<GLint, 2>* uniform = new Uniform<GLint, 2>(name, x, y);
++    priv->uniforms.push_back (uniform);
++}
++
++void GLVertexBuffer::addUniform3i (const char *name,
++                                   GLint x,
++                                   GLint y,
++                                   GLint z)
++{
++    Uniform<GLint, 3>* uniform = new Uniform<GLint, 3>(name, x, y, z);
++    priv->uniforms.push_back (uniform);
++}
++
++void GLVertexBuffer::addUniform4i (const char *name,
++                                   GLint x,
++                                   GLint y,
++                                   GLint z,
++                                   GLint w)
++{
++    Uniform<GLint, 4>* uniform = new Uniform<GLint, 4>(name, x, y, z, w);
++    priv->uniforms.push_back (uniform);
++}
++
++void GLVertexBuffer::setProgram (GLProgram *program)
++{
++    priv->program = program;
++}
++
++void GLVertexBuffer::setAutoProgram (AutoProgram *autoProgram)
++{
++    priv->autoProgram = autoProgram;
++}
++
++int GLVertexBuffer::render ()
++{
++    if (GL::vbo && GL::shaders)
++	return priv->render (NULL, NULL, NULL);
++    else
++	return -1;
++}
++
++int GLVertexBuffer::render (const GLMatrix &modelview)
++{
++    const GLWindowPaintAttrib attrib = { OPAQUE, BRIGHT, COLOR, 0, 0, 0, 0 };
++
++    return render (modelview, attrib);
++}
++
++int GLVertexBuffer::render (const GLMatrix            &modelview,
++                            const GLWindowPaintAttrib &attrib)
++{
++    GLScreen *gScreen = GLScreen::get (screen);
++    GLMatrix *projection = gScreen->projectionMatrix ();
++
++    return render (*projection, modelview, attrib);
++}
++
++int GLVertexBuffer::render (const GLMatrix            &projection,
++                            const GLMatrix            &modelview,
++                            const GLWindowPaintAttrib &attrib)
++{
++    if (!priv->vertexData.size ())
++	return -1;
++
++    if (GL::vbo && GL::shaders)
++	return priv->render (&projection, &modelview, &attrib);
++    else
++	return priv->legacyRender (projection, modelview, attrib);
++}
++
++PrivateVertexBuffer::PrivateVertexBuffer () :
++    program (NULL)
++{
++    if (!GL::vbo)
++	return;
++
++    GL::genBuffers (1, &vertexBuffer);
++    GL::genBuffers (1, &normalBuffer);
++    GL::genBuffers (1, &colorBuffer);
++    GL::genBuffers (4, &textureBuffers[0]);
++}
++
++PrivateVertexBuffer::~PrivateVertexBuffer ()
++{
++    if (!GL::vbo)
++	return;
++
++    GL::deleteBuffers (1, &vertexBuffer);
++    GL::deleteBuffers (1, &normalBuffer);
++    GL::deleteBuffers (1, &colorBuffer);
++    GL::deleteBuffers (4, &textureBuffers[0]);
++}
++
++int PrivateVertexBuffer::render (const GLMatrix            *projection,
++                                 const GLMatrix            *modelview,
++                                 const GLWindowPaintAttrib *attrib)
++{
++    GLfloat attribs[3] = {1, 1, 1};
++    GLint positionIndex = -1;
++    GLint normalIndex = -1;
++    GLint colorIndex = -1;
++    GLint texCoordIndex[4] = {-1, -1, -1, -1};
++    GLProgram *tmpProgram = program;
++
++    // If we don't have an explicitly set program, try to get one
++    // using the AutoProgram callback object.
++    if (tmpProgram == NULL && autoProgram) {
++	// Convert attrib to shader parameters
++	GLShaderParameters params;
++
++	params.opacity = attrib->opacity != OPAQUE;
++	params.brightness = attrib->brightness != BRIGHT;
++	params.saturation = attrib->saturation != COLOR;
++	params.color = colorData.size () == 4 ? GLShaderVariableUniform :
++	               colorData.size () >  4 ? GLShaderVariableVarying :
++	                                        GLShaderVariableNone;
++	params.normal = normalData.size () <= 4 ? GLShaderVariableUniform :
++	                                          GLShaderVariableVarying;
++	params.numTextures = textureData.size ();
++
++	// Get a program matching the parameters
++	tmpProgram = autoProgram->getProgram(params);
++    }
++
++    if (tmpProgram == NULL)
++    {
++	std::cerr << "no program defined!" << std::endl;
++	return -1;
++    }
++
++    tmpProgram->bind ();
++    if (!tmpProgram->valid ())
++    {
++	return -1;
++    }
++
++    if (projection)
++	tmpProgram->setUniform ("projection", *projection);
++
++    if (modelview)
++	tmpProgram->setUniform ("modelview", *modelview);
++
++    positionIndex = tmpProgram->attributeLocation ("position");
++    (*GL::enableVertexAttribArray) (positionIndex);
++    (*GL::bindBuffer) (GL_ARRAY_BUFFER, vertexBuffer);
++    (*GL::vertexAttribPointer) (positionIndex, 3, GL_FLOAT, GL_FALSE, 0, 0);
++
++    //use default normal
++    if (normalData.size () == 0)
++    {
++	tmpProgram->setUniform3f ("singleNormal", 0.0f, 0.0f, -1.0f);
++    }
++    // special case a single normal and apply it to the entire operation
++    else if (normalData.size () == 3)
++    {
++	tmpProgram->setUniform3f ("singleNormal",
++	                       normalData[0], normalData[1], normalData[2]);
++    }
++    else if (normalData.size () > 3)
++    {
++	normalIndex = tmpProgram->attributeLocation ("normal");
++	(*GL::enableVertexAttribArray) (normalIndex);
++	(*GL::bindBuffer) (GL_ARRAY_BUFFER, normalBuffer);
++	(*GL::vertexAttribPointer) (normalIndex, 3, GL_FLOAT, GL_FALSE, 0, 0);
++    }
++
++    // special case a single color and apply it to the entire operation
++    if (colorData.size () == 4)
++    {
++	tmpProgram->setUniform4f ("singleColor", colorData[0],
++	                       colorData[1], colorData[2], colorData[3]);
++    }
++    else if (colorData.size () > 4)
++    {
++	colorIndex = tmpProgram->attributeLocation ("color");
++	(*GL::enableVertexAttribArray) (colorIndex);
++	(*GL::bindBuffer) (GL_ARRAY_BUFFER, colorBuffer);
++	(*GL::vertexAttribPointer) (colorIndex, 4, GL_FLOAT, GL_FALSE, 0, 0);
++    }
++
++    for (int i = textureData.size () - 1; i >= 0; i--)
++    {
++	char name[10];
++
++	snprintf (name, 10, "texCoord%d", i);
++	texCoordIndex[i] = tmpProgram->attributeLocation (name);
++
++	(*GL::enableVertexAttribArray) (texCoordIndex[i]);
++	(*GL::bindBuffer) (GL_ARRAY_BUFFER, textureBuffers[i]);
++	(*GL::vertexAttribPointer) (texCoordIndex[i], 2, GL_FLOAT, GL_FALSE, 0, 0);
++
++	snprintf (name, 9, "texture%d", i);
++	tmpProgram->setUniform (name, i);
++    }
++
++    // set per-plugin uniforms
++    for (unsigned int i = 0; i < uniforms.size (); i++)
++    {
++	uniforms[i]->set (program);
++    }
++
++    //convert paint attribs to 0-1 range
++    if (attrib)
++    {
++	attribs[0] = attrib->opacity  / 65535.0f;
++	attribs[1] = attrib->brightness / 65535.0f;
++	attribs[2] = attrib->saturation / 65535.0f;
++	tmpProgram->setUniform3f ("paintAttrib", attribs[0], attribs[1], attribs[2]);
++    }
++
++    glDrawArrays (primitiveType, 0, vertexData.size () / 3);
++
++    for (int i = 0; i < 4; ++i)
++    {
++	if (texCoordIndex[i] != -1)
++	    (*GL::disableVertexAttribArray) (texCoordIndex[i]);
++    }
++
++    if (colorIndex != -1)
++	(*GL::disableVertexAttribArray) (colorIndex);
++
++    if (normalIndex != -1)
++	(*GL::disableVertexAttribArray) (normalIndex);
++
++    (*GL::disableVertexAttribArray) (positionIndex);
++
++    GL::bindBuffer (GL_ARRAY_BUFFER, 0);
++    tmpProgram->unbind ();
++
++    return 0;
++}
++
++int PrivateVertexBuffer::legacyRender (const GLMatrix            &projection,
++                                       const GLMatrix            &modelview,
++                                       const GLWindowPaintAttrib &attrib)
++{
++    #ifndef USE_GLES
++    glMatrixMode (GL_PROJECTION);
++    glPushMatrix ();
++    glLoadMatrixf (projection.getMatrix ());
++
++    glMatrixMode (GL_MODELVIEW);
++    glPushMatrix ();
++    glLoadMatrixf (modelview.getMatrix ());
++
++    glEnableClientState (GL_VERTEX_ARRAY);
++    glVertexPointer (3, GL_FLOAT, 0, &vertexData[0]);
++
++    //use default normal
++    if (normalData.size () == 0)
++    {
++	glNormal3f (0.0f, 0.0f, -1.0f);
++    }
++    // special case a single normal and apply it to the entire operation
++    else if (normalData.size () == 3)
++    {
++	glNormal3fv (&normalData[0]);
++    }
++    else if (normalData.size () > 3)
++    {
++	glEnableClientState (GL_NORMAL_ARRAY);
++	glNormalPointer (GL_FLOAT, 0, &normalData[0]);
++    }
++
++    // special case a single color and apply it to the entire operation
++    if (colorData.size () == 4)
++    {
++	glColor4fv (&colorData[0]);
++    }
++    else if (colorData.size () > 4)
++    {
++	glEnableClientState (GL_COLOR_ARRAY);
++	glColorPointer (4, GL_FLOAT, 0, &colorData[0]);
++    }
++
++    for (int i = textureData.size () - 1; i >= 0; i--)
++    {
++	GL::clientActiveTexture (GL_TEXTURE0_ARB + i);
++	glEnableClientState (GL_TEXTURE_COORD_ARRAY);
++	glTexCoordPointer (2, GL_FLOAT, 0, &textureData[i][0]);
++    }
++
++    glDrawArrays (primitiveType, 0, vertexData.size () / 3);
++
++    glDisableClientState (GL_VERTEX_ARRAY);
++    glDisableClientState (GL_NORMAL_ARRAY);
++    glDisableClientState (GL_COLOR_ARRAY);
++
++    for (int i = textureData.size (); i > 0; i--)
++    {
++	GL::clientActiveTexture (GL_TEXTURE0_ARB + i);
++	glDisableClientState (GL_TEXTURE_COORD_ARRAY);
++    }
++
++    GL::clientActiveTexture (GL_TEXTURE0_ARB);
++
++    glMatrixMode (GL_PROJECTION);
++    glPopMatrix ();
++
++    glMatrixMode (GL_MODELVIEW);
++    glPopMatrix ();
++    #endif
++
++    return 0;
++}
++
+--- compiz-0.9.7.6.orig/plugins/opengl/src/paint.cpp
++++ compiz-0.9.7.6/plugins/opengl/src/paint.cpp
+@@ -1,5 +1,6 @@
+ /*
+  * Copyright © 2005 Novell, Inc.
++ * Copyright © 2011 Linaro, Ltd.
+  *
+  * Permission to use, copy, modify, distribute, and sell this software
+  * and its documentation for any purpose is hereby granted without
+@@ -20,7 +21,8 @@
+  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+  *
+- * Author: David Reveman <davidr@xxxxxxxxxx>
++ * Authors: David Reveman <davidr@xxxxxxxxxx>
++ *          Travis Watkins <travis.watkins@xxxxxxxxxx>
+  */
+ 
+ #include "privates.h"
+@@ -35,6 +37,8 @@
+ 
+ #include <opengl/opengl.h>
+ 
++#include "privates.h"
++
+ #define DEG2RAD (M_PI / 180.0f)
+ 
+ GLScreenPaintAttrib defaultScreenPaintAttrib = {
+@@ -64,14 +68,16 @@ GLScreen::glApplyTransform (const GLScre
+ }
+ 
+ void
+-PrivateGLScreen::paintBackground (const CompRegion &region,
+-				  bool             transformed)
++PrivateGLScreen::paintBackground (const GLMatrix   &transform,
++                                  const CompRegion &region,
++                                  bool             transformed)
+ {
++    GLVertexBuffer *streamingBuffer = GLVertexBuffer::streamingBuffer ();
++    GLfloat         vertexData[18];
++    GLushort        colorData[4];
++
+     BoxPtr    pBox = const_cast <Region> (region.handle ())->rects;
+     int	      n, nBox = const_cast <Region> (region.handle ())->numRects;
+-    GLfloat   *d;
+-
+-    boost::scoped_array <GLfloat> data;
+ 
+     if (!nBox)
+ 	return;
+@@ -97,86 +103,111 @@ PrivateGLScreen::paintBackground (const
+ 
+     if (backgroundTextures.empty ())
+     {
+-	data.reset (new GLfloat [nBox * 8]);
+-
+-	d = data.get ();
++	streamingBuffer->begin (GL_TRIANGLES);
+ 	n = nBox;
+ 
+ 	while (n--)
+ 	{
+-	    *d++ = pBox->x1;
+-	    *d++ = pBox->y2;
+-
+-	    *d++ = pBox->x2;
+-	    *d++ = pBox->y2;
++	    vertexData[0]  = pBox->x1;
++	    vertexData[1]  = pBox->y1;
++	    vertexData[2]  = 0.0f;
++	    vertexData[3]  = pBox->x1;
++	    vertexData[4]  = pBox->y2;
++	    vertexData[5]  = 0.0f;
++	    vertexData[6]  = pBox->x2;
++	    vertexData[7]  = pBox->y1;
++	    vertexData[8]  = 0.0f;
++	    vertexData[9]  = pBox->x1;
++	    vertexData[10] = pBox->y2;
++	    vertexData[11] = 0.0f;
++	    vertexData[12] = pBox->x2;
++	    vertexData[13] = pBox->y2;
++	    vertexData[14] = 0.0f;
++
++	    vertexData[15] = pBox->x2;
++	    vertexData[16] = pBox->y1;
++	    vertexData[17] = 0.0f;
+ 
+-	    *d++ = pBox->x2;
+-	    *d++ = pBox->y1;
+-
+-	    *d++ = pBox->x1;
+-	    *d++ = pBox->y1;
++	    streamingBuffer->addVertices (6, vertexData);
+ 
+ 	    pBox++;
+ 	}
+ 
+-	glDisableClientState (GL_TEXTURE_COORD_ARRAY);
+-
+-	glVertexPointer (2, GL_FLOAT, sizeof (GLfloat) * 2, &data[0]);
++	colorData[0] = colorData[1] = colorData[2] = 0;
++	colorData[3] = std::numeric_limits <unsigned short>::max ();
++	streamingBuffer->addColors (1, colorData);
+ 
+-	glColor4us (0, 0, 0, std::numeric_limits<unsigned short>::max ());
+-	glDrawArrays (GL_QUADS, 0, nBox * 4);
+-	glColor4usv (defaultColor);
+-
+-	glEnableClientState (GL_TEXTURE_COORD_ARRAY);
++	streamingBuffer->end ();
++	streamingBuffer->render (transform);
+     }
+     else
+     {
+-	data.reset (new GLfloat [nBox * 16]);
+-
+-	d = data.get ();
+ 	n = nBox;
+ 
+ 	for (unsigned int i = 0; i < backgroundTextures.size (); i++)
+ 	{
++	    GLfloat textureData[12];
+ 	    GLTexture *bg = backgroundTextures[i];
+ 	    CompRegion r = region & *bg;
+ 
+ 	    pBox = const_cast <Region> (r.handle ())->rects;
+ 	    nBox = const_cast <Region> (r.handle ())->numRects;
+-	    d = data.get ();
+ 	    n = nBox;
+ 
++	    streamingBuffer->begin (GL_TRIANGLES);
++
+ 	    while (n--)
+ 	    {
+-		*d++ = COMP_TEX_COORD_X (bg->matrix (), pBox->x1);
+-		*d++ = COMP_TEX_COORD_Y (bg->matrix (), pBox->y2);
+-
+-		*d++ = pBox->x1;
+-		*d++ = pBox->y2;
+-
+-		*d++ = COMP_TEX_COORD_X (bg->matrix (), pBox->x2);
+-		*d++ = COMP_TEX_COORD_Y (bg->matrix (), pBox->y2);
+-
+-		*d++ = pBox->x2;
+-		*d++ = pBox->y2;
+-
+-		*d++ = COMP_TEX_COORD_X (bg->matrix (), pBox->x2);
+-		*d++ = COMP_TEX_COORD_Y (bg->matrix (), pBox->y1);
++		GLfloat tx1 = COMP_TEX_COORD_X (bg->matrix (), pBox->x1);
++		GLfloat tx2 = COMP_TEX_COORD_X (bg->matrix (), pBox->x2);
++		GLfloat ty1 = COMP_TEX_COORD_Y (bg->matrix (), pBox->y1);
++		GLfloat ty2 = COMP_TEX_COORD_Y (bg->matrix (), pBox->y2);
++
++		vertexData[0]  = pBox->x1;
++		vertexData[1]  = pBox->y1;
++		vertexData[2]  = 0.0f;
++		vertexData[3]  = pBox->x1;
++		vertexData[4]  = pBox->y2;
++		vertexData[5]  = 0.0f;
++		vertexData[6]  = pBox->x2;
++		vertexData[7]  = pBox->y1;
++		vertexData[8]  = 0.0f;
++		vertexData[9]  = pBox->x1;
++		vertexData[10] = pBox->y2;
++		vertexData[11] = 0.0f;
++		vertexData[12] = pBox->x2;
++		vertexData[13] = pBox->y2;
++		vertexData[14] = 0.0f;
++
++		vertexData[15] = pBox->x2;
++		vertexData[16] = pBox->y1;
++		vertexData[17] = 0.0f;
++
++		textureData[0]  = tx1;
++		textureData[1]  = ty1;
++
++		textureData[2]  = tx1;
++		textureData[3]  = ty2;
++
++		textureData[4]  = tx2;
++		textureData[5]  = ty1;
++
++		textureData[6]  = tx1;
++		textureData[7]  = ty2;
+ 
+-		*d++ = pBox->x2;
+-		*d++ = pBox->y1;
++		textureData[8]  = tx2;
++		textureData[9]  = ty2;
+ 
+-		*d++ = COMP_TEX_COORD_X (bg->matrix (), pBox->x1);
+-		*d++ = COMP_TEX_COORD_Y (bg->matrix (), pBox->y1);
++		textureData[10] = tx2;
++		textureData[11] = ty1;
+ 
+-		*d++ = pBox->x1;
+-		*d++ = pBox->y1;
++		streamingBuffer->addVertices (6, vertexData);
++		streamingBuffer->addTexCoords (0, 6, textureData);
+ 
+ 		pBox++;
+ 	    }
+ 
+-	    glTexCoordPointer (2, GL_FLOAT, sizeof (GLfloat) * 4, &data[0]);
+-	    glVertexPointer (2, GL_FLOAT, sizeof (GLfloat) * 4, &data[2]);
++	    streamingBuffer->end ();
+ 
+ 	    if (bg->name ())
+ 	    {
+@@ -185,7 +216,7 @@ PrivateGLScreen::paintBackground (const
+ 		else
+ 		    bg->enable (GLTexture::Fast);
+ 
+-		glDrawArrays (GL_QUADS, 0, nBox * 4);
++		streamingBuffer->render (transform);
+ 
+ 		bg->disable ();
+ 	    }
+@@ -329,7 +360,9 @@ PrivateGLScreen::paintOutputRegion (cons
+ 	CompositeWindow::get (fullscreenWindow)->unredirect ();
+ 
+     if (!(mask & PAINT_SCREEN_NO_BACKGROUND_MASK))
+-	paintBackground (tmpRegion, (mask & PAINT_SCREEN_TRANSFORMED_MASK));
++	paintBackground (transform,
++	                 tmpRegion,
++	                 (mask & PAINT_SCREEN_TRANSFORMED_MASK));
+ 
+     /* paint all windows from bottom to top */
+     foreach (w, pl)
+@@ -377,6 +410,7 @@ GLScreen::glEnableOutputClipping (const
+ {
+     WRAPABLE_HND_FUNCTN (glEnableOutputClipping, transform, region, output)
+ 
++    #ifndef USE_GLES
+     GLdouble h = screen->height ();
+ 
+     GLdouble p1[2] = { static_cast<GLdouble> (region.handle ()->extents.x1),
+@@ -409,6 +443,7 @@ GLScreen::glEnableOutputClipping (const
+     glEnable (GL_CLIP_PLANE3);
+ 
+     glPopMatrix ();
++    #endif
+ }
+ 
+ void
+@@ -416,10 +451,12 @@ GLScreen::glDisableOutputClipping ()
+ {
+     WRAPABLE_HND_FUNCTN (glDisableOutputClipping)
+ 
++    #ifndef USE_GLES
+     glDisable (GL_CLIP_PLANE0);
+     glDisable (GL_CLIP_PLANE1);
+     glDisable (GL_CLIP_PLANE2);
+     glDisable (GL_CLIP_PLANE3);
++    #endif
+ }
+ 
+ #define CLIP_PLANE_MASK (PAINT_SCREEN_TRANSFORMED_MASK | \
+@@ -449,26 +486,14 @@ GLScreen::glPaintTransformedOutput (cons
+ 	glEnableOutputClipping (sTransform, region, output);
+ 
+ 	sTransform.toScreenSpace (output, -sAttrib.zTranslate);
+-
+-	glPushMatrix ();
+-	glLoadMatrixf (sTransform.getMatrix ());
+-
+ 	priv->paintOutputRegion (sTransform, region, output, mask);
+ 
+-	glPopMatrix ();
+-
+ 	glDisableOutputClipping ();
+     }
+     else
+     {
+ 	sTransform.toScreenSpace (output, -sAttrib.zTranslate);
+-
+-	glPushMatrix ();
+-	glLoadMatrixf (sTransform.getMatrix ());
+-
+ 	priv->paintOutputRegion (sTransform, region, output, mask);
+-
+-	glPopMatrix ();
+     }
+ }
+ 
+@@ -503,13 +528,8 @@ GLScreen::glPaintOutput (const GLScreenP
+ 
+ 	sTransform.toScreenSpace (output, -DEFAULT_Z_CAMERA);
+ 
+-	glPushMatrix ();
+-	glLoadMatrixf (sTransform.getMatrix ());
+-
+ 	priv->paintOutputRegion (sTransform, region, output, mask);
+ 
+-	glPopMatrix ();
+-
+ 	return true;
+     }
+     else if (mask & PAINT_SCREEN_FULL_MASK)
+@@ -525,182 +545,260 @@ GLScreen::glPaintOutput (const GLScreenP
+     }
+ }
+ 
+-#define ADD_RECT(data, m, n, x1, y1, x2, y2)	   \
+-    for (it = 0; it < n; it++)			   \
+-    {						   \
+-        const GLTexture::Matrix &mat = m[it];	   \
+-	*(data)++ = COMP_TEX_COORD_X (mat, x1);    \
+-	*(data)++ = COMP_TEX_COORD_Y (mat, y1);    \
+-    }						   \
+-    *(data)++ = (x1);				   \
+-    *(data)++ = (y1);				   \
+-    *(data)++ = 0.0;				   \
+-    for (it = 0; it < n; it++)			   \
+-    {						   \
+-        const GLTexture::Matrix &mat = m[it];	   \
+-	*(data)++ = COMP_TEX_COORD_X (mat, x1);    \
+-	*(data)++ = COMP_TEX_COORD_Y (mat, y2);    \
+-    }						   \
+-    *(data)++ = (x1);				   \
+-    *(data)++ = (y2);				   \
+-    *(data)++ = 0.0;				   \
+-    for (it = 0; it < n; it++)			   \
+-    {						   \
+-        const GLTexture::Matrix &mat = m[it];	   \
+-	*(data)++ = COMP_TEX_COORD_X (mat, x2);    \
+-	*(data)++ = COMP_TEX_COORD_Y (mat, y2);    \
+-    }						   \
+-    *(data)++ = (x2);				   \
+-    *(data)++ = (y2);				   \
+-    *(data)++ = 0.0;				   \
+-    for (it = 0; it < n; it++)			   \
+-    {						   \
+-        const GLTexture::Matrix &mat = m[it];	   \
+-	*(data)++ = COMP_TEX_COORD_X (mat, x2);    \
+-	*(data)++ = COMP_TEX_COORD_Y (mat, y1);    \
+-    }						   \
+-    *(data)++ = (x2);				   \
+-    *(data)++ = (y1);				   \
+-    *(data)++ = 0.0
+-
+-#define ADD_QUAD(data, m, n, x1, y1, x2, y2)		\
+-    for (it = 0; it < n; it++)				\
+-    {							\
+-        const GLTexture::Matrix &mat = m[it];		\
+-	*(data)++ = COMP_TEX_COORD_XY (mat, x1, y1);	\
+-	*(data)++ = COMP_TEX_COORD_YX (mat, x1, y1);	\
+-    }							\
+-    *(data)++ = (x1);					\
+-    *(data)++ = (y1);					\
+-    *(data)++ = 0.0;					\
+-    for (it = 0; it < n; it++)				\
+-    {							\
+-        const GLTexture::Matrix &mat = m[it];		\
+-	*(data)++ = COMP_TEX_COORD_XY (mat, x1, y2);	\
+-	*(data)++ = COMP_TEX_COORD_YX (mat, x1, y2);	\
+-    }							\
+-    *(data)++ = (x1);					\
+-    *(data)++ = (y2);					\
+-    *(data)++ = 0.0;					\
+-    for (it = 0; it < n; it++)				\
+-    {							\
+-        const GLTexture::Matrix &mat = m[it];	        \
+-	*(data)++ = COMP_TEX_COORD_XY (mat, x2, y2);	\
+-	*(data)++ = COMP_TEX_COORD_YX (mat, x2, y2);	\
+-    }							\
+-    *(data)++ = (x2);					\
+-    *(data)++ = (y2);					\
+-    *(data)++ = 0.0;					\
+-    for (it = 0; it < n; it++)				\
+-    {							\
+-        const GLTexture::Matrix &mat = m[it];	        \
+-	*(data)++ = COMP_TEX_COORD_XY (mat, x2, y1);	\
+-	*(data)++ = COMP_TEX_COORD_YX (mat, x2, y1);	\
+-    }							\
+-    *(data)++ = (x2);					\
+-    *(data)++ = (y1);					\
+-    *(data)++ = 0.0;
+-
+ void
+-GLWindow::glDrawGeometry ()
++GLScreen::glPaintCompositedOutput (const CompRegion    &region,
++				   GLFramebufferObject *fbo,
++				   unsigned int         mask)
+ {
+-    WRAPABLE_HND_FUNCTN (glDrawGeometry)
+-
+-    int     texUnit = priv->geometry.texUnits;
+-    int     currentTexUnit = 0;
+-    int     stride = priv->geometry.vertexStride;
+-    GLfloat *vertices = priv->geometry.vertices + (stride - 3);
++    WRAPABLE_HND_FUNCTN (glPaintCompositedOutput, region, fbo, mask)
+ 
+-    stride *= sizeof (GLfloat);
++    GLMatrix sTransform;
++    std::vector<GLfloat> vertexData;
++    std::vector<GLfloat> textureData;
++    const GLTexture::Matrix & texmatrix = fbo->tex ()->matrix ();
++    GLVertexBuffer *streamingBuffer = GLVertexBuffer::streamingBuffer ();
++
++    streamingBuffer->begin (GL_TRIANGLES);
++
++    if (mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK)
++    {
++	GLfloat tx1 = COMP_TEX_COORD_X (texmatrix, 0.0f);
++	GLfloat tx2 = COMP_TEX_COORD_X (texmatrix, screen->width ());
++	GLfloat ty1 = 1.0 - COMP_TEX_COORD_Y (texmatrix, 0.0f);
++	GLfloat ty2 = 1.0 - COMP_TEX_COORD_Y (texmatrix, screen->height ());
++
++	vertexData = {
++	    0.0f,                    0.0f,                     0.0f,
++	    0.0f,                    (float)screen->height (), 0.0f,
++	    (float)screen->width (), 0.0f,                     0.0f,
++
++	    0.0f,                    (float)screen->height (), 0.0f,
++	    (float)screen->width (), (float)screen->height (), 0.0f,
++	    (float)screen->width (), 0.0f,                     0.0f,
++	};
++
++	textureData = {
++	    tx1, ty1,
++	    tx1, ty2,
++	    tx2, ty1,
++	    tx1, ty2,
++	    tx2, ty2,
++	    tx2, ty1,
++	};
+ 
+-    glVertexPointer (3, GL_FLOAT, stride, vertices);
+-
+-    while (texUnit--)
++	streamingBuffer->addVertices (6, &vertexData[0]);
++	streamingBuffer->addTexCoords (0, 6, &textureData[0]);
++    }
++    else
+     {
+-	if (texUnit != currentTexUnit)
++	BoxPtr pBox = const_cast <Region> (region.handle ())->rects;
++	int nBox = const_cast <Region> (region.handle ())->numRects;
++
++	while (nBox--)
+ 	{
+-	    (*GL::clientActiveTexture) (GL_TEXTURE0_ARB + texUnit);
+-	    glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+-	    currentTexUnit = texUnit;
++	    GLfloat tx1 = COMP_TEX_COORD_X (texmatrix, pBox->x1);
++	    GLfloat tx2 = COMP_TEX_COORD_X (texmatrix, pBox->x2);
++	    GLfloat ty1 = 1.0 - COMP_TEX_COORD_Y (texmatrix, pBox->y1);
++	    GLfloat ty2 = 1.0 - COMP_TEX_COORD_Y (texmatrix, pBox->y2);
++
++	    vertexData = {
++		(float)pBox->x1, (float)pBox->y1, 0.0f,
++		(float)pBox->x1, (float)pBox->y2, 0.0f,
++		(float)pBox->x2, (float)pBox->y1, 0.0f,
++
++		(float)pBox->x1, (float)pBox->y2, 0.0f,
++		(float)pBox->x2, (float)pBox->y2, 0.0f,
++		(float)pBox->x2, (float)pBox->y1, 0.0f,
++	    };
++
++	    textureData = {
++		tx1, ty1,
++		tx1, ty2,
++		tx2, ty1,
++		tx1, ty2,
++		tx2, ty2,
++		tx2, ty1,
++	    };
++
++	    streamingBuffer->addVertices (6, &vertexData[0]);
++	    streamingBuffer->addTexCoords (0, 6, &textureData[0]);
++	    pBox++;
+ 	}
+-	vertices -= priv->geometry.texCoordSize;
+-	glTexCoordPointer (priv->geometry.texCoordSize,
+-			   GL_FLOAT, stride, vertices);
+     }
+ 
+-    glDrawArrays (GL_QUADS, 0, priv->geometry.vCount);
+-
+-    /* disable all texture coordinate arrays except 0 */
+-    texUnit = priv->geometry.texUnits;
+-    if (texUnit > 1)
+-    {
+-	while (--texUnit)
+-	{
+-	    (*GL::clientActiveTexture) (GL_TEXTURE0_ARB + texUnit);
+-	    glDisableClientState (GL_TEXTURE_COORD_ARRAY);
+-	}
++    streamingBuffer->end ();
++    fbo->tex ()-> enable (GLTexture::Fast);
++    sTransform.toScreenSpace (&screen->fullscreenOutput (), -DEFAULT_Z_CAMERA);
++    streamingBuffer->render (sTransform);
++    fbo->tex ()-> disable ();
++}
+ 
+-	(*GL::clientActiveTexture) (GL_TEXTURE0_ARB);
++#define ADD_RECT(vertexBuffer, m, n, x1, y1, x2, y2) \
++    GLfloat vertexData[18] = {                       \
++	(float)x1, (float)y1, 0.0,                   \
++	(float)x1, (float)y2, 0.0,                   \
++	(float)x2, (float)y1, 0.0,                   \
++	(float)x2, (float)y1, 0.0,                   \
++	(float)x1, (float)y2, 0.0,                   \
++	(float)x2, (float)y2, 0.0                    \
++    };                                               \
++    vertexBuffer->addVertices (6, vertexData);       \
++                                                     \
++    for (it = 0; it < n; it++)                       \
++    {                                                \
++	GLfloat data[2];                             \
++	const GLTexture::Matrix &mat = m[it];        \
++	data[0] = COMP_TEX_COORD_X (mat, x1);        \
++	data[1] = COMP_TEX_COORD_Y (mat, y1);        \
++	vertexBuffer->addTexCoords (it, 1, data);    \
++    }                                                \
++    for (it = 0; it < n; it++)                       \
++    {                                                \
++	GLfloat data[2];                             \
++	const GLTexture::Matrix &mat = m[it];        \
++	data[0] = COMP_TEX_COORD_X (mat, x1);        \
++	data[1] = COMP_TEX_COORD_Y (mat, y2);        \
++	vertexBuffer->addTexCoords (it, 1, data);    \
++    }                                                \
++    for (it = 0; it < n; it++)                       \
++    {                                                \
++	GLfloat data[2];                             \
++	const GLTexture::Matrix &mat = m[it];        \
++	data[0] = COMP_TEX_COORD_X (mat, x2);        \
++	data[1] = COMP_TEX_COORD_Y (mat, y1);        \
++	vertexBuffer->addTexCoords (it, 1, data);    \
++    }                                                \
++    for (it = 0; it < n; it++)                       \
++    {                                                \
++	GLfloat data[2];                             \
++	const GLTexture::Matrix &mat = m[it];        \
++	data[0] = COMP_TEX_COORD_X (mat, x2);        \
++	data[1] = COMP_TEX_COORD_Y (mat, y1);        \
++	vertexBuffer->addTexCoords (it, 1, data);    \
++    }                                                \
++    for (it = 0; it < n; it++)                       \
++    {                                                \
++	GLfloat data[2];                             \
++	const GLTexture::Matrix &mat = m[it];        \
++	data[0] = COMP_TEX_COORD_X (mat, x1);        \
++	data[1] = COMP_TEX_COORD_Y (mat, y2);        \
++	vertexBuffer->addTexCoords (it, 1, data);    \
++    }                                                \
++    for (it = 0; it < n; it++)                       \
++    {                                                \
++	GLfloat data[2];                             \
++	const GLTexture::Matrix &mat = m[it];        \
++	data[0] = COMP_TEX_COORD_X (mat, x2);        \
++	data[1] = COMP_TEX_COORD_Y (mat, y2);        \
++	vertexBuffer->addTexCoords (it, 1, data);    \
++    }
++
++#define ADD_QUAD(vertexBuffer, m, n, x1, y1, x2, y2) \
++    GLfloat vertexData[18] = {                       \
++	(float)x1, (float)y1, 0.0,                   \
++	(float)x1, (float)y2, 0.0,                   \
++	(float)x2, (float)y1, 0.0,                   \
++	(float)x2, (float)y1, 0.0,                   \
++	(float)x1, (float)y2, 0.0,                   \
++	(float)x2, (float)y2, 0.0                    \
++    };                                               \
++    vertexBuffer->addVertices (6, vertexData);       \
++                                                     \
++    for (it = 0; it < n; it++)                       \
++    {                                                \
++	GLfloat data[2];                             \
++	const GLTexture::Matrix &mat = m[it];        \
++	data[0] = COMP_TEX_COORD_XY (mat, x1, y1);   \
++	data[1] = COMP_TEX_COORD_YX (mat, x1, y1);   \
++	vertexBuffer->addTexCoords (it, 1, data);    \
++    }                                                \
++    for (it = 0; it < n; it++)                       \
++    {                                                \
++	GLfloat data[2];                             \
++	const GLTexture::Matrix &mat = m[it];        \
++	data[0] = COMP_TEX_COORD_XY (mat, x1, y2);   \
++	data[1] = COMP_TEX_COORD_YX (mat, x1, y2);   \
++	vertexBuffer->addTexCoords (it, 1, data);    \
++    }                                                \
++    for (it = 0; it < n; it++)                       \
++    {                                                \
++	GLfloat data[2];                             \
++	const GLTexture::Matrix &mat = m[it];        \
++	data[0] = COMP_TEX_COORD_XY (mat, x2, y1);   \
++	data[1] = COMP_TEX_COORD_YX (mat, x2, y1);   \
++	vertexBuffer->addTexCoords (it, 1, data);    \
++    }                                                \
++    for (it = 0; it < n; it++)                       \
++    {                                                \
++	GLfloat data[2];                             \
++	const GLTexture::Matrix &mat = m[it];        \
++	data[0] = COMP_TEX_COORD_XY (mat, x2, y1);   \
++	data[1] = COMP_TEX_COORD_YX (mat, x2, y1);   \
++	vertexBuffer->addTexCoords (it, 1, data);    \
++    }                                                \
++    for (it = 0; it < n; it++)                       \
++    {                                                \
++	GLfloat data[2];                             \
++	const GLTexture::Matrix &mat = m[it];        \
++	data[0] = COMP_TEX_COORD_XY (mat, x1, y2);   \
++	data[1] = COMP_TEX_COORD_YX (mat, x1, y2);   \
++	vertexBuffer->addTexCoords (it, 1, data);    \
++    }                                                \
++    for (it = 0; it < n; it++)                       \
++    {                                                \
++	GLfloat data[2];                             \
++	const GLTexture::Matrix &mat = m[it];        \
++	data[0] = COMP_TEX_COORD_XY (mat, x2, y2);   \
++	data[1] = COMP_TEX_COORD_YX (mat, x2, y2);   \
++	vertexBuffer->addTexCoords (it, 1, data);    \
+     }
+-}
++
+ 
+ static inline void
+-addSingleQuad (GLfloat      *&d,
+-	       const        GLTexture::MatrixList &matrix,
+-	       unsigned int nMatrix,
+-	       int          x1,
+-	       int          y1,
+-	       int          x2,
+-	       int          y2,
+-	       int          &n,
+-	       bool         rect)
++addSingleQuad (GLVertexBuffer *vertexBuffer,
++               const GLTexture::MatrixList &matrix,
++               unsigned int nMatrix,
++               int          x1,
++               int          y1,
++               int          x2,
++               int          y2,
++               int          &n,
++               bool         rect)
+ {
+     unsigned int it;
+ 
+     if (rect)
+     {
+-	ADD_RECT (d, matrix, nMatrix, x1, y1, x2, y2);
++	ADD_RECT (vertexBuffer, matrix, nMatrix, x1, y1, x2, y2);
+     }
+     else
+     {
+-	ADD_QUAD (d, matrix, nMatrix, x1, y1, x2, y2);
++	ADD_QUAD (vertexBuffer, matrix, nMatrix, x1, y1, x2, y2);
+     }
+     n++;
+ }
+ 
+ static inline void
+-addQuads (GLfloat      *&d,
+-	  const        GLTexture::MatrixList &matrix,
+-	  unsigned int nMatrix,
+-	  int          x1,
+-	  int          y1,
+-	  int          x2,
+-	  int          y2,
+-	  int          &n,
+-	  int          vSize,
+-	  bool         rect,
+-	  GLWindow::Geometry &geometry,
+-	  unsigned int maxGridWidth,
+-	  unsigned int maxGridHeight)
++addQuads (GLVertexBuffer *vertexBuffer,
++          const GLTexture::MatrixList &matrix,
++          unsigned int nMatrix,
++          int          x1,
++          int          y1,
++          int          x2,
++          int          y2,
++          int          &n,
++          bool         rect,
++          unsigned int maxGridWidth,
++          unsigned int maxGridHeight)
+ {
+     int nQuadsX = (maxGridWidth == MAXSHORT) ? 1 :
+ 	1 + (x2 - x1 - 1) / (int) maxGridWidth;  // ceil. division
+     int nQuadsY = (maxGridHeight == MAXSHORT) ? 1 :
+ 	1 + (y2 - y1 - 1) / (int) maxGridHeight;
+-    int newVertexSize = (n + nQuadsX * nQuadsY) * vSize * 4;
+-
+-    // Make sure enough vertices are allocated for nQuadsX * nQuadsY more quads
+-    if (newVertexSize > geometry.vertexSize)
+-    {
+-	if (!geometry.moreVertices (newVertexSize))
+-	    return;
+-
+-	d = geometry.vertices + (n * vSize * 4);
+-    }
+ 
+     if (nQuadsX == 1 && nQuadsY == 1)
+     {
+-	addSingleQuad (d, matrix, nMatrix, x1, y1, x2, y2, n, rect);
++	addSingleQuad (vertexBuffer, matrix, nMatrix, x1, y1, x2, y2, n, rect);
+     }
+     else
+     {
+@@ -716,7 +814,8 @@ addQuads (GLfloat      *&d,
+ 	    {
+ 		nx2 = MIN (nx1 + (int) quadWidth, x2);
+ 
+-		addSingleQuad (d, matrix, nMatrix, nx1, ny1, nx2, ny2, n, rect);
++		addSingleQuad (vertexBuffer, matrix, nMatrix,
++		               nx1, ny1, nx2, ny2, n, rect);
+ 	    }
+ 	}
+     }
+@@ -729,13 +828,11 @@ GLWindow::glAddGeometry (const GLTexture
+ 			 unsigned int                maxGridWidth,
+ 			 unsigned int                maxGridHeight)
+ {
+-    WRAPABLE_HND_FUNCTN (glAddGeometry, matrix, region, clip)
++    WRAPABLE_HND_FUNCTN (glAddGeometry, matrix, region, clip, maxGridWidth, maxGridHeight)
+ 
+     BoxRec full;
+     int    nMatrix = matrix.size ();
+ 
+-    priv->geometry.texUnits = nMatrix;
+-
+     full = clip.handle ()->extents;
+     if (region.handle ()->extents.x1 > full.x1)
+ 	full.x1 = region.handle ()->extents.x1;
+@@ -753,9 +850,7 @@ GLWindow::glAddGeometry (const GLTexture
+ 	BoxPtr  pClip;
+ 	int     nClip;
+ 	BoxRec  cbox;
+-	int     vSize;
+ 	int     n, it, x1, y1, x2, y2;
+-	GLfloat *d;
+ 	bool    rect = true;
+ 
+ 	for (it = 0; it < nMatrix; it++)
+@@ -770,18 +865,6 @@ GLWindow::glAddGeometry (const GLTexture
+ 	pBox = const_cast <Region> (region.handle ())->rects;
+ 	nBox = const_cast <Region> (region.handle ())->numRects;
+ 
+-	vSize = 3 + nMatrix * 2;
+-
+-	n = priv->geometry.vCount / 4;
+-
+-	if ((n + nBox) * vSize * 4 > priv->geometry.vertexSize)
+-	{
+-	    if (!priv->geometry.moreVertices ((n + nBox) * vSize * 4))
+-		return;
+-	}
+-
+-	d = priv->geometry.vertices + (priv->geometry.vCount * vSize);
+-
+ 	while (nBox--)
+ 	{
+ 	    x1 = pBox->x1;
+@@ -806,24 +889,15 @@ GLWindow::glAddGeometry (const GLTexture
+ 
+ 		if (nClip == 1)
+ 		{
+-		    addQuads (d, matrix, nMatrix,
++		    addQuads (priv->vertexBuffer, matrix, nMatrix,
+ 			      x1, y1, x2, y2,
+-			      n, vSize, rect, priv->geometry,
++			      n, rect,
+ 			      maxGridWidth, maxGridHeight);
+ 		}
+ 		else
+ 		{
+ 		    pClip = const_cast <Region> (clip.handle ())->rects;
+ 
+-		    if (((n + nClip) * vSize * 4) > priv->geometry.vertexSize)
+-		    {
+-			if (!priv->geometry.moreVertices ((n + nClip) *
+-							  vSize * 4))
+-			    return;
+-
+-			d = priv->geometry.vertices + (n * vSize * 4);
+-		    }
+-
+ 		    while (nClip--)
+ 		    {
+ 			cbox = *pClip;
+@@ -841,120 +915,32 @@ GLWindow::glAddGeometry (const GLTexture
+ 
+ 			if (cbox.x1 < cbox.x2 && cbox.y1 < cbox.y2)
+ 			{
+-			    addQuads (d, matrix, nMatrix,
++			    addQuads (priv->vertexBuffer, matrix, nMatrix,
+ 				      cbox.x1, cbox.y1, cbox.x2, cbox.y2,
+-				      n, vSize, rect, priv->geometry,
++				      n, rect,
+ 				      maxGridWidth, maxGridHeight);
+ 			}
+ 		    }
+ 		}
+ 	    }
+ 	}
+-
+-	priv->geometry.vCount       = n * 4;
+-	priv->geometry.vertexStride = vSize;
+-	priv->geometry.texCoordSize = 2;
+-    }
+-}
+-
+-static bool
+-enableFragmentProgramAndDrawGeometry (GLScreen	         *gs,
+-				      GLWindow           *w,
+-				      GLTexture          *texture,
+-				      GLFragment::Attrib &attrib,
+-				      GLTexture::Filter  filter,
+-				      unsigned int       mask)
+-{
+-    GLFragment::Attrib fa (attrib);
+-    bool               blending;
+-
+-    if (GL::canDoSaturated && attrib.getSaturation () != COLOR)
+-    {
+-	int param, function;
+-
+-	param    = fa.allocParameters (1);
+-	function =
+-	    GLFragment::getSaturateFragmentFunction (texture, param);
+-
+-	fa.addFunction (function);
+-
+-	(*GL::programEnvParameter4f) (GL_FRAGMENT_PROGRAM_ARB, param,
+-				      RED_SATURATION_WEIGHT,
+-				      GREEN_SATURATION_WEIGHT,
+-				      BLUE_SATURATION_WEIGHT,
+-				      attrib.getSaturation () / 65535.0f);
+-    }
+-
+-    if (!fa.enable (&blending))
+-	return false;
+-
+-    texture->enable (filter);
+-
+-    if (mask & PAINT_WINDOW_BLEND_MASK)
+-    {
+-	if (blending)
+-	    glEnable (GL_BLEND);
+-
+-	if (attrib.getOpacity () != OPAQUE || attrib.getBrightness () != BRIGHT)
+-	{
+-	    GLushort color;
+-
+-	    color = (attrib.getOpacity () * attrib.getBrightness ()) >> 16;
+-
+-	    gs->setTexEnvMode (GL_MODULATE);
+-	    glColor4us (color, color, color, attrib.getOpacity ());
+-
+-	    w->glDrawGeometry ();
+-
+-	    glColor4usv (defaultColor);
+-	    gs->setTexEnvMode (GL_REPLACE);
+-	}
+-	else
+-	{
+-	    w->glDrawGeometry ();
+-	}
+-
+-	if (blending)
+-	    glDisable (GL_BLEND);
+-    }
+-    else if (attrib.getBrightness () != BRIGHT)
+-    {
+-	gs->setTexEnvMode (GL_MODULATE);
+-	glColor4us (attrib.getBrightness (), attrib.getBrightness (),
+-		    attrib.getBrightness (), BRIGHT);
+-
+-	w->glDrawGeometry ();
+-
+-	glColor4usv (defaultColor);
+-	gs->setTexEnvMode (GL_REPLACE);
+     }
+-    else
+-    {
+-	w->glDrawGeometry ();
+-    }
+-
+-    texture->disable ();
+-
+-    fa.disable ();
+-
+-    return true;
+ }
+ 
++#ifndef USE_GLES
+ static void
+-enableFragmentOperationsAndDrawGeometry (GLScreen	    *gs,
+-					 GLWindow	    *w,
+-					 GLTexture	    *texture,
+-					 GLFragment::Attrib &attrib,
+-					 GLTexture::Filter  filter,
+-					 unsigned int	    mask)
++enableLegacyOBSAndRender (GLScreen                  *gs,
++                          GLWindow                  *w,
++                          GLTexture                 *texture,
++                          const GLMatrix            &transform,
++                          const GLWindowPaintAttrib &attrib,
++                          GLTexture::Filter         filter,
++                          unsigned int              mask)
+ {
+-    if (GL::canDoSaturated && attrib.getSaturation () != COLOR)
++    if (GL::canDoSaturated && attrib.saturation != COLOR)
+     {
+ 	GLfloat constant[4];
+ 
+-	if (mask & PAINT_WINDOW_BLEND_MASK)
+-	    glEnable (GL_BLEND);
+-
+ 	texture->enable (filter);
+ 
+ 	glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
+@@ -985,7 +971,7 @@ enableFragmentOperationsAndDrawGeometry
+ 	glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
+ 	glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
+ 
+-	if (GL::canDoSlightlySaturated && attrib.getSaturation () > 0)
++	if (GL::canDoSlightlySaturated && attrib.saturation > 0)
+ 	{
+ 	    glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
+ 	    glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
+@@ -1016,20 +1002,20 @@ enableFragmentOperationsAndDrawGeometry
+ 	    glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
+ 	    glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
+ 
+-	    constant[3] = attrib.getSaturation () / 65535.0f;
++	    constant[3] = attrib.saturation / 65535.0f;
+ 
+ 	    glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant);
+ 
+-	    if (attrib.getOpacity () < OPAQUE ||
+-		attrib.getBrightness () != BRIGHT)
++	    if (attrib.opacity < OPAQUE ||
++		attrib.brightness != BRIGHT)
+ 	    {
+ 		GL::activeTexture (GL_TEXTURE3_ARB);
+ 
+ 		texture->enable (filter);
+ 
+-		constant[3] = attrib.getOpacity () / 65535.0f;
++		constant[3] = attrib.opacity / 65535.0f;
+ 		constant[0] = constant[1] = constant[2] = constant[3] *
+-		    attrib.getBrightness () / 65535.0f;
++		    attrib.brightness / 65535.0f;
+ 
+ 		glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant);
+ 
+@@ -1047,7 +1033,7 @@ enableFragmentOperationsAndDrawGeometry
+ 		glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
+ 		glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
+ 
+-		w->glDrawGeometry ();
++		w->vertexBuffer ()->render (transform, attrib);
+ 
+ 		texture->disable ();
+ 
+@@ -1057,7 +1043,7 @@ enableFragmentOperationsAndDrawGeometry
+ 	    }
+ 	    else
+ 	    {
+-		w->glDrawGeometry ();
++		w->vertexBuffer ()->render (transform, attrib);
+ 	    }
+ 
+ 	    texture->disable ();
+@@ -1074,9 +1060,9 @@ enableFragmentOperationsAndDrawGeometry
+ 	    glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
+ 	    glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
+ 
+-	    constant[3] = attrib.getOpacity () / 65535.0f;
++	    constant[3] = attrib.opacity / 65535.0f;
+ 	    constant[0] = constant[1] = constant[2] = constant[3] *
+-			  attrib.getBrightness ()/ 65535.0f;
++			  attrib.brightness / 65535.0f;
+ 
+ 	    constant[0] = 0.5f + 0.5f * RED_SATURATION_WEIGHT   * constant[0];
+ 	    constant[1] = 0.5f + 0.5f * GREEN_SATURATION_WEIGHT * constant[1];
+@@ -1084,7 +1070,7 @@ enableFragmentOperationsAndDrawGeometry
+ 
+ 	    glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant);
+ 
+-	    w->glDrawGeometry ();
++	    w->vertexBuffer ()->render (transform, attrib);
+ 	}
+ 
+ 	texture->disable ();
+@@ -1097,9 +1083,6 @@ enableFragmentOperationsAndDrawGeometry
+ 
+ 	glColor4usv (defaultColor);
+ 	gs->setTexEnvMode (GL_REPLACE);
+-
+-	if (mask & PAINT_WINDOW_BLEND_MASK)
+-	    glDisable (GL_BLEND);
+     }
+     else
+     {
+@@ -1107,57 +1090,64 @@ enableFragmentOperationsAndDrawGeometry
+ 
+ 	if (mask & PAINT_WINDOW_BLEND_MASK)
+ 	{
+-	    glEnable (GL_BLEND);
+-	    if (attrib.getOpacity ()!= OPAQUE ||
+-		attrib.getBrightness () != BRIGHT)
++	    if (attrib.opacity != OPAQUE ||
++		attrib.brightness != BRIGHT)
+ 	    {
+ 		GLushort color;
+ 
+-		color = (attrib.getOpacity () * attrib.getBrightness ()) >> 16;
++		color = (attrib.opacity * attrib.brightness) >> 16;
+ 
+ 		gs->setTexEnvMode (GL_MODULATE);
+-		glColor4us (color, color, color, attrib.getOpacity ());
++		glColor4us (color, color, color, attrib.opacity);
+ 
+-		w->glDrawGeometry ();
++		w->vertexBuffer ()->render (transform, attrib);
+ 
+ 		glColor4usv (defaultColor);
+ 		gs->setTexEnvMode (GL_REPLACE);
+ 	    }
+ 	    else
+ 	    {
+-		w->glDrawGeometry ();
++		w->vertexBuffer ()->render (transform, attrib);
+ 	    }
+-
+-	    glDisable (GL_BLEND);
+ 	}
+-	else if (attrib.getBrightness () != BRIGHT)
++	else if (attrib.brightness != BRIGHT)
+ 	{
+ 	    gs->setTexEnvMode (GL_MODULATE);
+-	    glColor4us (attrib.getBrightness (), attrib.getBrightness (),
+-			attrib.getBrightness (), BRIGHT);
++	    glColor4us (attrib.brightness, attrib.brightness,
++			attrib.brightness, BRIGHT);
+ 
+-	    w->glDrawGeometry ();
++	    w->vertexBuffer ()->render (transform, attrib);
+ 
+ 	    glColor4usv (defaultColor);
+ 	    gs->setTexEnvMode (GL_REPLACE);
+ 	}
+ 	else
+ 	{
+-	    w->glDrawGeometry ();
++	    w->vertexBuffer ()->render (transform, attrib);
+ 	}
+ 
+ 	texture->disable ();
+     }
+ }
++#endif
+ 
+ void
+-GLWindow::glDrawTexture (GLTexture          *texture,
+-			 GLFragment::Attrib &attrib,
+-			 unsigned int       mask)
++GLWindow::glDrawTexture (GLTexture                 *texture,
++                         const GLMatrix            &transform,
++			 const GLWindowPaintAttrib &attrib,
++			 unsigned int              mask)
+ {
+-    WRAPABLE_HND_FUNCTN (glDrawTexture, texture, attrib, mask)
++    WRAPABLE_HND_FUNCTN (glDrawTexture, texture, transform, attrib, mask)
+ 
+     GLTexture::Filter filter;
++    GLboolean isBlendingEnabled = GL_FALSE;
++
++    // Enable blending if needed
++    if (mask & PAINT_WINDOW_BLEND_MASK) {
++	glGetBooleanv (GL_BLEND, &isBlendingEnabled);
++	if (!isBlendingEnabled)
++	    glEnable(GL_BLEND);
++    }
+ 
+     if (mask & (PAINT_WINDOW_TRANSFORMED_MASK |
+ 		PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK))
+@@ -1165,24 +1155,36 @@ GLWindow::glDrawTexture (GLTexture
+     else
+ 	filter = priv->gScreen->filter (NOTHING_TRANS_FILTER);
+ 
+-    if ((!attrib.hasFunctions () && (!priv->gScreen->lighting () ||
+-	 attrib.getSaturation () == COLOR || attrib.getSaturation () == 0)) ||
+-	!enableFragmentProgramAndDrawGeometry (priv->gScreen, this, texture,
+-					       attrib, filter, mask))
+-    {
+-	enableFragmentOperationsAndDrawGeometry (priv->gScreen, this, texture,
+-						 attrib, filter, mask);
+-    }
++    glActiveTexture(GL_TEXTURE0);
++    texture->enable (filter);
++
++    #ifdef USE_GLES
++    priv->vertexBuffer->render (transform, attrib);
++    #else
++
++    if (!GL::vbo && !GL::shaders)
++	enableLegacyOBSAndRender (priv->gScreen, this, texture, transform,
++                                  attrib, filter, mask);
++    else
++	priv->vertexBuffer->render (transform, attrib);
++    #endif
++
++    priv->shaders.clear ();
++    texture->disable ();
++
++    // Reset blending to old value
++    if ((mask & PAINT_WINDOW_BLEND_MASK) && !isBlendingEnabled)
++	glDisable(GL_BLEND);
+ }
+ 
+ bool
+-GLWindow::glDraw (const GLMatrix     &transform,
+-		  GLFragment::Attrib &fragment,
+-		  const CompRegion   &region,
+-		  unsigned int       mask)
++GLWindow::glDraw (const GLMatrix            &transform,
++		  const GLWindowPaintAttrib &attrib,
++		  const CompRegion          &region,
++		  unsigned int              mask)
+ {
+     WRAPABLE_HND_FUNCTN_RETURN (bool, glDraw, transform,
+-			      fragment, region, mask)
++			      attrib, region, mask)
+ 
+     const CompRegion &reg = (mask & PAINT_WINDOW_TRANSFORMED_MASK) ?
+                             infiniteRegion : region;
+@@ -1213,10 +1215,11 @@ GLWindow::glDraw (const GLMatrix     &tr
+     if (priv->textures.size () == 1)
+     {
+ 	ml[0] = priv->matrices[0];
+-	priv->geometry.reset ();
++	priv->vertexBuffer->begin ();
+ 	glAddGeometry (ml, priv->window->region (), reg);
+-	if (priv->geometry.vCount)
+-	    glDrawTexture (priv->textures[0], fragment, mask);
++	priv->vertexBuffer->end ();
++
++	glDrawTexture (priv->textures[0], transform, attrib, mask);
+     }
+     else
+     {
+@@ -1225,10 +1228,11 @@ GLWindow::glDraw (const GLMatrix     &tr
+ 	for (unsigned int i = 0; i < priv->textures.size (); i++)
+ 	{
+ 	    ml[0] = priv->matrices[i];
+-	    priv->geometry.reset ();
++	    priv->vertexBuffer->begin ();
+ 	    glAddGeometry (ml, priv->regions[i], reg);
+-	    if (priv->geometry.vCount)
+-		glDrawTexture (priv->textures[i], fragment, mask);
++	    priv->vertexBuffer->end ();
++
++	    glDrawTexture (priv->textures[i], transform, attrib, mask);
+ 	}
+     }
+ 
+@@ -1243,7 +1247,6 @@ GLWindow::glPaint (const GLWindowPaintAt
+ {
+     WRAPABLE_HND_FUNCTN_RETURN (bool, glPaint, attrib, transform, region, mask)
+ 
+-    GLFragment::Attrib fragment (attrib);
+     bool               status;
+ 
+     priv->lastPaint = attrib;
+@@ -1273,18 +1276,7 @@ GLWindow::glPaint (const GLWindowPaintAt
+     if (mask & PAINT_WINDOW_NO_CORE_INSTANCE_MASK)
+ 	return true;
+ 
+-    if (mask & PAINT_WINDOW_TRANSFORMED_MASK ||
+-        mask & PAINT_WINDOW_WITH_OFFSET_MASK)
+-    {
+-	glPushMatrix ();
+-	glLoadMatrixf (transform.getMatrix ());
+-    }
+-
+-    status = glDraw (transform, fragment, region, mask);
+-
+-    if (mask & PAINT_WINDOW_TRANSFORMED_MASK ||
+-        mask & PAINT_WINDOW_WITH_OFFSET_MASK)
+-	glPopMatrix ();
++    status = glDraw (transform, attrib, region, mask);
+ 
+     return status;
+ }
+--- /dev/null
++++ compiz-0.9.7.6/plugins/opengl/src/shadercache.cpp
+@@ -0,0 +1,246 @@
++/*
++ * Copyright © 2012 Linaro Ltd.
++ *
++ * Permission to use, copy, modify, distribute, and sell this software
++ * and its documentation for any purpose is hereby granted without
++ * fee, provided that the above copyright notice appear in all copies
++ * and that both that copyright notice and this permission notice
++ * appear in supporting documentation, and that the name of
++ * Linaro Ltd. not be used in advertising or publicity pertaining to
++ * distribution of the software without specific, written prior permission.
++ * Linaro Ltd. makes no representations about the suitability of this
++ * software for any purpose. It is provided "as is" without express or
++ * implied warranty.
++ *
++ * LINARO LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
++ * NO EVENT SHALL LINARO LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
++ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
++ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
++ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
++ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ *
++ * Authors: Alexandros Frantzis <alexandros.frantzis@xxxxxxxxxx>
++ */
++#include <map>
++#include <sstream>
++
++#include <opengl/shadercache.h>
++
++/** 
++ * Compares two GLShaderParameters objects.
++ */
++class GLShaderParametersComparer
++{
++public:
++    bool operator()(const GLShaderParameters &left, const GLShaderParameters &right) const
++    {
++        return left.hash() < right.hash();
++    }
++
++};
++
++typedef std::map<GLShaderParameters, GLShaderData, GLShaderParametersComparer> ShaderMapType;
++
++/** 
++ * Private data for GLPrivate
++ */
++class PrivateShaderCache
++{
++public:
++    PrivateShaderCache() {}
++
++    ShaderMapType::const_iterator addShaderData(const GLShaderParameters &params);
++
++    std::string createVertexShader (const GLShaderParameters &params);
++    std::string createFragmentShader (const GLShaderParameters &params);
++
++    ShaderMapType shaderMap;
++};
++
++/**********************
++ * GLShaderParameters *
++ **********************/
++
++int
++GLShaderParameters::hash() const
++{
++    return static_cast<int>(opacity) |
++           (static_cast<int>(brightness) << 1) |
++           (static_cast<int>(saturation) << 2) |
++           (static_cast<int>(color) << 3) |
++           (static_cast<int>(normal) << 5) |
++           (static_cast<int>(numTextures) << 8);
++}
++
++std::string
++GLShaderParameters::id() const
++{
++    std::stringstream ss;
++
++    ss << (opacity ? "t" : "f");
++    ss << (brightness ? "t" : "f");
++    ss << (saturation ? "t" : "f");
++    ss << (color == GLShaderVariableNone ? "n" :
++           color == GLShaderVariableUniform ? "u" : "v");
++
++    ss << (normal == GLShaderVariableNone ? "n" :
++           normal == GLShaderVariableUniform ? "u" : "v");
++    ss << numTextures;
++
++    return ss.str();
++}
++
++/*****************
++ * GLShaderCache *
++ *****************/
++
++GLShaderCache::GLShaderCache () :
++    priv (new PrivateShaderCache ())
++{
++}
++
++const GLShaderData &
++GLShaderCache::getShaderData (const GLShaderParameters &params)
++{
++    ShaderMapType::const_iterator iter;
++
++    // Try to find a cached shader pair that matches the parameters.
++    // If we don't have it cached, create it.
++    if ((iter = priv->shaderMap.find (params)) == priv->shaderMap.end ())
++        iter = priv->addShaderData (params);
++
++    return iter->second;
++}
++
++/**********************
++ * PrivateShaderCache *
++ **********************/
++
++ShaderMapType::const_iterator
++PrivateShaderCache::addShaderData (const GLShaderParameters &params)
++{
++    GLShaderData shaderData;
++
++    shaderData.name = params.id ();
++    shaderData.fragmentShader = createFragmentShader (params);
++    shaderData.vertexShader = createVertexShader (params);
++
++    std::pair<ShaderMapType::iterator, bool> ret =
++        shaderMap.insert(std::pair<GLShaderParameters, GLShaderData>(params,shaderData));
++
++    return ret.first;
++}
++
++/** 
++ * Creates a minimal vertex shader that can handle the GLShaderParameters.
++ * 
++ * @param params the GLShaderParameters the created shader should handle.
++ * 
++ * @return the shader string
++ */
++std::string
++PrivateShaderCache::createVertexShader (const GLShaderParameters &params)
++{
++    std::stringstream ss;
++
++    ss << "#ifdef GL_ES\n" <<
++          "precision mediump float;\n" <<
++          "#endif\n";
++
++    ss << "uniform mat4 modelview;\n" <<
++          "uniform mat4 projection;\n";
++
++    ss << "attribute vec3 position;\n" <<
++          "attribute vec3 normal;\n" <<
++          "attribute vec4 color;\n" <<
++          "attribute vec2 texCoord0;\n" <<
++          "attribute vec2 texCoord1;\n" <<
++          "attribute vec2 texCoord2;\n" <<
++          "attribute vec2 texCoord3;\n";
++
++    ss << "@VERTEX_FUNCTIONS@\n";
++
++    if (params.color == GLShaderVariableVarying)
++        ss << "varying vec4 vColor;\n";
++
++    for (int i = 0; i < params.numTextures; i++)
++        ss << "varying vec2 vTexCoord" << i << ";\n";
++
++    ss << "void main() {\n";
++
++    for (int i = 0; i < params.numTextures; i++)
++        ss << "vTexCoord" << i << " = texCoord" << i <<";\n";
++
++    if (params.color == GLShaderVariableVarying)
++        ss << "vColor = color;\n";
++
++    ss << "gl_Position = projection * modelview * vec4(position, 1.0);\n";
++
++    ss << "@VERTEX_FUNCTION_CALLS@\n}";
++
++    return ss.str();
++}
++
++/** 
++ * Creates a minimal fragment shader that can handle the GLShaderParameters.
++ * 
++ * @param params the GLShaderParameters the created shader should handle.
++ * 
++ * @return the shader string
++ */
++std::string
++PrivateShaderCache::createFragmentShader (const GLShaderParameters &params)
++{
++    std::stringstream ss;
++    ss << "#ifdef GL_ES\n" <<
++          "precision mediump float;\n" <<
++          "#endif\n";
++
++    ss << "uniform vec3 paintAttrib;\n";
++
++    for (int i = 0; i < params.numTextures; i++) {
++        ss << "uniform sampler2D texture" << i << ";\n";
++        ss << "varying vec2 vTexCoord" << i << ";\n";
++    }
++
++    if (params.color == GLShaderVariableUniform)
++        ss << "uniform vec4 singleColor;\n";
++    else if (params.color == GLShaderVariableVarying)
++        ss << "varying vec4 vColor;\n";
++
++    ss << "@FRAGMENT_FUNCTIONS@\n";
++
++    ss << "void main() {\n vec4 color = ";
++
++    if (params.color == GLShaderVariableUniform)
++        ss << "singleColor *";
++    else if (params.color == GLShaderVariableVarying)
++        ss << "vColor *";
++
++    for (int i = 0; i < params.numTextures; i++)
++        ss << " texture2D(texture" << i << ", vTexCoord" << i << ") *";
++
++    ss << " 1.0;\n";
++
++    if (params.saturation) {
++	ss << "vec3 desaturated = color.rgb * vec3 (0.30, 0.59, 0.11);\n" <<
++	      "desaturated = vec3 (dot (desaturated, color.rgb));\n" <<
++	      "color.rgb = color.rgb * vec3 (paintAttrib.z) + desaturated *\n" <<
++	      "            vec3 (1.0 - paintAttrib.z);\n";
++    }
++
++    if (params.brightness) {
++	ss << "color.rgb = color.rgb * paintAttrib.y" <<
++	      (params.opacity ? " * paintAttrib.x;\n" : ";\n") <<
++	      (params.opacity ? "color.a = color.a * paintAttrib.x;\n" : "");
++    }
++    else if (params.opacity) {
++	ss << "color = color * paintAttrib.x;\n";
++    }
++
++    ss << "gl_FragColor = color;\n";
++    ss << "@FRAGMENT_FUNCTION_CALLS@\n}";
++
++    return ss.str();
++}
+--- /dev/null
++++ compiz-0.9.7.6/plugins/opengl/include/opengl/framebufferobject.h
+@@ -0,0 +1,107 @@
++/*
++ * Copyright (c) 2011 Collabora, Ltd.
++ *
++ * Permission to use, copy, modify, distribute, and sell this software
++ * and its documentation for any purpose is hereby granted without
++ * fee, provided that the above copyright notice appear in all copies
++ * and that both that copyright notice and this permission notice
++ * appear in supporting documentation, and that the name of
++ * Collabora Ltd. not be used in advertising or publicity pertaining to
++ * distribution of the software without specific, written prior permission.
++ * Collabora Ltd. makes no representations about the suitability of this
++ * software for any purpose. It is provided "as is" without express or
++ * implied warranty.
++ *
++ * COLLABORA LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
++ * NO EVENT SHALL COLLABORA LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
++ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
++ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
++ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
++ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ *
++ * Authors: Pekka Paalanen <ppaalanen@xxxxxxxxx>
++ */
++
++#ifndef _COMPIZ_GLFRAMEBUFFEROBJECT_H
++#define _COMPIZ_GLFRAMEBUFFEROBJECT_H
++
++#include <opengl/opengl.h>
++
++struct PrivateGLFramebufferObject;
++
++/**
++ * Class representing a framebuffer object in GL, supporting only one
++ * color attachment as per GLES 2 spec. The color attachment is referred
++ * to as the texture (of the FBO).
++ *
++ * Usage:
++ * 1. create a GLFramebufferObject (requires a GL context)
++ * 2. call allocate (size), and check status ()
++ * 3. old = bind ()
++ * 4. do your rendering
++ * 5. rebind (old)
++ * 6. use the rendered texture via tex ()
++ * 7. go to 2 or 3, or delete to quit (requires a GL context)
++ *
++ * TODO: add depth/stencil attachments
++ * FIXME: written for OpenGL ES 2 only, desktop OpenGL might not work.
++ */
++class GLFramebufferObject
++{
++    public:
++	GLFramebufferObject ();
++	~GLFramebufferObject ();
++
++	/**
++	 * Ensure the texture is of the given size, recreating it if needed,
++	 * and replace the FBO color attachment with it. The texture contents
++	 * become undefined, unless specified in the 'image' argument.
++	 * When specifying 'image', it's also possible to pass-in the
++	 * desired image's 'format' and 'type'.
++	 *
++	 * Returns true on success, and false on texture allocation failure.
++	 */
++	bool allocate (const CompSize &size,
++		       const char *image = NULL,
++		       GLenum format = GL_RGBA,
++		       GLenum type = GL_UNSIGNED_BYTE);
++
++	/**
++	 * Bind this as the current FBO, previous binding in GL context is
++	 * undone. GL rendering is now targeted to this FBO.
++	 * Returns a pointer to the previously bound FBO, or NULL if
++	 * the previous binding was zero (the window system provided
++	 * framebuffer).
++	 *
++	 * The previous FBO is no longer bound, so you can use its
++	 * texture. To restore the previous FBO, call rebind (FBO) with
++	 * the returned pointer as the argument.
++	 */
++	GLFramebufferObject *bind ();
++
++	/**
++	 * Bind the given FBO as the current FBO, without looking up the
++	 * previous binding. The argument can be NULL, in which case the
++	 * window system provided framebuffer gets bound (FBO is unbound).
++	 */
++	static void rebind (GLFramebufferObject *fbo);
++
++	/**
++	 * Check the FBO completeness. Returns true on complete.
++	 * Otherwise returns false and reports the error to log.
++	 */
++	bool checkStatus ();
++
++	/**
++	 * Return a pointer to the texture that is the color attachment.
++	 * This will return NULL, if allocate () has not been called, or
++	 * the last allocate () call failed.
++	 */
++	GLTexture *tex ();
++
++    private:
++	PrivateGLFramebufferObject *priv;
++};
++
++#endif // _COMPIZ_GLFRAMEBUFFEROBJECT_H
+--- /dev/null
++++ compiz-0.9.7.6/plugins/opengl/include/opengl/program.h
+@@ -0,0 +1,75 @@
++/*
++ * Copyright © 2011 Linaro Ltd.
++ *
++ * Permission to use, copy, modify, distribute, and sell this software
++ * and its documentation for any purpose is hereby granted without
++ * fee, provided that the above copyright notice appear in all copies
++ * and that both that copyright notice and this permission notice
++ * appear in supporting documentation, and that the name of
++ * Linaro Ltd. not be used in advertising or publicity pertaining to
++ * distribution of the software without specific, written prior permission.
++ * Linaro Ltd. makes no representations about the suitability of this
++ * software for any purpose. It is provided "as is" without express or
++ * implied warranty.
++ *
++ * LINARO LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
++ * NO EVENT SHALL LINARO LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
++ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
++ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
++ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
++ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ *
++ * Authors: Travis Watkins <travis.watkins@xxxxxxxxxx>
++ */
++
++#ifndef _COMPIZ_GLPROGRAM_H
++#define _COMPIZ_GLPROGRAM_H
++
++#ifdef USE_GLES
++#include <GLES2/gl2.h>
++#else
++#include <GL/gl.h>
++#endif
++
++#include <core/core.h>
++#include <opengl/matrix.h>
++
++class PrivateProgram;
++
++class GLProgram
++{
++    public:
++	GLProgram (CompString &vertexShader, CompString &fragmentShader);
++	~GLProgram ();
++
++	bool valid ();
++	void bind ();
++	void unbind ();
++
++	bool setUniform   (const char *name, GLfloat value);
++	bool setUniform   (const char *name, GLint value);
++	bool setUniform   (const char *name, const GLMatrix &value);
++	bool setUniform2f (const char *name, GLfloat x, GLfloat y);
++	bool setUniform3f (const char *name, GLfloat x, GLfloat y, GLfloat z);
++	bool setUniform4f (const char *name,
++	                   GLfloat x,
++	                   GLfloat y,
++	                   GLfloat z,
++                           GLfloat w);
++	bool setUniform2i (const char *name, GLint x, GLint y);
++	bool setUniform3i (const char *name, GLint x, GLint y, GLint z);
++	bool setUniform4i (const char *name,
++	                   GLint x,
++	                   GLint y,
++	                   GLint z,
++                           GLint w);
++
++	GLuint attributeLocation (const char *name);
++
++    private:
++	PrivateProgram *priv;
++};
++
++#endif // _COMPIZ_GLPROGRAM_H
++
+--- /dev/null
++++ compiz-0.9.7.6/plugins/opengl/include/opengl/vertexbuffer.h
+@@ -0,0 +1,109 @@
++/*
++ * Copyright © 2011 Linaro Ltd.
++ *
++ * Permission to use, copy, modify, distribute, and sell this software
++ * and its documentation for any purpose is hereby granted without
++ * fee, provided that the above copyright notice appear in all copies
++ * and that both that copyright notice and this permission notice
++ * appear in supporting documentation, and that the name of
++ * Linaro Ltd. not be used in advertising or publicity pertaining to
++ * distribution of the software without specific, written prior permission.
++ * Linaro Ltd. makes no representations about the suitability of this
++ * software for any purpose. It is provided "as is" without express or
++ * implied warranty.
++ *
++ * LINARO LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
++ * NO EVENT SHALL LINARO LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
++ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
++ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
++ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
++ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ *
++ * Authors: Travis Watkins <travis.watkins@xxxxxxxxxx>
++ *          Frederic Plourde <frederic.plourde@xxxxxxxxxxxxxxx>
++ */
++
++#ifndef _COMPIZ_GLVERTEXBUFFER_H
++#define _COMPIZ_GLVERTEXBUFFER_H
++
++#ifdef USE_GLES
++#include <GLES2/gl2.h>
++#else
++#include <GL/gl.h>
++#endif
++
++#include <core/core.h>
++#include <opengl/program.h>
++#include <opengl/shadercache.h>
++
++class PrivateVertexBuffer;
++struct GLWindowPaintAttrib;
++
++class GLVertexBuffer
++{
++    public:
++	class AutoProgram
++	{
++	public:
++	    virtual GLProgram *getProgram(GLShaderParameters &params) = 0;
++	};
++
++	GLVertexBuffer ();
++	GLVertexBuffer (GLenum usage);
++	~GLVertexBuffer ();
++
++	static GLVertexBuffer *streamingBuffer ();
++
++	void begin (GLenum primitiveType);
++	// default primitiveType is GL_TRIANGLES
++	void begin ();
++	int end ();
++
++	// vertices and normals are 3 parts, count is number of xyz groups
++	void addVertices (GLuint nVertices, GLfloat *vertices);
++	void addNormals (GLuint nNormals, GLfloat *normals);
++
++	// color is always RGBA (4 parts), count is number of rgba groups
++	void addColors (GLuint nColors, GLushort *colors);
++
++	// texture is index, texcoords are 2 parts, count is number of pairs
++	void addTexCoords (GLuint texture,
++	                   GLuint nTexcoords,
++	                   GLfloat *texcoords);
++
++	void addUniform (const char *name, GLfloat value);
++	void addUniform (const char *name, GLint value);
++	bool addUniform (const char *name, const GLMatrix &value);
++	void addUniform2f (const char *name, GLfloat x, GLfloat y);
++	void addUniform3f (const char *name, GLfloat x, GLfloat y, GLfloat z);
++	void addUniform4f (const char *name, GLfloat x, GLfloat y,
++			                     GLfloat z, GLfloat w);
++	void addUniform2i (const char *name, GLint x, GLint y);
++	void addUniform3i (const char *name, GLint x, GLint y, GLint z);
++	void addUniform4i (const char *name, GLint x, GLint y,
++			                     GLint z, GLint w);
++
++	void setProgram (GLProgram *program);
++
++	void setAutoProgram (AutoProgram *autoProgram);
++
++	// This no-argument render () function is intended for use by plugins
++	// that have custom programs.
++	int render ();
++
++	int render (const GLMatrix &modelview);
++
++	int render (const GLMatrix            &modelview,
++	            const GLWindowPaintAttrib &attrib);
++
++	int render (const GLMatrix            &projection,
++	            const GLMatrix            &modelview,
++	            const GLWindowPaintAttrib &attrib);
++
++    private:
++	PrivateVertexBuffer *priv;
++};
++
++#endif // _COMPIZ_GLVERTEXBUFFER_H
++
+--- compiz-0.9.7.6.orig/plugins/opengl/include/opengl/texture.h
++++ compiz-0.9.7.6/plugins/opengl/include/opengl/texture.h
+@@ -32,7 +32,12 @@
+ #include "core/string.h"
+ 
+ #include <X11/Xlib-xcb.h>
++
++#ifdef USE_GLES
++#include <GLES2/gl2.h>
++#else
+ #include <GL/gl.h>
++#endif
+ 
+ #include <boost/function.hpp>
+ 
+--- /dev/null
++++ compiz-0.9.7.6/plugins/opengl/include/opengl/programcache.h
+@@ -0,0 +1,51 @@
++/*
++ * Copyright © 2011 Linaro Ltd.
++ *
++ * Permission to use, copy, modify, distribute, and sell this software
++ * and its documentation for any purpose is hereby granted without
++ * fee, provided that the above copyright notice appear in all copies
++ * and that both that copyright notice and this permission notice
++ * appear in supporting documentation, and that the name of
++ * Linaro Ltd. not be used in advertising or publicity pertaining to
++ * distribution of the software without specific, written prior permission.
++ * Linaro Ltd. makes no representations about the suitability of this
++ * software for any purpose. It is provided "as is" without express or
++ * implied warranty.
++ *
++ * LINARO LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
++ * NO EVENT SHALL LINARO LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
++ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
++ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
++ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
++ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ *
++ * Authors: Travis Watkins <travis.watkins@xxxxxxxxxx>
++ */
++
++#ifndef _COMPIZ_GLPROGRAMCACHE_H
++#define _COMPIZ_GLPROGRAMCACHE_H
++
++#include <string>
++#include <list>
++#include <map>
++#include <boost/bind.hpp>
++#include <opengl/program.h>
++
++class PrivateProgramCache;
++struct GLShaderData;
++
++class GLProgramCache
++{
++    private:
++	PrivateProgramCache *priv;
++
++    public:
++	GLProgramCache (size_t);
++	~GLProgramCache ();
++
++	GLProgram* operator () (std::list<const GLShaderData*>);
++};
++
++#endif // _COMPIZ_GLPROGRAMCACHE_H
++
+--- compiz-0.9.7.6.orig/plugins/opengl/include/opengl/matrix.h
++++ compiz-0.9.7.6/plugins/opengl/include/opengl/matrix.h
+@@ -44,6 +44,8 @@ class GLMatrix {
+ 	void reset ();
+ 	void toScreenSpace (const CompOutput *output, float z);
+ 
++	bool invert ();
++
+ 	void rotate (const float angle, const float x,
+ 		     const float y, const float z);
+ 	void rotate (const float angle, const GLVector& vector);
+--- /dev/null
++++ compiz-0.9.7.6/plugins/opengl/include/opengl/shadercache.h
+@@ -0,0 +1,100 @@
++/*
++ * Copyright © 2012 Linaro Ltd.
++ *
++ * Permission to use, copy, modify, distribute, and sell this software
++ * and its documentation for any purpose is hereby granted without
++ * fee, provided that the above copyright notice appear in all copies
++ * and that both that copyright notice and this permission notice
++ * appear in supporting documentation, and that the name of
++ * Linaro Ltd. not be used in advertising or publicity pertaining to
++ * distribution of the software without specific, written prior permission.
++ * Linaro Ltd. makes no representations about the suitability of this
++ * software for any purpose. It is provided "as is" without express or
++ * implied warranty.
++ *
++ * LINARO LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
++ * NO EVENT SHALL LINARO LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
++ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
++ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
++ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
++ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ *
++ * Authors: Alexandros Frantzis <alexandros.frantzis@xxxxxxxxxx>
++ */
++#ifndef GL_SHADER_CACHE_H_
++#define GL_SHADER_CACHE_H_
++
++#include <string>
++
++/**
++ * How to use a variable in a shader.
++ */
++enum GLShaderVariableType
++{
++    /** The variable is not used */
++    GLShaderVariableNone,
++    /** The variable value is held in a uniform */
++    GLShaderVariableUniform,
++    /** The variable value is held in a varying (from a vertex attribute) */
++    GLShaderVariableVarying,
++};
++
++/**
++ * Parameters that define a vertex-fragment shader pair.
++ */
++struct GLShaderParameters
++{
++    /** Whether this shader supports opacity */
++    bool opacity;
++    /** Whether this shader supports brightness */
++    bool brightness;
++    /** Whether this shader supports saturation */
++    bool saturation;
++    /** Whether this shader supports color and how */
++    GLShaderVariableType color;
++    /** Whether this shader supports normals and how */
++    GLShaderVariableType normal;
++    /** The number of textures this shader uses */
++    int numTextures;
++
++    /** Gets a minimalistic string representation of the parameters */
++    std::string id() const;
++    /** Gets a unique hash value for this set of parameters */
++    int hash() const;
++};
++
++/**
++ * An object representing a named vertex-fragment shader pair.
++ */
++struct GLShaderData
++{
++    std::string name;
++    std::string vertexShader;
++    std::string fragmentShader;
++};
++
++class PrivateShaderCache;
++
++/**
++ * A cache of vertex-fragment shader pairs (GLShaderData).
++ */
++class GLShaderCache
++{
++public:
++    GLShaderCache ();
++
++    /**
++     * Gets the GLShaderData associated with the specified parameters.
++     *
++     * @param params the parameters to get the GLShaderData for.
++     *
++     * @return the GLShaderData
++     */
++    const GLShaderData &getShaderData (const GLShaderParameters &params);
++
++private:
++    PrivateShaderCache *priv;
++};
++
++#endif
+--- compiz-0.9.7.6.orig/plugins/opengl/include/opengl/opengl.h
++++ compiz-0.9.7.6/plugins/opengl/include/opengl/opengl.h
+@@ -28,16 +28,45 @@
+ #ifndef _COMPIZ_OPENGL_H
+ #define _COMPIZ_OPENGL_H
+ 
++#ifdef USE_GLES
++#define SUPPORT_X11
++#include <GLES2/gl2.h>
++#include <GLES2/gl2ext.h>
++#include <EGL/egl.h>
++#include <EGL/eglext.h>
++#else
+ #include <GL/gl.h>
+ #include <GL/glx.h>
++#endif
++
++#include <core/size.h>
++#include <core/pluginclasshandler.h>
+ 
+ #include <opengl/matrix.h>
+ #include <opengl/texture.h>
+-#include <opengl/fragment.h>
++#include <opengl/framebufferobject.h>
++#include <opengl/vertexbuffer.h>
++#include <opengl/program.h>
++#include <opengl/programcache.h>
++#include <opengl/shadercache.h>
+ 
+ #define COMPIZ_OPENGL_ABI 4
+ 
+-#include <core/pluginclasshandler.h>
++#if !defined(GL_BGRA)
++    #if !defined(GL_BGRA_EXT)
++	#error GL_BGRA support is required
++    #else
++	#define GL_BGRA GL_BGRA_EXT
++    #endif
++#endif
++
++#if !defined(GL_BGRA)
++    #if !defined(GL_BGRA_EXT)
++	#error GL_BGRA support is required
++    #else
++	#define GL_BGRA GL_BGRA_EXT
++    #endif
++#endif
+ 
+ /**
+  * camera distance from screen, 0.5 * tan (FOV)
+@@ -75,8 +104,26 @@ extern GLushort   defaultColor[4];
+ #endif
+ 
+ namespace GL {
++    #ifdef USE_GLES
++    typedef EGLImageKHR (*EGLCreateImageKHRProc)  (EGLDisplay dpy,
++                                                   EGLContext ctx,
++                                                   EGLenum target,
++                                                   EGLClientBuffer buffer,
++                                                   const EGLint *attrib_list);
++    typedef EGLBoolean  (*EGLDestroyImageKHRProc) (EGLDisplay dpy,
++                                                   EGLImageKHR image);
++
++    typedef void (*GLEGLImageTargetTexture2DOESProc) (GLenum target,
++                                                      GLeglImageOES image);
++
++    typedef EGLBoolean (*EGLPostSubBufferNVProc) (EGLDisplay dpy,
++						  EGLSurface surface,
++						  EGLint x, EGLint y,
++						  EGLint width, EGLint height);
+ 
++    #else
+     typedef void (*FuncPtr) (void);
++
+     typedef FuncPtr (*GLXGetProcAddressProc) (const GLubyte *procName);
+ 
+     typedef void    (*GLXBindTexImageProc)    (Display	 *display,
+@@ -122,11 +169,6 @@ namespace GL {
+ 					      const int   *attribList);
+     typedef void      (*GLXDestroyPixmapProc) (Display *display,
+     					       GLXPixmap pixmap);
+-
+-    typedef void (*GLActiveTextureProc) (GLenum texture);
+-    typedef void (*GLClientActiveTextureProc) (GLenum texture);
+-    typedef void (*GLMultiTexCoord2fProc) (GLenum, GLfloat, GLfloat);
+-
+     typedef void (*GLGenProgramsProc) (GLsizei n,
+ 				       GLuint  *programs);
+     typedef void (*GLDeleteProgramsProc) (GLsizei n,
+@@ -146,11 +188,16 @@ namespace GL {
+     typedef void (*GLGetProgramivProc) (GLenum target,
+ 					GLenum pname,
+ 					int    *params);
++    #endif
++
++    typedef void (*GLActiveTextureProc) (GLenum texture);
++    typedef void (*GLClientActiveTextureProc) (GLenum texture);
++    typedef void (*GLMultiTexCoord2fProc) (GLenum, GLfloat, GLfloat);
+ 
+     typedef void (*GLGenFramebuffersProc) (GLsizei n,
+ 					   GLuint  *framebuffers);
+     typedef void (*GLDeleteFramebuffersProc) (GLsizei n,
+-					      GLuint  *framebuffers);
++					      const GLuint  *framebuffers);
+     typedef void (*GLBindFramebufferProc) (GLenum target,
+ 					   GLuint framebuffer);
+     typedef GLenum (*GLCheckFramebufferStatusProc) (GLenum target);
+@@ -161,6 +208,96 @@ namespace GL {
+ 						GLint  level);
+     typedef void (*GLGenerateMipmapProc) (GLenum target);
+ 
++    typedef void (*GLBindBufferProc) (GLenum target,
++                                      GLuint buffer);
++    typedef void (*GLDeleteBuffersProc) (GLsizei n,
++                                         const GLuint *buffers);
++    typedef void (*GLGenBuffersProc) (GLsizei n,
++                                      GLuint *buffers);
++    typedef void (*GLBufferDataProc) (GLenum target,
++                                      GLsizeiptr size,
++                                      const GLvoid *data,
++                                      GLenum usage);
++    typedef void (*GLBufferSubDataProc) (GLenum target,
++                                         GLintptr offset,
++                                         GLsizeiptr size,
++                                         const GLvoid *data);
++
++    typedef void (*GLGetShaderivProc) (GLuint shader,
++                                       GLenum pname,
++                                       GLint *params);
++    typedef void (*GLGetShaderInfoLogProc) (GLuint shader,
++                                            GLsizei bufsize,
++                                            GLsizei *length,
++                                            GLchar *infoLog);
++    typedef void (*GLGetProgramivProc) (GLuint program,
++                                        GLenum pname,
++                                        GLint* params);
++    typedef void (*GLGetProgramInfoLogProc) (GLuint program,
++                                             GLsizei bufsize,
++                                             GLsizei *length,
++                                             GLchar *infoLog);
++    typedef GLuint (*GLCreateShaderProc) (GLenum type);
++    typedef void (*GLShaderSourceProc) (GLuint shader,
++                                        GLsizei count,
++                                        const GLchar **string,
++                                        const GLint* length);
++    typedef void (*GLCompileShaderProc) (GLuint shader);
++    typedef GLuint (*GLCreateProgramProc) ();
++    typedef void (*GLAttachShaderProc) (GLuint program,
++                                        GLuint shader);
++    typedef void (*GLLinkProgramProc) (GLuint program);
++    typedef void (*GLValidateProgramProc) (GLuint program);
++    typedef void (*GLDeleteShaderProc) (GLuint shader);
++    typedef void (*GLDeleteProgramProc) (GLuint program);
++    typedef void (*GLUseProgramProc) (GLuint program);
++    typedef int  (*GLGetUniformLocationProc) (GLuint program,
++                                              const GLchar* name);
++    typedef void (*GLUniform1fProc) (GLint location, GLfloat x);
++    typedef void (*GLUniform1iProc) (GLint location, GLint x);
++    typedef void (*GLUniform2fProc) (GLint location, GLfloat x, GLfloat y);
++    typedef void (*GLUniform3fProc) (GLint location,
++                                     GLfloat x,
++                                     GLfloat y,
++                                     GLfloat z);
++    typedef void (*GLUniform4fProc) (GLint location,
++                                     GLfloat x,
++                                     GLfloat y,
++                                     GLfloat z,
++                                     GLfloat w);
++    typedef void (*GLUniform2iProc) (GLint location, GLint x, GLint y);
++    typedef void (*GLUniform3iProc) (GLint location,
++                                     GLint x,
++                                     GLint y,
++                                     GLint z);
++    typedef void (*GLUniform4iProc) (GLint location,
++                                     GLint x,
++                                     GLint y,
++                                     GLint z,
++                                     GLint w);
++    typedef void (*GLUniformMatrix4fvProc) (GLint location,
++                                            GLsizei count,
++                                            GLboolean transpose,
++                                            const GLfloat *value);
++    typedef int (*GLGetAttribLocationProc) (GLuint program,
++                                            const GLchar *name);
++
++    typedef void (*GLEnableVertexAttribArrayProc) (GLuint index);
++    typedef void (*GLDisableVertexAttribArrayProc) (GLuint index);
++    typedef void (*GLVertexAttribPointerProc) (GLuint index,
++                                               GLint size,
++                                               GLenum type,
++                                               GLboolean normalized,
++                                               GLsizei stride,
++                                               const GLvoid *ptr);
++
++    #ifdef USE_GLES
++    extern EGLCreateImageKHRProc  createImage;
++    extern EGLDestroyImageKHRProc destroyImage;
++
++    extern GLEGLImageTargetTexture2DOESProc eglImageTargetTexture;
++
++    #else
+     extern GLXBindTexImageProc      bindTexImage;
+     extern GLXReleaseTexImageProc   releaseTexImage;
+     extern GLXQueryDrawableProc     queryDrawable;
+@@ -172,11 +309,6 @@ namespace GL {
+     extern GLXGetFBConfigAttribProc getFBConfigAttrib;
+     extern GLXCreatePixmapProc      createPixmap;
+     extern GLXDestroyPixmapProc     destroyPixmap;
+-
+-    extern GLActiveTextureProc       activeTexture;
+-    extern GLClientActiveTextureProc clientActiveTexture;
+-    extern GLMultiTexCoord2fProc     multiTexCoord2f;
+-
+     extern GLGenProgramsProc        genPrograms;
+     extern GLDeleteProgramsProc     deletePrograms;
+     extern GLBindProgramProc        bindProgram;
+@@ -184,6 +316,11 @@ namespace GL {
+     extern GLProgramParameter4fProc programEnvParameter4f;
+     extern GLProgramParameter4fProc programLocalParameter4f;
+     extern GLGetProgramivProc       getProgramiv;
++    #endif
++
++    extern GLActiveTextureProc       activeTexture;
++    extern GLClientActiveTextureProc clientActiveTexture;
++    extern GLMultiTexCoord2fProc     multiTexCoord2f;
+ 
+     extern GLGenFramebuffersProc        genFramebuffers;
+     extern GLDeleteFramebuffersProc     deleteFramebuffers;
+@@ -192,16 +329,56 @@ namespace GL {
+     extern GLFramebufferTexture2DProc   framebufferTexture2D;
+     extern GLGenerateMipmapProc         generateMipmap;
+ 
++    extern GLBindBufferProc    bindBuffer;
++    extern GLDeleteBuffersProc deleteBuffers;
++    extern GLGenBuffersProc    genBuffers;
++    extern GLBufferDataProc    bufferData;
++    extern GLBufferSubDataProc bufferSubData;
++
++
++    extern GLGetShaderivProc        getShaderiv;
++    extern GLGetShaderInfoLogProc   getShaderInfoLog;
++    extern GLGetProgramivProc       getProgramiv;
++    extern GLGetProgramInfoLogProc  getProgramInfoLog;
++    extern GLCreateShaderProc       createShader;
++    extern GLShaderSourceProc       shaderSource;
++    extern GLCompileShaderProc      compileShader;
++    extern GLCreateProgramProc      createProgram;
++    extern GLAttachShaderProc       attachShader;
++    extern GLLinkProgramProc        linkProgram;
++    extern GLValidateProgramProc    validateProgram;
++    extern GLDeleteShaderProc       deleteShader;
++    extern GLDeleteProgramProc      deleteProgram;
++    extern GLUseProgramProc         useProgram;
++    extern GLGetUniformLocationProc getUniformLocation;
++    extern GLUniform1fProc          uniform1f;
++    extern GLUniform1iProc          uniform1i;
++    extern GLUniform2fProc          uniform2f;
++    extern GLUniform2iProc          uniform2i;
++    extern GLUniform3fProc          uniform3f;
++    extern GLUniform3iProc          uniform3i;
++    extern GLUniform4fProc          uniform4f;
++    extern GLUniform4iProc          uniform4i;
++    extern GLUniformMatrix4fvProc   uniformMatrix4fv;
++    extern GLGetAttribLocationProc  getAttribLocation;
++
++    extern GLEnableVertexAttribArrayProc  enableVertexAttribArray;
++    extern GLDisableVertexAttribArrayProc disableVertexAttribArray;
++    extern GLVertexAttribPointerProc      vertexAttribPointer;
++
++
+     extern bool  textureFromPixmap;
+     extern bool  textureRectangle;
+     extern bool  textureNonPowerOfTwo;
++    extern bool  textureNonPowerOfTwoMipmap;
+     extern bool  textureEnvCombine;
+     extern bool  textureEnvCrossbar;
+     extern bool  textureBorderClamp;
+     extern bool  textureCompression;
+     extern GLint maxTextureSize;
+     extern bool  fbo;
+-    extern bool  fragmentProgram;
++    extern bool  vbo;
++    extern bool  shaders;
+     extern GLint maxTextureUnits;
+ 
+     extern bool canDoSaturated;
+@@ -220,6 +397,7 @@ struct GLScreenPaintAttrib {
+ 
+ #define MAX_DEPTH 32
+ 
++#ifndef USE_GLES
+ struct GLFBConfig {
+     GLXFBConfig fbConfig;
+     int         yInverted;
+@@ -227,6 +405,7 @@ struct GLFBConfig {
+     int         textureFormat;
+     int         textureTargets;
+ };
++#endif
+ 
+ #define NOTHING_TRANS_FILTER 0
+ #define SCREEN_TRANS_FILTER  1
+@@ -236,6 +415,7 @@ struct GLFBConfig {
+ extern GLScreenPaintAttrib defaultScreenPaintAttrib;
+ 
+ class GLScreen;
++class GLFramebufferObject;
+ 
+ class GLScreenInterface :
+     public WrapableInterface<GLScreen, GLScreenInterface>
+@@ -302,11 +482,24 @@ class GLScreenInterface :
+ 					     CompOutput *);
+ 	virtual void glDisableOutputClipping ();
+ 
++	virtual GLMatrix *projectionMatrix ();
++
++	/**
++	 * Hookable function used by plugins to shade the final composited
++	 * Output.
++	 *
++	 * @param tmpRegion Describes the final composited output region
++	 * @param scratchFbo Describes the final composited FBO that is
++	 * to be rendered.
++	 */
++	virtual void glPaintCompositedOutput (const CompRegion    &region,
++					      GLFramebufferObject *fbo,
++					      unsigned int         mask);
+ };
+ 
+ 
+ class GLScreen :
+-    public WrapableHandler<GLScreenInterface, 6>,
++    public WrapableHandler<GLScreenInterface, 7>,
+     public PluginClassHandler<GLScreen, CompScreen, COMPIZ_OPENGL_ABI>,
+     public CompOption::Class
+ {
+@@ -332,7 +525,9 @@ class GLScreen :
+ 	/**
+ 	 * Gets the libGL address of a particular openGL functor
+ 	 */
++	#ifndef USE_GLES
+ 	GL::FuncPtr getProcAddress (const char *name);
++	#endif
+ 
+ 	void updateBackground ();
+ 
+@@ -346,8 +541,6 @@ class GLScreen :
+ 	 */
+ 	void setFilter (int, GLTexture::Filter);
+ 
+-	GLFragment::Storage * fragmentStorage ();
+-
+ 	/**
+ 	 * Sets a new compiz-wid openGL texture environment mode
+ 	 */
+@@ -356,7 +549,6 @@ class GLScreen :
+ 	/**
+ 	 * Turns lighting on and off
+ 	 */
+-
+ 	void setLighting (bool lighting);
+ 
+ 	/**
+@@ -371,20 +563,35 @@ class GLScreen :
+ 	GLTexture::BindPixmapHandle registerBindPixmap (GLTexture::BindPixmapProc);
+ 	void unregisterBindPixmap (GLTexture::BindPixmapHandle);
+ 
++	#ifndef USE_GLES
+ 	GLFBConfig * glxPixmapFBConfig (unsigned int depth);
++	#endif
++
++	#ifdef USE_GLES
++	EGLContext getEGLContext ();
++	#endif
+ 
+ 	/**
+-	 * Returns a default icon texture
++	 * Returns a GLProgram from the cache or creates one and caches it
+ 	 */
+-	GLTexture *defaultIcon ();
++	GLProgram *getProgram (std::list<const GLShaderData*>);
+ 
+-	void resetRasterPos ();
++	/**
++	 * Returns a GLShaderData from the cache or creates one and caches it
++	 */
++	const GLShaderData *getShaderData (GLShaderParameters &params);
+ 
+ 	/**
+-	 * Returns a 4x4 const float array which
+-	 * represents the current projection matrix
++	 * Returns the FBO compiz is using for the screen
+ 	 */
+-	const float * projectionMatrix ();
++	GLFramebufferObject *fbo ();
++
++	/**
++	 * Returns a default icon texture
++	 */
++	GLTexture *defaultIcon ();
++
++	void resetRasterPos ();
+ 
+ 	bool glInitContext (XVisualInfo *);
+ 
+@@ -402,7 +609,12 @@ class GLScreen :
+ 		      const GLMatrix &, const CompRegion &, CompOutput *);
+ 	WRAPABLE_HND (4, GLScreenInterface, void, glDisableOutputClipping);
+ 
++	WRAPABLE_HND (5, GLScreenInterface, GLMatrix *, projectionMatrix);
++	WRAPABLE_HND (6, GLScreenInterface, void, glPaintCompositedOutput,
++		      const CompRegion &, GLFramebufferObject *, unsigned int);
++
+ 	friend class GLTexture;
++	friend class GLWindow;
+ 
+     private:
+ 	PrivateGLScreen *priv;
+@@ -453,10 +665,10 @@ class GLWindowInterface :
+ 	 * @param region Describes which region will be drawn
+ 	 * @param mask   Bitmask which describes how this window is drawn
+ 	 */
+-	virtual bool glDraw (const GLMatrix 	&matrix,
+-			     GLFragment::Attrib &attrib,
+-			     const CompRegion 	&region,
+-			     unsigned int	mask);
++	virtual bool glDraw (const GLMatrix 	       &matrix,
++			     const GLWindowPaintAttrib &attrib,
++			     const CompRegion 	       &region,
++			     unsigned int              mask);
+ 
+ 	/**
+ 	 * Hookable function to add points to a window
+@@ -479,51 +691,18 @@ class GLWindowInterface :
+ 				    const CompRegion 		&clipRegion,
+ 				    unsigned int		min = MAXSHORT,
+ 				    unsigned int		max = MAXSHORT);
+-	virtual void glDrawTexture (GLTexture *texture, GLFragment::Attrib &,
+-				    unsigned int);
+-	virtual void glDrawGeometry ();
++	virtual void glDrawTexture (GLTexture *texture, const GLMatrix &,
++	                            const GLWindowPaintAttrib &, unsigned int);
+ };
+ 
+ class GLWindow :
+-    public WrapableHandler<GLWindowInterface, 5>,
++    public WrapableHandler<GLWindowInterface, 4>,
+     public PluginClassHandler<GLWindow, CompWindow, COMPIZ_OPENGL_ABI>
+ {
+     public:
+ 
+-	/**
+-	 * Class which describes the texture geometry and transformation points
+-	 * of a window
+-	 */
+-	class Geometry {
+-	    public:
+-		Geometry ();
+-		~Geometry ();
+-
+-		void reset ();
+-
+-		/**
+-		 * Set the number of vertices in the texture geometry
+-		 */
+-		bool moreVertices (int newSize);
+-
+-		/**
+-		 * Set the number of indices in the texture geometry
+-		 */
+-		bool moreIndices (int newSize);
+-
+-	    public:
+-		GLfloat  *vertices;
+-		int      vertexSize;
+-		int      vertexStride;
+-		GLushort *indices;
+-		int      indexSize;
+-		int      vCount;
+-		int      texUnits;
+-		int      texCoordSize;
+-		int      indexCount;
+-	};
+-
+ 	static GLWindowPaintAttrib defaultPaintAttrib;
++
+     public:
+ 
+ 	GLWindow (CompWindow *w);
+@@ -566,9 +745,20 @@ class GLWindow :
+ 	void updatePaintAttribs ();
+ 
+ 	/**
+-	 * Returns the window texture geometry
++	 * Returns the window vertex buffer object
+ 	 */
+-	Geometry & geometry ();
++	GLVertexBuffer * vertexBuffer ();
++
++	/**
++	 * Add a vertex and/or fragment shader function to the pipeline.
++	 *
++	 * @param name Name of the plugin adding the functions
++	 * @param vertex_shader Function to add to the vertex shader
++	 * @param fragment_shader Function to add to the fragment shader
++	 */
++	void addShaders (std::string name,
++	                 std::string vertex_shader,
++	                 std::string fragment_shader);
+ 
+ 	GLTexture *getIcon (int width, int height);
+ 
+@@ -576,20 +766,24 @@ class GLWindow :
+ 		      const GLWindowPaintAttrib &, const GLMatrix &,
+ 		      const CompRegion &, unsigned int);
+ 	WRAPABLE_HND (1, GLWindowInterface, bool, glDraw, const GLMatrix &,
+-		      GLFragment::Attrib &, const CompRegion &, unsigned int);
++		      const GLWindowPaintAttrib &, const CompRegion &,
++	              unsigned int);
+ 	WRAPABLE_HND (2, GLWindowInterface, void, glAddGeometry,
+ 		      const GLTexture::MatrixList &, const CompRegion &,
+ 		      const CompRegion &,
+ 		      unsigned int = MAXSHORT, unsigned int = MAXSHORT);
+ 	WRAPABLE_HND (3, GLWindowInterface, void, glDrawTexture,
+-		      GLTexture *texture, GLFragment::Attrib &, unsigned int);
+-	WRAPABLE_HND (4, GLWindowInterface, void, glDrawGeometry);
++		      GLTexture *texture, const GLMatrix &,
++	              const GLWindowPaintAttrib &, unsigned int);
+ 
+ 	friend class GLScreen;
+ 	friend class PrivateGLScreen;
++	friend class SpewScreen;
++	friend class SpewWindow;
+ 
+     private:
+ 	PrivateGLWindow *priv;
+ };
+ 
+ #endif
++
+--- compiz-0.9.7.6.orig/plugins/opengl/include/opengl/vector.h
++++ compiz-0.9.7.6/plugins/opengl/include/opengl/vector.h
+@@ -40,7 +40,7 @@ class GLVector {
+ 	} VectorCoordsEnum;
+ 
+ 	GLVector ();
+-	GLVector (float x, float y, float z, float w);
++	GLVector (float x, float y, float z, float w = 0.0f);
+ 
+ 	/**
+ 	 * Returns a reference to the x, y, z or w value by using
+--- compiz-0.9.7.6.orig/plugins/compiztoolbox/src/compiztoolbox.cpp
++++ compiz-0.9.7.6/plugins/compiztoolbox/src/compiztoolbox.cpp
+@@ -465,9 +465,7 @@ BaseSwitchWindow::paintThumb (const GLWi
+ 	sAttrib.yTranslate = wy - g.y () +
+ 			     window->border ().top  * sAttrib.yScale;
+ 
+-	GLFragment::Attrib fragment (sAttrib);
+-
+-	if (window->alpha () || fragment.getOpacity () != OPAQUE)
++	if (window->alpha () || sAttrib.opacity != OPAQUE)
+ 	    mask |= PAINT_WINDOW_TRANSLUCENT_MASK;
+ 
+ 	wTransform.translate (g.x (), g.y (), 0.0f);
+@@ -476,9 +474,6 @@ BaseSwitchWindow::paintThumb (const GLWi
+ 			      sAttrib.yTranslate / sAttrib.yScale - g.y (),
+ 			      0.0f);
+ 
+-	glPushMatrix ();
+-	glLoadMatrixf (wTransform.getMatrix ());
+-
+ 	filter = gScreen->textureFilter ();
+ 
+ 	if (baseScreen->getMipmap ())
+@@ -488,13 +483,11 @@ BaseSwitchWindow::paintThumb (const GLWi
+ 	   very ugly but necessary until the vertex stage has been made
+ 	   fully pluggable. */
+ 	gWindow->glAddGeometrySetCurrentIndex (MAXSHORT);
+-	gWindow->glDraw (wTransform, fragment, infiniteRegion, mask);
++	gWindow->glDraw (wTransform, sAttrib, infiniteRegion, mask);
+ 	gWindow->glAddGeometrySetCurrentIndex (addWindowGeometryIndex);
+ 
+ 	gScreen->setTextureFilter (filter);
+ 
+-	glPopMatrix ();
+-
+ 	if (iconMode != HideIcon)
+ 	{
+ 	    icon = gWindow->getIcon (MAX_ICON_SIZE, MAX_ICON_SIZE);
+@@ -535,30 +528,23 @@ BaseSwitchWindow::paintThumb (const GLWi
+ 	sAttrib.xTranslate = wx - g.x ();
+ 	sAttrib.yTranslate = wy - g.y ();
+ 
+-	gWindow->geometry ().reset ();
++	gWindow->vertexBuffer ()->begin ();
+ 
+ 	gWindow->glAddGeometrySetCurrentIndex (MAXSHORT);
+ 	gWindow->glAddGeometry (matrix, iconReg, infiniteRegion);
+ 	gWindow->glAddGeometrySetCurrentIndex (addWindowGeometryIndex);
+ 
+-	if (gWindow->geometry ().vCount)
+-	{
+-	    GLFragment::Attrib fragment (sAttrib);
+-	    GLMatrix           wTransform (transform);
+-
+-	    wTransform.translate (g.x (), g.y (), 0.0f);
+-	    wTransform.scale (sAttrib.xScale, sAttrib.yScale, 1.0f);
+-	    wTransform.translate (sAttrib.xTranslate / sAttrib.xScale - g.x (),
+-				  sAttrib.yTranslate / sAttrib.yScale - g.y (),
+-				  0.0f);
++	gWindow->vertexBuffer ()->end ();
+ 
+-	    glPushMatrix ();
+-	    glLoadMatrixf (wTransform.getMatrix ());
++	GLMatrix           wTransform (transform);
+ 
+-	    gWindow->glDrawTexture (icon, fragment, mask);
++	wTransform.translate (g.x (), g.y (), 0.0f);
++	wTransform.scale (sAttrib.xScale, sAttrib.yScale, 1.0f);
++	wTransform.translate (sAttrib.xTranslate / sAttrib.xScale - g.x (),
++	                      sAttrib.yTranslate / sAttrib.yScale - g.y (),
++	                      0.0f);
+ 
+-	    glPopMatrix ();
+-	}
++	gWindow->glDrawTexture (icon, wTransform, sAttrib, mask);
+     }
+ }
+ 
+--- compiz-0.9.7.6.orig/plugins/switcher/src/switcher.cpp
++++ compiz-0.9.7.6/plugins/switcher/src/switcher.cpp
+@@ -31,25 +31,33 @@ COMPIZ_PLUGIN_20090315 (switcher, Switch
+ 
+ static float _boxVertices[] =
+ {
+-    -(WIDTH >> 1), 0,
+-    -(WIDTH >> 1), BOX_WIDTH,
+-     (WIDTH >> 1), BOX_WIDTH,
+-     (WIDTH >> 1), 0,
+-
+-    -(WIDTH >> 1),	       BOX_WIDTH,
+-    -(WIDTH >> 1),	       HEIGHT - BOX_WIDTH,
+-    -(WIDTH >> 1) + BOX_WIDTH, HEIGHT - BOX_WIDTH,
+-    -(WIDTH >> 1) + BOX_WIDTH, 0,
+-
+-     (WIDTH >> 1) - BOX_WIDTH, BOX_WIDTH,
+-     (WIDTH >> 1) - BOX_WIDTH, HEIGHT - BOX_WIDTH,
+-     (WIDTH >> 1),	       HEIGHT - BOX_WIDTH,
+-     (WIDTH >> 1),	       0,
+-
+-    -(WIDTH >> 1), HEIGHT - BOX_WIDTH,
+-    -(WIDTH >> 1), HEIGHT,
+-     (WIDTH >> 1), HEIGHT,
+-     (WIDTH >> 1), HEIGHT - BOX_WIDTH
++    -(WIDTH >> 1), BOX_WIDTH, 0.0f,
++     (WIDTH >> 1), BOX_WIDTH, 0.0f,
++    -(WIDTH >> 1), 0.0f,      0.0f,
++    -(WIDTH >> 1), 0.0f,      0.0f,
++     (WIDTH >> 1), BOX_WIDTH, 0.0f,
++     (WIDTH >> 1), 0.0f,      0.0f,
++
++    -(WIDTH >> 1),             HEIGHT - BOX_WIDTH, 0.0f,
++    -(WIDTH >> 1) + BOX_WIDTH, HEIGHT - BOX_WIDTH, 0.0f,
++    -(WIDTH >> 1),             BOX_WIDTH,          0.0f,
++    -(WIDTH >> 1),             BOX_WIDTH,          0.0f,
++    -(WIDTH >> 1) + BOX_WIDTH, HEIGHT - BOX_WIDTH, 0.0f,
++    -(WIDTH >> 1) + BOX_WIDTH, BOX_WIDTH,          0.0f,
++
++     (WIDTH >> 1) - BOX_WIDTH, HEIGHT - BOX_WIDTH, 0.0f,
++     (WIDTH >> 1),             HEIGHT - BOX_WIDTH, 0.0f,
++     (WIDTH >> 1) - BOX_WIDTH, BOX_WIDTH,          0.0f,
++     (WIDTH >> 1) - BOX_WIDTH, BOX_WIDTH,          0.0f,
++     (WIDTH >> 1),             HEIGHT - BOX_WIDTH, 0.0f,
++     (WIDTH >> 1),             BOX_WIDTH,          0.0f,
++
++    -(WIDTH >> 1), HEIGHT,             0.0f,
++     (WIDTH >> 1), HEIGHT,             0.0f,
++    -(WIDTH >> 1), HEIGHT - BOX_WIDTH, 0.0f,
++    -(WIDTH >> 1), HEIGHT - BOX_WIDTH, 0.0f,
++     (WIDTH >> 1), HEIGHT,             0.0f,
++     (WIDTH >> 1), HEIGHT - BOX_WIDTH, 0.0f,
+ };
+ 
+ 
+@@ -799,9 +807,6 @@ SwitchScreen::glPaintOutput (const GLScr
+ 
+ 	    sTransform.toScreenSpace (output, -DEFAULT_Z_CAMERA);
+ 
+-	    glPushMatrix ();
+-	    glLoadMatrixf (sTransform.getMatrix ());
+-
+ 	    if (!switcher->destroyed () &&
+ 		switcher->isViewable () &&
+ 		sw->cWindow->damaged ())
+@@ -809,8 +814,6 @@ SwitchScreen::glPaintOutput (const GLScr
+ 		sw->gWindow->glPaint (sw->gWindow->paintAttrib (),
+ 				      sTransform, infiniteRegion, 0);
+ 	    }
+-
+-	    glPopMatrix ();
+ 	}
+     }
+     else
+@@ -950,8 +953,10 @@ SwitchWindow::glPaint (const GLWindowPai
+ 		       const CompRegion          &region,
+ 		       unsigned int              mask)
+ {
+-    int	       zoomType = NORMAL_WINDOW_MASK;
+-    bool       status;
++    GLVertexBuffer *streamingBuffer = GLVertexBuffer::streamingBuffer ();
++    GLMatrix        wTransform (transform);
++    int             zoomType = NORMAL_WINDOW_MASK;
++    bool            status;
+ 
+     if (window->id () == sScreen->popupWindow)
+     {
+@@ -975,17 +980,14 @@ SwitchWindow::glPaint (const GLWindowPai
+ 	x = x1 + sScreen->pos;
+ 	y = g.y () + SPACE;
+ 
+-	glPushAttrib (GL_SCISSOR_BIT);
+-
+ 	glEnable (GL_SCISSOR_TEST);
+ 	glScissor (x1, 0, x2 - x1, screen->height ());
+ 
+ 	foreach (CompWindow *w, sScreen->windows)
+ 	{
+ 	    if (x + WIDTH > x1)
+-		SwitchWindow::get (w)->paintThumb (
+-		    gWindow->lastPaintAttrib (), transform,
+-		    mask, x, y);
++		SwitchWindow::get (w)->paintThumb (gWindow->lastPaintAttrib (),
++		                                   transform, mask, x, y);
+ 	    x += WIDTH;
+ 	}
+ 
+@@ -994,31 +996,30 @@ SwitchWindow::glPaint (const GLWindowPai
+ 	    if (x > x2)
+ 		break;
+ 
+-            SwitchWindow::get (w)->paintThumb (
+-		gWindow->lastPaintAttrib (), transform,
+-		mask, x, y);
++            SwitchWindow::get (w)->paintThumb (gWindow->lastPaintAttrib (),
++	                                       transform, mask, x, y);
+ 	    x += WIDTH;
+ 	}
+ 
+-	glPopAttrib ();
++	glDisable (GL_SCISSOR_TEST);
+ 
+ 	cx = g.x () + (g.width () >> 1);
++	wTransform.translate (cx, y, 0.0f);
+ 
+-	glDisableClientState (GL_TEXTURE_COORD_ARRAY);
+-	glEnable (GL_BLEND);
+ 	for (i = 0; i < 4; i++)
++	{
+ 	    color[i] = (unsigned int)sScreen->fgColor[i] *
+-		       gWindow->lastPaintAttrib ().opacity /
+-		       0xffff;
+-	glColor4usv (color);
+-	glPushMatrix ();
+-	glTranslatef (cx, y, 0.0f);
+-	glVertexPointer (2, GL_FLOAT, 0, _boxVertices);
+-	glDrawArrays (GL_QUADS, 0, 16);
+-	glPopMatrix ();
+-	glColor4usv (defaultColor);
+-	glDisable (GL_BLEND);
+-	glEnableClientState (GL_TEXTURE_COORD_ARRAY);
++	               gWindow->lastPaintAttrib ().opacity /
++	               0xffff;
++	}
++
++	streamingBuffer->begin (GL_TRIANGLES);
++
++	streamingBuffer->addColors (1, color);
++	streamingBuffer->addVertices (24, _boxVertices);
++
++	streamingBuffer->end ();
++	streamingBuffer->render (wTransform, attrib);
+     }
+     else if (window == sScreen->selectedWindow)
+     {
+--- compiz-0.9.7.6.orig/plugins/blur/CMakeLists.txt
++++ compiz-0.9.7.6/plugins/blur/CMakeLists.txt
+@@ -2,15 +2,15 @@ find_package (Compiz REQUIRED)
+ 
+ include (CompizPlugin)
+ 
+-find_package (OpenGL)
++#find_package (OpenGL)
+ 
+-if (OPENGL_GLU_FOUND)
+-    compiz_plugin(blur PLUGINDEPS composite opengl LIBRARIES decoration ${OPENGL_glu_LIBRARY} INCDIRS ${OPENGL_INCLUDE_DIR})
++#if (OPENGL_GLU_FOUND)
++#    compiz_plugin(blur PLUGINDEPS composite opengl LIBRARIES decoration ${OPENGL_glu_LIBRARY} INCDIRS ${OPENGL_INCLUDE_DIR})
+ 
+-    if (COMPIZ_BUILD_WITH_RPATH AND NOT COMPIZ_DISABLE_PLUGIN_BLUR)
+-	set_target_properties (
+-	    blur PROPERTIES
+-	    INSTALL_RPATH "${COMPIZ_LIBDIR}"
+-	)
+-    endif (COMPIZ_BUILD_WITH_RPATH AND NOT COMPIZ_DISABLE_PLUGIN_BLUR)
+-endif ()
++#    if (COMPIZ_BUILD_WITH_RPATH AND NOT COMPIZ_DISABLE_PLUGIN_BLUR)
++#	set_target_properties (
++#	    blur PROPERTIES
++#	    INSTALL_RPATH "${COMPIZ_LIBDIR}"
++#	)
++#    endif (COMPIZ_BUILD_WITH_RPATH AND NOT COMPIZ_DISABLE_PLUGIN_BLUR)
++#endif ()
+--- compiz-0.9.7.6.orig/plugins/obs/src/obs.h
++++ compiz-0.9.7.6/plugins/obs/src/obs.h
+@@ -66,7 +66,7 @@ class ObsWindow :
+ 
+ 	bool glPaint (const GLWindowPaintAttrib &, const GLMatrix &,
+ 		      const CompRegion &, unsigned int);
+-	bool glDraw (const GLMatrix &, GLFragment::Attrib &,
++	bool glDraw (const GLMatrix &, const GLWindowPaintAttrib &,
+ 		     const CompRegion &, unsigned int);
+ 
+ 	void changePaintModifier (unsigned int, int);
+--- compiz-0.9.7.6.orig/plugins/obs/src/obs.cpp
++++ compiz-0.9.7.6/plugins/obs/src/obs.cpp
+@@ -151,29 +151,30 @@ ObsWindow::glPaint (const GLWindowPaintA
+ 	 we wrap into glDrawWindow here */
+ 
+ bool
+-ObsWindow::glDraw (const GLMatrix&     transform,
+-		   GLFragment::Attrib& attrib,
+-		   const CompRegion&   region,
+-		   unsigned int        mask)
++ObsWindow::glDraw (const GLMatrix            &transform,
++		   const GLWindowPaintAttrib &attrib,
++		   const CompRegion          &region,
++		   unsigned int              mask)
+ {
++    GLWindowPaintAttrib wAttrib (attrib);
+     int factor;
+ 
+     factor = customFactor[MODIFIER_OPACITY];
+     if (factor != 100)
+     {
+-	attrib.setOpacity (factor * attrib.getOpacity () / 100);
++	wAttrib.opacity = factor * wAttrib.opacity / 100;
+ 	mask |= PAINT_WINDOW_TRANSLUCENT_MASK;
+     }
+ 
+     factor = customFactor[MODIFIER_BRIGHTNESS];
+     if (factor != 100)
+-	attrib.setBrightness (factor * attrib.getBrightness () / 100);
++	wAttrib.brightness = factor * wAttrib.brightness / 100;
+ 
+     factor = customFactor[MODIFIER_SATURATION];
+     if (factor != 100)
+-	attrib.setSaturation (factor * attrib.getSaturation () / 100);
++	wAttrib.saturation = factor * wAttrib.saturation / 100;
+ 
+-    return gWindow->glDraw (transform, attrib, region, mask);
++    return gWindow->glDraw (transform, wAttrib, region, mask);
+ }
+ 
+ void
+--- compiz-0.9.7.6.orig/plugins/imgsvg/src/imgsvg.h
++++ compiz-0.9.7.6/plugins/imgsvg/src/imgsvg.h
+@@ -76,7 +76,8 @@ class SvgWindow :
+ 	SvgWindow (CompWindow *window);
+ 	~SvgWindow ();
+ 
+-	bool glDraw (const GLMatrix &transform, GLFragment::Attrib &fragment,
++	bool glDraw (const GLMatrix &transform,
++		     const GLWindowPaintAttrib &attrib,
+ 		     const CompRegion &region, unsigned int mask);
+ 	void moveNotify (int dx, int dy, bool immediate);
+ 	void resizeNotify (int dx, int dy, int dwidth, int dheight);
+--- compiz-0.9.7.6.orig/plugins/imgsvg/src/imgsvg.cpp
++++ compiz-0.9.7.6/plugins/imgsvg/src/imgsvg.cpp
+@@ -220,12 +220,12 @@ SvgWindow::~SvgWindow ()
+ }
+ 
+ bool
+-SvgWindow::glDraw (const GLMatrix     &transform,
+-		   GLFragment::Attrib &fragment,
+-		   const CompRegion   &region,
+-		   unsigned int       mask)
++SvgWindow::glDraw (const GLMatrix            &transform,
++		   const GLWindowPaintAttrib &attrib,
++		   const CompRegion          &region,
++		   unsigned int              mask)
+ {
+-    bool status = gWindow->glDraw (transform, fragment, region, mask);
++    bool status = gWindow->glDraw (transform, attrib, region, mask);
+ 
+     if (!status)
+ 	return status;
+@@ -251,13 +251,15 @@ SvgWindow::glDraw (const GLMatrix     &t
+ 	{
+ 	    matrix[0] = context->texture[0].matrices[i];
+ 
+-	    gWindow->geometry ().reset ();
++	    gWindow->vertexBuffer ()->begin ();
+ 	    gWindow->glAddGeometry (matrix, context->box, reg);
++	    gWindow->vertexBuffer ()->end ();
+ 
+ 	    if (mask & PAINT_WINDOW_TRANSLUCENT_MASK)
+ 		mask |= PAINT_WINDOW_BLEND_MASK;
+ 
+-	    gWindow->glDrawTexture (context->texture[0].textures[i], fragment, mask);
++	    gWindow->glDrawTexture (context->texture[0].textures[i], transform,
++	                            attrib, mask);
+ 
+ 	    if (rect.width () > 0 && rect.height () > 0)
+ 	    {
+@@ -321,11 +323,12 @@ SvgWindow::glDraw (const GLMatrix     &t
+ 		    saveFilter = gScreen->filter (SCREEN_TRANS_FILTER);
+ 		    gScreen->setFilter (SCREEN_TRANS_FILTER, GLTexture::Good);
+ 
+-		    gWindow->geometry ().reset ();
++		    gWindow->vertexBuffer ()->begin ();
+ 		    gWindow->glAddGeometry (matrix, r, reg);
++		    gWindow->vertexBuffer ()->end ();
+ 
+ 		    gWindow->glDrawTexture (context->texture[1].textures[j],
+-					    fragment, mask);
++					    transform, attrib, mask);
+ 
+ 		    gScreen->setFilter (SCREEN_TRANS_FILTER, saveFilter);
+ 		}
+--- compiz-0.9.7.6.orig/plugins/water/water.xml.in
++++ compiz-0.9.7.6/plugins/water/water.xml.in
+@@ -49,6 +49,30 @@
+ 		<min>1</min>
+ 		<max>3600000</max>
+ 	    </option>
++	    <option name="light_vec_x" type="float">
++		<_short>lightVec X</_short>
++		<_long>Light vector X coordinate</_long>
++		<default>1.0</default>
++		<min>-1</min>
++		<max>1</max>
++		<precision>0.1</precision>
++	    </option>
++	    <option name="light_vec_y" type="float">
++		<_short>lightVec Y</_short>
++		<_long>Light vector Y coordinate</_long>
++		<default>1.0</default>
++		<min>-1</min>
++		<max>1</max>
++		<precision>0.1</precision>
++	    </option>
++	    <option name="light_vec_z" type="float">
++		<_short>lightVec Z</_short>
++		<_long>Light vector Z coordinate</_long>
++		<default>1.0</default>
++		<min>0.1</min>
++		<max>1</max>
++		<precision>0.1</precision>
++	    </option>
+ 	    <option name="title_wave" type="bell">
+ 		<_short>Title wave</_short>
+ 		<_long>Wave effect from window title</_long>
+--- compiz-0.9.7.6.orig/plugins/water/CMakeLists.txt
++++ compiz-0.9.7.6/plugins/water/CMakeLists.txt
+@@ -2,4 +2,4 @@ find_package (Compiz REQUIRED)
+ 
+ include (CompizPlugin)
+ 
+-compiz_plugin(water PLUGINDEPS composite opengl)
+\ No newline at end of file
++compiz_plugin(water PLUGINDEPS composite opengl)
+--- compiz-0.9.7.6.orig/plugins/water/src/water.cpp
++++ compiz-0.9.7.6/plugins/water/src/water.cpp
+@@ -21,6 +21,7 @@
+  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+  *
+  * Author: David Reveman <davidr@xxxxxxxxxx>
++ *         Frederic Plourde <frederic.plourde@xxxxxxxxxxxxxxx>
+  */
+ 
+ #include "water.h"
+@@ -33,270 +34,33 @@ COMPIZ_PLUGIN_20090315 (water, WaterPlug
+ static int waterLastPointerX = 0;
+ static int waterLastPointerY = 0;
+ 
+-static const char *waterFpString =
+-    "!!ARBfp1.0"
+-
+-    "PARAM param = program.local[0];"
+-    "ATTRIB t11  = fragment.texcoord[0];"
+-
+-    "TEMP t01, t21, t10, t12;"
+-    "TEMP c11, c01, c21, c10, c12;"
+-    "TEMP prev, v, temp, accel;"
+-
+-    "TEX prev, t11, texture[0], %s;"
+-    "TEX c11,  t11, texture[1], %s;"
+-
+-    /* sample offsets */
+-    "ADD t01, t11, { - %f, 0.0, 0.0, 0.0 };"
+-    "ADD t21, t11, {   %f, 0.0, 0.0, 0.0 };"
+-    "ADD t10, t11, { 0.0, - %f, 0.0, 0.0 };"
+-    "ADD t12, t11, { 0.0,   %f, 0.0, 0.0 };"
+-
+-    /* fetch nesseccary samples */
+-    "TEX c01, t01, texture[1], %s;"
+-    "TEX c21, t21, texture[1], %s;"
+-    "TEX c10, t10, texture[1], %s;"
+-    "TEX c12, t12, texture[1], %s;"
+-
+-    /* x/y normals from height */
+-    "MOV v, { 0.0, 0.0, 0.75, 0.0 };"
+-    "SUB v.x, c12.w, c10.w;"
+-    "SUB v.y, c01.w, c21.w;"
+-
+-    /* bumpiness */
+-    "MUL v, v, 1.5;"
+-
+-    /* normalize */
+-    "MAD temp, v.x, v.x, 1.0;"
+-    "MAD temp, v.y, v.y, temp;"
+-    "RSQ temp, temp.x;"
+-    "MUL v, v, temp;"
+-
+-    /* add scale and bias to normal */
+-    "MAD v, v, 0.5, 0.5;"
+-
+-    /* done with computing the normal, continue with computing the next
+-       height value */
+-    "ADD accel, c10, c12;"
+-    "ADD accel, c01, accel;"
+-    "ADD accel, c21, accel;"
+-    "MAD accel, -4.0, c11, accel;"
+-
+-    /* store new height in alpha component */
+-    "MAD v.w, 2.0, c11, -prev.w;"
+-    "MAD v.w, accel, param.x, v.w;"
+-
+-    /* fade out height */
+-    "MUL v.w, v.w, param.y;"
+-
+-    "MOV result.color, v;"
+-
+-    "END";
+-
+-static bool
+-loadFragmentProgram (GLuint	*program,
+-		     const char *string)
+-{
+-    GLint errorPos;
+-
+-    /* clear errors */
+-    glGetError ();
+-
+-    if (!*program)
+-	GL::genPrograms (1, program);
+-
+-    GL::bindProgram (GL_FRAGMENT_PROGRAM_ARB, *program);
+-    GL::programString (GL_FRAGMENT_PROGRAM_ARB,
+-		       GL_PROGRAM_FORMAT_ASCII_ARB,
+-		       strlen (string), string);
+-
+-    glGetIntegerv (GL_PROGRAM_ERROR_POSITION_ARB, &errorPos);
+-    if (glGetError () != GL_NO_ERROR || errorPos != -1)
+-    {
+-	compLogMessage ("water", CompLogLevelError,
+-			"failed to load bump map program");
+-
+-	GL::deletePrograms (1, program);
+-	*program = 0;
+-
+-	return false;
+-    }
+-
+-    return true;
+-}
+-
+-static int
+-loadWaterProgram ()
+-{
+-    char buffer[1024];
+-
+-    WATER_SCREEN (screen);
+-
+-    if (ws->target == GL_TEXTURE_2D)
+-	sprintf (buffer, waterFpString,
+-		 "2D", "2D",
+-		 1.0f / ws->width,  1.0f / ws->width,
+-		 1.0f / ws->height, 1.0f / ws->height,
+-		 "2D", "2D", "2D", "2D");
+-    else
+-	sprintf (buffer, waterFpString,
+-		 "RECT", "RECT",
+-		 1.0f, 1.0f, 1.0f, 1.0f,
+-		 "RECT", "RECT", "RECT", "RECT");
+-
+-    return loadFragmentProgram (&ws->program, buffer);
+-}
+-
+-GLFragment::FunctionId
+-WaterScreen::getBumpMapFragmentFunction (GLTexture *texture,
+-					 int       unit,
+-					 int       param)
+-{
+-    GLFragment::FunctionData data;
+-    int                      target;
+-    WaterFunction            function;
+-
+-    if (texture->target () == GL_TEXTURE_2D)
+-	target = COMP_FETCH_TARGET_2D;
+-    else
+-	target = COMP_FETCH_TARGET_RECT;
+-
+-    foreach (WaterFunction &f, bumpMapFunctions)
+-    {
+-	if (f.param  == param &&
+-	    f.unit   == unit  &&
+-	    f.target == target)
+-	    return f.id;
+-    }
+-
+-    static const char *temp[] = { "normal", "temp", "total", "bump", "offset" };
+-
+-    for (unsigned int i = 0; i < sizeof (temp) / sizeof (temp[0]); i++)
+-	data.addTempHeaderOp (temp[i]);
+-
+-    data.addDataOp (
+-	/* get normal from normal map */
+-	"TEX normal, fragment.texcoord[%d], texture[%d], %s;"
+-
+-	/* save height */
+-	"MOV offset, normal;"
+-
+-	/* remove scale and bias from normal */
+-	"MAD normal, normal, 2.0, -1.0;"
+-
+-	/* normalize the normal map */
+-	"DP3 temp, normal, normal;"
+-	"RSQ temp, temp.x;"
+-	"MUL normal, normal, temp;"
+-
+-	/* scale down normal by height and constant and use as
+-	    offset in texture */
+-	"MUL offset, normal, offset.w;"
+-	"MUL offset, offset, program.env[%d];",
+-
+-	unit, unit,
+-	(this->target == GL_TEXTURE_2D) ? "2D" : "RECT",
+-	param);
+-
+-    data.addFetchOp ("output", "offset.yxzz", target);
+-
+-    data.addDataOp (
+-	/* normal dot lightdir, this should eventually be
+-	    changed to a real light vector */
+-	"DP3 bump, normal, { 0.707, 0.707, 0.0, 0.0 };"
+-	"MUL bump, bump, state.light[0].diffuse;");
+-
+-
+-    data.addColorOp ("output", "output");
+-
+-    data.addDataOp (
+-	/* diffuse per-vertex lighting, opacity and brightness
+-	    and add lightsource bump color */
+-	"ADD output, output, bump;");
+-
+-    if (!data.status ())
+-	return 0;
+-
+-
+-    function.id = data.createFragmentFunction ("water");
+-
+-    function.target = target;
+-    function.param  = param;
+-    function.unit   = unit;
+-
+-    bumpMapFunctions.push_back (function);
+-
+-    return function.id;
+-}
+-
+-void
+-WaterScreen::allocTexture (int index)
+-{
+-    glGenTextures (1, &texture[index]);
+-    glBindTexture (target, texture[index]);
+-
+-    glTexParameteri (target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+-    glTexParameteri (target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+-    glTexParameteri (target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+-    glTexParameteri (target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+-
+-    glTexImage2D (target, 0, GL_RGBA, width, height, 0, GL_BGRA,
+-#if IMAGE_BYTE_ORDER == MSBFirst
+-		  GL_UNSIGNED_INT_8_8_8_8_REV,
+-#else
+-		  GL_UNSIGNED_BYTE,
+-#endif
+-		  t0);
+-
+-    glBindTexture (target, 0);
+-}
++GLfloat WaterScreen::vertexData [18] = {
++    -1.0f, -1.0f, 0.0f,
++     1.0f, -1.0f, 0.0f,
++    -1.0f,  1.0f, 0.0f,
++    -1.0f,  1.0f, 0.0f,
++     1.0f, -1.0f, 0.0f,
++     1.0f,  1.0f, 0.0f,
++};
++
++GLfloat WaterScreen::textureData [12] = {
++    0.0f, 0.0f,
++    1.0f, 0.0f,
++    0.0f, 1.0f,
++    0.0f, 1.0f,
++    1.0f, 0.0f,
++    1.0f, 1.0f,
++};
+ 
+ bool
+-WaterScreen::fboPrologue (int tIndex)
++WaterScreen::fboPrologue (int fIndex)
+ {
+-    if (!fbo)
++    if (!useFbo)
+ 	return false;
+ 
+-    if (!texture[tIndex])
+-	allocTexture (tIndex);
+-
+-    GL::bindFramebuffer (GL_FRAMEBUFFER_EXT, fbo);
+-
+-    GL::framebufferTexture2D (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
+-			      target, texture[tIndex], 0);
+-
+-    glDrawBuffer (GL_COLOR_ATTACHMENT0_EXT);
+-    glReadBuffer (GL_COLOR_ATTACHMENT0_EXT);
+-
+-    /* check status the first time */
+-    if (!fboStatus)
+-    {
+-	fboStatus = GL::checkFramebufferStatus (GL_FRAMEBUFFER_EXT);
+-	if (fboStatus != GL_FRAMEBUFFER_COMPLETE_EXT)
+-	{
+-	    compLogMessage ("water", CompLogLevelError,
+-			    "framebuffer incomplete");
+-
+-	    GL::bindFramebuffer (GL_FRAMEBUFFER_EXT, 0);
+-	    GL::deleteFramebuffers (1, &fbo);
+-
+-	    glDrawBuffer (GL_BACK);
+-	    glReadBuffer (GL_BACK);
+-
+-	    fbo = 0;
+-
+-	    return false;
+-	}
+-    }
+-
+-    glViewport (0, 0, width, height);
+-    glMatrixMode (GL_PROJECTION);
+-    glPushMatrix ();
+-    glLoadIdentity ();
+-    glOrtho (0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
+-    glMatrixMode (GL_MODELVIEW);
+-    glPushMatrix ();
+-    glLoadIdentity ();
++    oldFbo = waterFbo[fIndex]->bind ();
++    glGetIntegerv(GL_VIEWPORT,  &oldViewport[0]);
++    glViewport (0, 0, texWidth, texHeight);
+ 
+     return true;
+ }
+@@ -304,424 +68,115 @@ WaterScreen::fboPrologue (int tIndex)
+ void
+ WaterScreen::fboEpilogue ()
+ {
+-    GL::bindFramebuffer (GL_FRAMEBUFFER_EXT, 0);
+-
+-    glMatrixMode (GL_PROJECTION);
+-    glLoadIdentity ();
+-    glMatrixMode (GL_MODELVIEW);
+-    glLoadIdentity ();
+-    glDepthRange (0, 1);
+-    glViewport (-1, -1, 2, 2);
+-
+-    gScreen->resetRasterPos ();
+-
+-    gScreen->setDefaultViewport ();
+-
+-    glMatrixMode (GL_PROJECTION);
+-    glPopMatrix ();
+-    glMatrixMode (GL_MODELVIEW);
+-    glPopMatrix ();
+-
+-    glDrawBuffer (GL_BACK);
+-    glReadBuffer (GL_BACK);
+-}
+-
+-bool
+-WaterScreen::fboUpdate (float dt, float fade)
+-{
+-    if (!fboPrologue (TINDEX (this, 1)))
+-	return false;
+-
+-    if (!texture[TINDEX (this, 2)])
+-	allocTexture (TINDEX (this, 2));
+-
+-    if (!texture[TINDEX (this, 0)])
+-	allocTexture (TINDEX (this, 0));
+-
+-    glEnable (target);
+-
+-    GL::activeTexture (GL_TEXTURE0_ARB);
+-    glBindTexture (target, texture[TINDEX (this, 2)]);
+-
+-    glTexParameteri (target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+-    glTexParameteri (target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+-    GL::activeTexture (GL_TEXTURE1_ARB);
+-    glBindTexture (target, texture[TINDEX (this, 0)]);
+-    glTexParameteri (target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+-    glTexParameteri (target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+-
+-    glEnable (GL_FRAGMENT_PROGRAM_ARB);
+-    GL::bindProgram (GL_FRAGMENT_PROGRAM_ARB, program);
+-
+-    GL::programLocalParameter4f (GL_FRAGMENT_PROGRAM_ARB, 0,
+-				 dt * K, fade, 1.0f, 1.0f);
+-
+-    glBegin (GL_QUADS);
+-
+-    glTexCoord2f (0.0f, 0.0f);
+-    glVertex2f   (0.0f, 0.0f);
+-    glTexCoord2f (tx, 0.0f);
+-    glVertex2f   (1.0f, 0.0f);
+-    glTexCoord2f (tx, ty);
+-    glVertex2f   (1.0f, 1.0f);
+-    glTexCoord2f (0.0f, ty);
+-    glVertex2f   (0.0f, 1.0f);
+-
+-    glEnd ();
+-
+-    glDisable (GL_FRAGMENT_PROGRAM_ARB);
+-
+-    glTexParameteri (target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+-    glTexParameteri (target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+-    glBindTexture (target, 0);
+-    GL::activeTexture (GL_TEXTURE0_ARB);
+-    glTexParameteri (target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+-    glTexParameteri (target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+-    glBindTexture (target, 0);
+-
+-    glDisable (target);
+-
+-    fboEpilogue ();
+-
+-    /* increment texture index */
+-    tIndex = TINDEX (this, 1);
+-
+-    return true;
+-}
+-
+-bool
+-WaterScreen::fboVertices (GLenum type,
+-			  XPoint *p,
+-			  int    n,
+-			  float  v)
+-{
+-    if (!fboPrologue (TINDEX (this, 0)))
+-	return false;
+-
+-    glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
+-    glColor4f (0.0f, 0.0f, 0.0f, v);
+-
+-    glPointSize (3.0f);
+-    glLineWidth (1.0f);
+-
+-    glScalef (1.0f / width, 1.0f / height, 1.0);
+-    glTranslatef (0.5f, 0.5f, 0.0f);
+-
+-    glBegin (type);
+-
+-    while (n--)
+-    {
+-	glVertex2i (p->x, p->y);
+-	p++;
+-    }
+-
+-    glEnd ();
+-
+-    glColor4usv (defaultColor);
+-    glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+-
+-    fboEpilogue ();
+-
+-    return true;
++    GLFramebufferObject::rebind (oldFbo);
++    glViewport (oldViewport[0], oldViewport[1], oldViewport[2], oldViewport[3]);
+ }
+ 
+ void
+-WaterScreen::softwareUpdate (float dt, float fade)
++WaterScreen::waterUpdate (float dt)
+ {
+-    float         *dTmp;
+-    int           i, j;
+-    float         v0, v1, inv;
+-    float         accel, value;
+-    unsigned char *t0, *t;
+-    int           dWidth, dHeight;
+-    float         *d01, *d10, *d11, *d12;
+-
+-    if (!texture[TINDEX (this, 0)])
+-	allocTexture (TINDEX (this, 0));
+-
+-    dt *= K * 2.0f;
+-    fade *= 0.99f;
+-
+-    dWidth  = width  + 2;
+-    dHeight = height + 2;
+-
+-#define D(d, j) (*((d) + (j)))
+-
+-    d01 = d0 + dWidth;
+-    d10 = d1;
+-    d11 = d10 + dWidth;
+-    d12 = d11 + dWidth;
+-
+-    for (i = 1; i < dHeight - 1; i++)
+-    {
+-	for (j = 1; j < dWidth - 1; j++)
+-	{
+-	    accel = dt * (D (d10, j)     +
+-			  D (d12, j)     +
+-			  D (d11, j - 1) +
+-			  D (d11, j + 1) - 4.0f * D (d11, j));
+-
+-	    value = (2.0f * D (d11, j) - D (d01, j) + accel) * fade;
+-
+-	    value = CLAMP (value, 0.0f, 1.0f);
+-
+-	    D (d01, j) = value;
+-	}
+-
+-	d01 += dWidth;
+-	d10 += dWidth;
+-	d11 += dWidth;
+-	d12 += dWidth;
+-    }
+-
+-    /* update border */
+-    memcpy (d0, d0 + dWidth, dWidth * sizeof (GLfloat));
+-    memcpy (d0 + dWidth * (dHeight - 1),
+-	    d0 + dWidth * (dHeight - 2),
+-	    dWidth * sizeof (GLfloat));
+-
+-    d01 = d0 + dWidth;
+-
+-    for (i = 1; i < dHeight - 1; i++)
+-    {
+-	D (d01, 0)	    = D (d01, 1);
+-	D (d01, dWidth - 1) = D (d01, dWidth - 2);
+-
+-	d01 += dWidth;
+-    }
+-
+-    d10 = d1;
+-    d11 = d10 + dWidth;
+-    d12 = d11 + dWidth;
+-
+-    t0 = this->t0;
++    GLfloat fade = 1.0f;
+ 
+-    /* update texture */
+-    for (i = 0; i < height; i++)
++    if (count < 1000)
+     {
+-	for (j = 0; j < width; j++)
+-	{
+-	    v0 = (D (d12, j)     - D (d10, j))     * 1.5f;
+-	    v1 = (D (d11, j - 1) - D (d11, j + 1)) * 1.5f;
+-
+-	    /* 0.5 for scale */
+-	    inv = 0.5f / sqrtf (v0 * v0 + v1 * v1 + 1.0f);
+-
+-	    /* add scale and bias to normal */
+-	    v0 = v0 * inv + 0.5f;
+-	    v1 = v1 * inv + 0.5f;
+-
+-	    /* store normal map in RGB components */
+-	    t = t0 + (j * 4);
+-	    t[0] = (unsigned char) ((inv + 0.5f) * 255.0f);
+-	    t[1] = (unsigned char) (v1 * 255.0f);
+-	    t[2] = (unsigned char) (v0 * 255.0f);
+-
+-	    /* store height in A component */
+-	    t[3] = (unsigned char) (D (d11, j) * 255.0f);
+-	}
+-
+-	d10 += dWidth;
+-	d11 += dWidth;
+-	d12 += dWidth;
+-
+-	t0 += width * 4;
++	if (count > 1)
++	    fade = 0.90f + (float) count / 10000.0f;
++	else
++	    fade = 0.0f;
+     }
+ 
+-#undef D
+-
+-    /* swap height maps */
+-    dTmp   = d0;
+-    d0 = d1;
+-    d1 = dTmp;
++    if (!fboPrologue (INDEX (this, 1)))
++	return;
+ 
+-    if (texture[TINDEX (this, 0)])
+-    {
+-	glBindTexture (target, texture[TINDEX (this, 0)]);
+-	glTexImage2D (target, 0, GL_RGBA, width, height, 0, GL_BGRA,
+-#if IMAGE_BYTE_ORDER == MSBFirst
+-		      GL_UNSIGNED_INT_8_8_8_8_REV,
+-#else
+-		      GL_UNSIGNED_BYTE,
+-#endif
+-		      this->t0);
+-    }
+-}
++    glEnable (GL_TEXTURE_2D);
+ 
++    vertexBuffer[UPDATE]->begin ();
++    vertexBuffer[UPDATE]->addVertices  (6, &vertexData[0]);
++    vertexBuffer[UPDATE]->addTexCoords (0, 6, &textureData[0]);
++    vertexBuffer[UPDATE]->end ();
++
++    // TODO: use GLTexture facilities here, instead of manually setting active
++    //       texture, especially when there will be texture unit support
++    glActiveTexture (GL_TEXTURE0);
++    waterFbo[INDEX (this, 2)]->tex ()->setFilter (GL_NEAREST);
++    glBindTexture (GL_TEXTURE_2D, waterFbo[INDEX (this, 2)]->tex ()->name ());
++
++    glActiveTexture (GL_TEXTURE1);
++    waterFbo[INDEX (this, 0)]->tex ()->setFilter (GL_NEAREST);
++    glBindTexture (GL_TEXTURE_2D, waterFbo[INDEX (this, 0)]->tex ()->name ());
++
++    vertexBuffer[UPDATE]->addUniform ("prevTex", 0);
++    vertexBuffer[UPDATE]->addUniform ("currTex", 1);
++    vertexBuffer[UPDATE]->addUniform ("timeLapse", dt * K);
++    vertexBuffer[UPDATE]->addUniform ("fade", fade);
++
++    GLboolean isBlendingEnabled;
++    glGetBooleanv (GL_BLEND, &isBlendingEnabled);
++    glDisable (GL_BLEND);
++    vertexBuffer[UPDATE]->render ();
++    if (isBlendingEnabled)
++	glEnable (GL_BLEND);
+ 
+-#define SET(x, y, v) *((d1) + (width + 2) * (y + 1) + (x + 1)) = (v)
++    glActiveTexture (GL_TEXTURE0);
++    glBindTexture (GL_TEXTURE_2D, 0);
+ 
+-void
+-WaterScreen::softwarePoints (XPoint *p,
+-			     int     n,
+-			     float   add)
+-{
+-    while (n--)
+-    {
+-	SET (p->x - 1, p->y - 1, add);
+-	SET (p->x, p->y - 1, add);
+-	SET (p->x + 1, p->y - 1, add);
++    glActiveTexture (GL_TEXTURE1);
++    glBindTexture (GL_TEXTURE_2D, 0);
+ 
+-	SET (p->x - 1, p->y, add);
+-	SET (p->x, p->y, add);
+-	SET (p->x + 1, p->y, add);
++    glDisable (GL_TEXTURE_2D);
+ 
+-	SET (p->x - 1, p->y + 1, add);
+-	SET (p->x, p->y + 1, add);
+-	SET (p->x + 1, p->y + 1, add);
++    fboEpilogue ();
+ 
+-	p++;
+-    }
++    /* increment texture index */
++    fboIndex = INDEX (this, 1);
+ }
+ 
+-/* bresenham */
+ void
+-WaterScreen::softwareLines (XPoint *p,
++WaterScreen::waterVertices (GLenum type,
++			    XPoint *p,
+ 			    int    n,
+ 			    float  v)
+ {
+-    int	 x1, y1, x2, y2;
+-    bool steep;
+-    int  tmp;
+-    int  deltaX, deltaY;
+-    int  error = 0;
+-    int  yStep;
+-    int  x, y;
+-
+-#define SWAP(v0, v1) \
+-    tmp = v0;	     \
+-    v0 = v1;	     \
+-    v1 = tmp
+-
+-    while (n > 1)
+-    {
+-	x1 = p->x;
+-	y1 = p->y;
+-
+-	p++;
+-	n--;
+-
+-	x2 = p->x;
+-	y2 = p->y;
+-
+-	p++;
+-	n--;
+-
+-	steep = abs (y2 - y1) > abs (x2 - x1);
+-	if (steep)
+-	{
+-	    SWAP (x1, y1);
+-	    SWAP (x2, y2);
+-	}
+-
+-	if (x1 > x2)
+-	{
+-	    SWAP (x1, x2);
+-	    SWAP (y1, y2);
+-	}
+-
+-#undef SWAP
+-
+-	deltaX = x2 - x1;
+-	deltaY = abs (y2 - y1);
+-
+-	y = y1;
+-	if (y1 < y2)
+-	    yStep = 1;
+-	else
+-	    yStep = -1;
+-
+-	for (x = x1; x <= x2; x++)
+-	{
+-	    if (steep)
+-	    {
+-		SET (y, x, v);
+-	    }
+-	    else
+-	    {
+-		SET (x, y, v);
+-	    }
+-
+-	    error += deltaY;
+-	    if (2 * error >= deltaX)
+-	    {
+-		y += yStep;
+-		error -= deltaX;
+-	    }
+-	}
+-    }
+-}
+-
+-#undef SET
+-
+-void
+-WaterScreen::softwareVertices (GLenum type,
+-			       XPoint *p,
+-			       int    n,
+-			       float  v)
+-{
+-    switch (type) {
+-	case GL_POINTS:
+-	    softwarePoints (p, n, v);
+-	    break;
+-	case GL_LINES:
+-	    softwareLines (p, n, v);
+-	    break;
+-    }
+-}
+-
+-void
+-WaterScreen::waterUpdate (float dt)
+-{
+-    GLfloat fade = 1.0f;
+-
+-    if (count < 1000)
+-    {
+-	if (count > 1)
+-	    fade = 0.90f + count / 10000.0f;
+-	else
+-	    fade = 0.0f;
+-    }
++    if (!fboPrologue (INDEX (this, 0)))
++	return;
+ 
+-    if (!fboUpdate (dt, fade))
+-	softwareUpdate (dt, fade);
+-}
++    glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
++    glLineWidth (1.0f);
+ 
+-void
+-WaterScreen::scaleVertices (XPoint *p, int n)
+-{
+-    while (n--)
++    if (GL::vbo && GL::shaders)
+     {
+-	p[n].x = (width  * p[n].x) / screen->width ();
+-	p[n].y = (height * p[n].y) / screen->height ();
++	vertexBuffer[SET]->begin (type);
++	float data[3];
++	for (int i = 0; i < n; i++)
++	{
++	    data[0] = (((float) p->x / (float) screen->width ())  * 2.0f) - 1.0f;
++	    data[1] = ((((float) screen->height () - (float) p->y)/
++			(float) screen->height ()) * 2.0f) - 1.0f;
++	    data[2] = 0.0f;
++	    p++;
++	    vertexBuffer[SET]->addVertices  (1, &data[0]);
++	}
++	vertexBuffer[SET]->end();
++
++	vertexBuffer[SET]->addUniform ("color", v);
++	GLboolean isBlendingEnabled;
++	glGetBooleanv (GL_BLEND, &isBlendingEnabled);
++	glDisable (GL_BLEND);
++	vertexBuffer[SET]->render ();
++	if (isBlendingEnabled)
++	    glEnable (GL_BLEND);
+     }
+-}
+-
+-void
+-WaterScreen::waterVertices (GLenum type,
+-			    XPoint *p,
+-			    int    n,
+-			    float  v)
+-{
+-    if (!GL::fragmentProgram)
+-	return;
+ 
+-    scaleVertices (p, n);
++    glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ 
+-    if (!fboVertices (type, p, n, v))
+-	softwareVertices (type, p, n, v);
++    fboEpilogue ();
+ 
+     if (count <= 0)
+     {
+-	WaterWindow *ww;
+-
+ 	cScreen->preparePaintSetEnabled (this, true);
++	gScreen->glPaintOutputSetEnabled (this, true);
++	gScreen->glPaintCompositedOutputSetEnabled (this, true);
+ 	cScreen->donePaintSetEnabled (this, true);
+-	foreach (CompWindow *w, screen->windows ())
+-	{
+-	    ww = WaterWindow::get (w);
+-	    ww->gWindow->glDrawTextureSetEnabled (ww, true);
+-	}
+     }
+ 
+     if (count < 3000)
+@@ -758,15 +213,21 @@ WaterScreen::wiperTimeout ()
+ }
+ 
+ void
+-WaterScreen::waterReset ()
++WaterScreen::waterSetup ()
+ {
+-    int size, i, j;
+-
+-    height = TEXTURE_SIZE;
+-    width  = (height * screen->width ()) / screen->height ();
+-
++    int size;
++    char buf[8192];
++    std::string buffer;
++
++    texHeight = TEXTURE_SIZE;
++    texWidth  = (texHeight * screen->width ()) / screen->height ();
++
++#ifdef USE_GLES
++    target = GL_TEXTURE_2D;
++    tx = ty = 1.0f;
++#else
+     if (GL::textureNonPowerOfTwo ||
+-	(POWER_OF_TWO (width) && POWER_OF_TWO (height)))
++	(POWER_OF_TWO (texWidth) && POWER_OF_TWO (texHeight)))
+     {
+ 	target = GL_TEXTURE_2D;
+ 	tx = ty = 1.0f;
+@@ -774,38 +235,15 @@ WaterScreen::waterReset ()
+     else
+     {
+ 	target = GL_TEXTURE_RECTANGLE_NV;
+-	tx = width;
+-	ty = height;
+-    }
+-
+-    if (!GL::fragmentProgram)
+-	return;
+-
+-    if (GL::fbo)
+-    {
+-	loadWaterProgram ();
+-	if (!fbo)
+-	    GL::genFramebuffers (1, &fbo);
+-    }
+-
+-    fboStatus = 0;
+-
+-    for (i = 0; i < TEXTURE_NUM; i++)
+-    {
+-	if (texture[i])
+-	{
+-	    glDeleteTextures (1, &texture[i]);
+-	    texture[i] = 0;
+-	}
++	tx = texWidth;
++	ty = texHeight;
+     }
++#endif
+ 
+-    if (data)
+-	free (data);
+-
+-    size = (width + 2) * (height + 2);
++    size = (texWidth + 2) * (texHeight + 2);
+ 
+     data = calloc (1, (sizeof (float) * size * 2) +
+-		   (sizeof (GLubyte) * width * height * 4));
++		   (sizeof (GLubyte) * texWidth * texHeight * 4));
+     if (!data)
+ 	return;
+ 
+@@ -813,89 +251,112 @@ WaterScreen::waterReset ()
+     d1 = (d0 + (size));
+     t0 = (unsigned char *) (d1 + (size));
+ 
+-    for (i = 0; i < height; i++)
++    if (GL::fbo)
+     {
+-	for (j = 0; j < width; j++)
++	program[SET]    = new GLProgram (set_water_vertices_vertex_shader,
++				         set_water_vertices_fragment_shader);
++
++	if (target == GL_TEXTURE_2D)
++	    sprintf (buf, update_water_vertices_fragment_shader.c_str (),
++		     "2D", "2D",
++		     1.0f / (float) texWidth,  1.0f / (float) texWidth,
++		     1.0f / (float) texHeight, 1.0f / (float) texHeight,
++		     "2D", "2D", "2D", "2D");
++	else
++	    sprintf (buf, update_water_vertices_fragment_shader.c_str (),
++		     "RECT", "RECT",
++		     1.0f, 1.0f, 1.0f, 1.0f,
++		     "RECT", "RECT", "RECT", "RECT");
++
++	buffer.assign (buf);
++	program[UPDATE] = new GLProgram (update_water_vertices_vertex_shader,
++				         buffer);
++
++	sprintf (buf, paint_water_vertices_fragment_shader.c_str (),
++		     screen->width (), screen->height ());
++
++	buffer.assign (buf);
++	program[PAINT]  = new GLProgram (paint_water_vertices_vertex_shader,
++				         buffer);
++
++	vertexBuffer[SET] = new GLVertexBuffer (GL_DYNAMIC_DRAW);
++	vertexBuffer[SET]->setProgram (program[SET]);
++
++	vertexBuffer[UPDATE] = new GLVertexBuffer (GL_STATIC_DRAW);
++	vertexBuffer[UPDATE]->setProgram (program[UPDATE]);
++
++	vertexBuffer[PAINT] = new GLVertexBuffer (GL_STATIC_DRAW);
++	vertexBuffer[PAINT]->setProgram (program[PAINT]);
++    }
++
++    if (GL::fbo)
++    {
++	CompSize size(texWidth, texHeight);
++	for (int i = 0; i < TEXTURE_NUM; i++)
+ 	{
+-	    (t0 + (width * 4 * i + j * 4))[0] = 0xff;
++	    waterFbo[i] = new GLFramebufferObject ();
++	    waterFbo[i]->allocate (size, (char *) t0,
++				   GL_BGRA, GL_UNSIGNED_BYTE);
++	    // check if FBOs are working. If not, fallback to software textures
++	    oldFbo = waterFbo[i]->bind ();
++	    waterFbo[i]->rebind (oldFbo);
++ 	    if (!waterFbo[i]->checkStatus ())
++	    {
++		useFbo = false;
++		delete waterFbo[i];
++		break;
++	    }
+ 	}
+     }
+ }
+ 
+ void
+-WaterWindow::glDrawTexture (GLTexture          *texture,
+-			    GLFragment::Attrib &attrib,
+-			    unsigned int       mask)
++WaterScreen::glPaintCompositedOutput (const CompRegion    &region,
++				      GLFramebufferObject *fbo,
++				      unsigned int         mask)
+ {
+-    if (wScreen->count)
++    if (count)
+     {
+-	GLFragment::Attrib     fa (attrib);
+-	bool                   lighting = wScreen->gScreen->lighting ();
+-	int                    param, unit;
+-	GLFragment::FunctionId function;
+-	GLfloat                plane[4];
+-
+-	param = fa.allocParameters (1);
+-	unit  = fa.allocTextureUnits (1);
+-
+-	function = wScreen->getBumpMapFragmentFunction (texture, unit, param);
+-	if (function)
++	if (GL::vbo && GL::shaders)
+ 	{
+-	    fa.addFunction (function);
+-
+-	    gScreen->setLighting (true);
+-
+-	    GL::activeTexture (GL_TEXTURE0_ARB + unit);
+-
+-	    glBindTexture (wScreen->target,
+-			   wScreen->texture[TINDEX (wScreen, 0)]);
+-
+-	    plane[1] = plane[2] = 0.0f;
+-	    plane[0] = wScreen->tx / (GLfloat) screen->width ();
+-	    plane[3] = 0.0f;
+-
+-	    glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
+-	    glTexGenfv (GL_S, GL_EYE_PLANE, plane);
+-	    glEnable (GL_TEXTURE_GEN_S);
+-
+-	    plane[0] = plane[2] = 0.0f;
+-	    plane[1] = wScreen->ty / (GLfloat) screen->height ();
+-	    plane[3] = 0.0f;
+-
+-	    glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
+-	    glTexGenfv (GL_T, GL_EYE_PLANE, plane);
+-	    glEnable (GL_TEXTURE_GEN_T);
++	    GLFramebufferObject::rebind (oldFbo);
++	    glViewport (oldViewport[0], oldViewport[1],
++			oldViewport[2], oldViewport[3]);
++
++	    vertexBuffer[PAINT]->begin ();
++	    vertexBuffer[PAINT]->addVertices (6, &vertexData[0]);
++	    vertexBuffer[PAINT]->addTexCoords (0, 6, &textureData[0]);
++	    vertexBuffer[PAINT]->end ();
++
++	    glEnable (GL_TEXTURE_2D);
++
++	    glActiveTexture (GL_TEXTURE0);
++	    fbo->tex ()->setFilter (GL_LINEAR);
++	    glBindTexture (GL_TEXTURE_2D, fbo->tex ()->name ());
++	    vertexBuffer[PAINT]->addUniform ("baseTex", 0);
++
++	    glActiveTexture (GL_TEXTURE1);
++	    waterFbo[INDEX (this, 0)]->tex ()->setFilter (GL_LINEAR);
++	    glBindTexture (GL_TEXTURE_2D,
++			waterFbo[INDEX (this, 0)]->tex ()->name ());
++	    vertexBuffer[PAINT]->addUniform ("waveTex", 1);
++
++	    vertexBuffer[PAINT]->addUniform3f ("lightVec",
++					lightVec[0],
++					lightVec[1],
++					lightVec[2]);
++	    vertexBuffer[PAINT]->addUniform ("offsetScale", offsetScale);
++	    GLboolean isBlendingEnabled;
++	    glGetBooleanv (GL_BLEND, &isBlendingEnabled);
++	    glDisable (GL_BLEND);
++	    vertexBuffer[PAINT]->render ();
++	    if (isBlendingEnabled)
++		glEnable (GL_BLEND);
+ 
+-	    GL::activeTexture (GL_TEXTURE0_ARB);
+-
+-	    GL::programEnvParameter4f (GL_FRAGMENT_PROGRAM_ARB, param,
+-				       texture->matrix ().yy *
+-				       wScreen->offsetScale,
+-				       -texture->matrix ().xx *
+-				       wScreen->offsetScale,
+-				       0.0f, 0.0f);
+-	}
+-
+-	/* to get appropriate filtering of texture */
+-	mask |= PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK;
+-
+-	gWindow->glDrawTexture (texture, fa, mask);
+-
+-	if (function)
+-	{
+-	    GL::activeTexture (GL_TEXTURE0_ARB + unit);
+-	    glDisable (GL_TEXTURE_GEN_T);
+-	    glDisable (GL_TEXTURE_GEN_S);
+-	    glBindTexture (wScreen->target, 0);
+-	    GL::activeTexture (GL_TEXTURE0_ARB);
+-
+-	    gScreen->setLighting (lighting);
++	    glBindTexture (GL_TEXTURE_2D, 0);
++	    glDisable (GL_TEXTURE_2D);
+ 	}
+     }
+-    else
+-    {
+-	gWindow->glDrawTexture (texture, attrib, mask);
+-    }
+ }
+ 
+ /* TODO: a way to control the speed */
+@@ -976,8 +437,6 @@ WaterScreen::preparePaint (int msSinceLa
+ 		    p[0].y = screen->height ();
+ 		}
+ 
+-		/* software rasterizer doesn't support triangles yet so wiper
+-		   effect will only work with FBOs right now */
+ 		waterVertices (GL_TRIANGLES, p, 3, 0.0f);
+ 	    }
+ 
+@@ -985,7 +444,7 @@ WaterScreen::preparePaint (int msSinceLa
+ 
+ 	}
+ 
+-	waterUpdate (0.8f);
++	waterUpdate (0.8);
+     }
+ 
+     cScreen->preparePaint (msSinceLastPaint);
+@@ -998,15 +457,10 @@ WaterScreen::donePaint ()
+ 	cScreen->damageScreen ();
+     else
+     {
+-	WaterWindow *ww;
+-
+ 	cScreen->preparePaintSetEnabled (this, false);
++	gScreen->glPaintOutputSetEnabled (this, false);
++	gScreen->glPaintCompositedOutputSetEnabled (this, false);
+ 	cScreen->donePaintSetEnabled (this, false);
+-	foreach (CompWindow *w, screen->windows ())
+-	{
+-	    ww = WaterWindow::get (w);
+-	    ww->gWindow->glDrawTextureSetEnabled (ww, false);
+-	}
+     }
+ 
+     cScreen->donePaint ();
+@@ -1029,7 +483,6 @@ WaterScreen::handleMotionEvent ()
+ 
+ 	cScreen->damageScreen ();
+     }
+-
+ }
+ 
+ static bool
+@@ -1059,7 +512,7 @@ waterInitiate (CompAction         *actio
+ 	    p.x = waterLastPointerX = xRoot;
+ 	    p.y = waterLastPointerY = yRoot;
+ 
+-	    ws->waterVertices (GL_POINTS, &p, 1, 0.8f);
++ 	    ws->waterVertices (GL_POINTS, &p, 1, 1.0f);
+ 
+ 	    ws->cScreen->damageScreen ();
+ 	}
+@@ -1263,7 +716,7 @@ WaterScreen::optionChange (WaterOptions:
+ {
+     switch (num) {
+ 	case WaterOptions::OffsetScale:
+-	    offsetScale = optionGetOffsetScale () * 50.0f;
++	    offsetScale = optionGetOffsetScale () * 10.0f;
+ 	    break;
+ 	case WaterOptions::RainDelay:
+ 	    if (rainTimer.active ())
+@@ -1272,6 +725,15 @@ WaterScreen::optionChange (WaterOptions:
+ 				    (float)optionGetRainDelay () * 1.2);
+ 	    }
+ 	    break;
++	case WaterOptions::LightVecX:
++	    lightVec[0] = optionGetLightVecX();
++	    break;
++	case WaterOptions::LightVecY:
++	    lightVec[1] = optionGetLightVecY();
++	    break;
++	case WaterOptions::LightVecZ:
++	    lightVec[2] = optionGetLightVecZ();
++	    break;
+ 	default:
+ 	    break;
+     }
+@@ -1282,21 +744,20 @@ WaterScreen::WaterScreen (CompScreen *sc
+     cScreen (CompositeScreen::get (screen)),
+     gScreen (GLScreen::get (screen)),
+     grabIndex (0),
+-    width (0),
+-    height (0),
+ 
+-    program (0),
++    oldFbo (NULL),
++    fboIndex (0),
++    useFbo (true),
++
++    texWidth (0),
++    texHeight (0),
+ 
+-    tIndex (0),
+     target (0),
+     tx (0),
+     ty (0),
+ 
+     count (0),
+ 
+-    fbo (0),
+-    fboStatus (0),
+-
+     data (NULL),
+     d0 (NULL),
+     d1 (NULL),
+@@ -1304,20 +765,22 @@ WaterScreen::WaterScreen (CompScreen *sc
+ 
+     wiperAngle (0),
+     wiperSpeed (0),
+-
+-    bumpMapFunctions ()
++    lightVec(GLVector(optionGetLightVecX(),
++		      optionGetLightVecY(),
++		      optionGetLightVecZ()))
+ {
+-    offsetScale = optionGetOffsetScale () * 50.0f;
+-
+-    memset (texture, 0, sizeof (GLuint) * TEXTURE_NUM);
++    offsetScale = optionGetOffsetScale () * 10.0f;
+ 
+     wiperTimer.setCallback (boost::bind (&WaterScreen::wiperTimeout, this));
+     rainTimer.setCallback (boost::bind (&WaterScreen::rainTimeout, this));
+ 
+-    waterReset ();
++    waterSetup ();
+ 
+     optionSetOffsetScaleNotify (boost::bind (&WaterScreen::optionChange, this, _2));
+-    optionSetRainDelayNotify (boost::bind (&WaterScreen::optionChange, this, _2));
++    optionSetRainDelayNotify   (boost::bind (&WaterScreen::optionChange, this, _2));
++    optionSetLightVecXNotify   (boost::bind (&WaterScreen::optionChange, this, _2));
++    optionSetLightVecYNotify   (boost::bind (&WaterScreen::optionChange, this, _2));
++    optionSetLightVecZNotify   (boost::bind (&WaterScreen::optionChange, this, _2));
+ 
+     optionSetInitiateKeyInitiate (waterInitiate);
+     optionSetInitiateKeyTerminate (waterTerminate);
+@@ -1329,29 +792,28 @@ WaterScreen::WaterScreen (CompScreen *sc
+ 
+     ScreenInterface::setHandler (screen, false);
+     CompositeScreenInterface::setHandler (cScreen, false);
++    GLScreenInterface::setHandler (gScreen, false);
+ }
+ 
+ WaterScreen::~WaterScreen ()
+ {
+-    if (fbo)
+-	GL::deleteFramebuffers (1, &fbo);
++    if (program[SET])
++	delete program[SET];
++
++    if (program[UPDATE])
++	delete program[UPDATE];
++
++    if (program[PAINT])
++	delete program[PAINT];
+ 
+-    for (unsigned int i = 0; i < TEXTURE_NUM; i++)
++    for (int i = 0; i < TEXTURE_NUM; i++)
+     {
+-	if (texture[i])
+-	    glDeleteTextures (1, &texture[i]);
++	if (waterFbo[i])
++	    delete waterFbo[i];
+     }
+ 
+-    if (program)
+-	GL::deletePrograms (1, &program);
+-
+     if (data)
+ 	free (data);
+-
+-    foreach (WaterFunction &f, bumpMapFunctions)
+-    {
+-	GLFragment::destroyFragmentFunction (f.id);
+-    }
+ }
+ 
+ bool
+--- compiz-0.9.7.6.orig/plugins/water/src/water.h
++++ compiz-0.9.7.6/plugins/water/src/water.h
+@@ -21,6 +21,7 @@
+  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+  *
+  * Author: David Reveman <davidr@xxxxxxxxxx>
++ *         Frederic Plourde <frederic.plourde@xxxxxxxxxxxxxxx>
+  */
+ 
+ #include "water_options.h"
+@@ -29,6 +30,8 @@
+ 
+ #include <composite/composite.h>
+ #include <opengl/opengl.h>
++#include <opengl/framebufferobject.h>
++#include "shaders.h"
+ 
+ 
+ #define WATER_SCREEN(s) \
+@@ -38,27 +41,22 @@
+ 
+ #define K 0.1964f
+ 
+-#define TEXTURE_NUM 3
++#define TEXTURE_NUM  3
++#define PROG_NUM 3
+ 
+-#define TINDEX(ws, i) (((ws)->tIndex + (i)) % TEXTURE_NUM)
++#define INDEX(ws, i) (((ws)->fboIndex + (i)) % TEXTURE_NUM)
+ 
+-#define WATER_INITIATE_MODIFIERS_DEFAULT (ControlMask | CompSuperMask)
+-
+-struct WaterFunction {
+-    GLFragment::FunctionId id;
+-
+-    int target;
+-    int param;
+-    int unit;
+-};
++enum programTypes { SET, UPDATE, PAINT};
+ 
+ class WaterScreen :
+     public ScreenInterface,
++    public GLScreenInterface,
+     public CompositeScreenInterface,
+     public PluginClassHandler<WaterScreen,CompScreen>,
+     public WaterOptions
+ {
+     public:
++
+ 	WaterScreen (CompScreen *screen);
+ 	~WaterScreen ();
+ 
+@@ -66,34 +64,23 @@ class WaterScreen :
+ 
+ 	void handleEvent (XEvent *);
+ 
++	void glPaintCompositedOutput (const CompRegion    &region,
++				      GLFramebufferObject *fbo,
++				      unsigned int         mask);
+ 	void preparePaint (int);
+ 	void donePaint ();
+ 
+-	GLFragment::FunctionId
+-	getBumpMapFragmentFunction (GLTexture *texture,
+-				    int       unit,
+-				    int       param);
+-
+-	void allocTexture (int index);
+-
+-	bool fboPrologue (int tIndex);
++	bool fboPrologue (int fboIndex);
+ 	void fboEpilogue ();
+-	bool fboUpdate (float dt, float fade);
+-	bool fboVertices (GLenum type, XPoint *p, int n, float v);
++	bool fboUpdate   (float dt, float fade);
+ 
+-	void softwareUpdate (float dt, float fade);
+-	void softwarePoints (XPoint *p, int n, float add);
+-	void softwareLines (XPoint *p, int n, float v);
+-	void softwareVertices (GLenum type, XPoint *p, int n, float v);
+-
+-	void waterUpdate (float dt);
+-	void scaleVertices (XPoint *p, int n);
++	void waterUpdate   (float dt);
+ 	void waterVertices (GLenum type, XPoint *p, int n, float v);
+ 
+ 	bool rainTimeout ();
+ 	bool wiperTimeout ();
+ 
+-	void waterReset ();
++	void waterSetup ();
+ 
+ 	void handleMotionEvent ();
+ 
+@@ -104,20 +91,26 @@ class WaterScreen :
+ 
+ 	CompScreen::GrabHandle grabIndex;
+ 
+-	int width, height;
++	GLProgram      *program[PROG_NUM];
++	GLVertexBuffer *vertexBuffer[PROG_NUM];
++
++	static GLfloat vertexData[18];
+ 
+-	GLuint program;
+-	GLuint texture[TEXTURE_NUM];
++	static GLfloat textureData[12];
+ 
+-	int     tIndex;
++	GLFramebufferObject *waterFbo[TEXTURE_NUM];
++
++	GLFramebufferObject *oldFbo;
++	GLint oldViewport[4];
++	int    fboIndex;
++	bool   useFbo;
++
++	int texWidth, texHeight;
+ 	GLenum  target;
+ 	GLfloat tx, ty;
+ 
+ 	int count;
+ 
+-	GLuint fbo;
+-	GLint  fboStatus;
+-
+ 	void          *data;
+ 	float         *d0;
+ 	float         *d1;
+@@ -129,37 +122,14 @@ class WaterScreen :
+ 	float wiperAngle;
+ 	float wiperSpeed;
+ 
+-	std::vector<WaterFunction> bumpMapFunctions;
+-};
+-
+-class WaterWindow :
+-    public GLWindowInterface,
+-    public PluginClassHandler<WaterWindow,CompWindow>
+-{
+-    public:
+-	WaterWindow (CompWindow *window) :
+-	    PluginClassHandler<WaterWindow,CompWindow> (window),
+-	    window (window),
+-	    gWindow (GLWindow::get (window)),
+-	    wScreen (WaterScreen::get (screen)),
+-	    gScreen (GLScreen::get (screen))
+-	{
+-	    GLWindowInterface::setHandler (gWindow, false);
+-	}
+-
+-	void glDrawTexture (GLTexture *texture, GLFragment::Attrib &,
+-			    unsigned int);
+-
+-	CompWindow  *window;
+-	GLWindow    *gWindow;
+-	WaterScreen *wScreen;
+-	GLScreen    *gScreen;
++	GLVector lightVec;
+ };
+ 
+ class WaterPluginVTable :
+-    public CompPlugin::VTableForScreenAndWindow<WaterScreen,WaterWindow>
++    public CompPlugin::VTableForScreen<WaterScreen>
+ {
+     public:
+ 
+ 	bool init ();
+ };
++
+--- /dev/null
++++ compiz-0.9.7.6/plugins/water/src/shaders.h
+@@ -0,0 +1,201 @@
++/*
++ * Copyright © 2011 Collabora Ltd.
++ *
++ * Permission to use, copy, modify, distribute, and sell this software
++ * and its documentation for any purpose is hereby granted without
++ * fee, provided that the above copyright notice appear in all copies
++ * and that both that copyright notice and this permission notice
++ * appear in supporting documentation, and that the name of
++ * Collabora Ltd. not be used in advertising or publicity pertaining to
++ * distribution of the software without specific, written prior permission.
++ * Collabora Ltd. makes no representations about the suitability of this
++ * software for any purpose. It is provided "as is" without express or
++ * implied warranty.
++ *
++ * COLLABORA LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
++ * NO EVENT SHALL LINARO LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
++ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
++ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
++ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
++ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ *
++ * Authors: Frederic Plourde <frederic.plourde@xxxxxxxxxxxxxxx>
++ */
++
++#ifndef _COMPIZ_WATERSHADERS_H
++#define _COMPIZ_WATERSHADERS_H
++
++
++// This vertex shader is used to set water vertices ...
++static std::string set_water_vertices_vertex_shader = "                     \n\
++#ifdef GL_ES                                                                \n\
++precision mediump float;                                                    \n\
++#endif                                                                      \n\
++                                                                            \n\
++attribute vec3 position;                                                    \n\
++                                                                            \n\
++void main ()                                                                \n\
++{                                                                           \n\
++    gl_PointSize = 3.0;                                                     \n\
++    gl_Position = vec4(position, 1.0);                                      \n\
++                                                                            \n\
++}";
++
++// This fragment shader is used to draw water primitives ...
++// we're only setting the height here, so we only care about the .w coord.
++static std::string set_water_vertices_fragment_shader = "                   \n\
++#ifdef GL_ES                                                                \n\
++precision mediump float;                                                    \n\
++#endif                                                                      \n\
++                                                                            \n\
++uniform float color;                                                        \n\
++                                                                            \n\
++void main ()                                                                \n\
++{                                                                           \n\
++    gl_FragColor = vec4(0.0, 0.0, 0.0, color);                              \n\
++}";
++
++
++
++
++// This vertex shader is used to update water vertices...
++static std::string update_water_vertices_vertex_shader = "                  \n\
++#ifdef GL_ES                                                                \n\
++precision mediump float;                                                    \n\
++#endif                                                                      \n\
++                                                                            \n\
++attribute vec3 position;                                                    \n\
++attribute vec2 texCoord0;                                                   \n\
++                                                                            \n\
++varying vec2 vTexCoord0;                                                    \n\
++                                                                            \n\
++void main ()                                                                \n\
++{                                                                           \n\
++    vTexCoord0 = texCoord0;                                                 \n\
++    gl_Position = vec4(position, 1.0);                                      \n\
++                                                                            \n\
++}";
++
++// This fragment shader is used to compute new normal + height of water vertices.
++// here we're using two input textures, previous and current.
++static std::string update_water_vertices_fragment_shader = "                \n\
++#ifdef GL_ES                                                                \n\
++precision mediump float;                                                    \n\
++#endif                                                                      \n\
++                                                                            \n\
++uniform sampler2D prevTex;                                                  \n\
++uniform sampler2D currTex;                                                  \n\
++                                                                            \n\
++varying vec2 vTexCoord0;                                                    \n\
++                                                                            \n\
++uniform float timeLapse;                                                    \n\
++uniform float fade;                                                         \n\
++                                                                            \n\
++void main ()                                                                \n\
++{                                                                           \n\
++    vec2 t01, t21, t10, t12;                                                \n\
++    vec4 c01, c21, c10, c12;                                                \n\
++    vec4 curr, prev, v;                                                     \n\
++    float accel;                                                            \n\
++                                                                            \n\
++    // fetch current and previous normals                                   \n\
++    prev = texture%s (prevTex, vTexCoord0);                                 \n\
++    curr = texture%s (currTex, vTexCoord0);                                 \n\
++                                                                            \n\
++    // sample offsets                                                       \n\
++    t01 = vTexCoord0 + vec2 (- %f, 0.0);                                    \n\
++    t21 = vTexCoord0 + vec2 (  %f, 0.0);                                    \n\
++    t10 = vTexCoord0 + vec2 ( 0.0,- %f);                                    \n\
++    t12 = vTexCoord0 + vec2 ( 0.0,  %f);                                    \n\
++                                                                            \n\
++    // fetch necessary samples                                              \n\
++    c01 = texture%s (currTex, t01);                                         \n\
++    c21 = texture%s (currTex, t21);                                         \n\
++    c10 = texture%s (currTex, t10);                                         \n\
++    c12 = texture%s (currTex, t12);                                         \n\
++                                                                            \n\
++    // x/y normals from height                                              \n\
++    v = vec4 (0.0, 0.0, 0.75, 0.0);                                         \n\
++    v.x = c01.w - c21.w;                                                    \n\
++    v.y = c12.w - c10.w;                                                    \n\
++                                                                            \n\
++    // bumpiness                                                            \n\
++    v = normalize (v);                                                      \n\
++                                                                            \n\
++    // add scale and bias                                                   \n\
++    v = (v * 0.5) + 0.5;                                                    \n\
++                                                                            \n\
++    // done with computing the normal, continue with computing              \n\
++    // the next height value                                                \n\
++    accel = (curr.w * -4.0) + (c10.w + c12.w + c01.w + c21.w);              \n\
++                                                                            \n\
++    // store new height in alpha component                                  \n\
++    v.w = (accel * timeLapse) + ((curr.w * 2.0) - prev.w);                  \n\
++                                                                            \n\
++    // fade out height                                                      \n\
++    v.w *= fade;                                                            \n\
++                                                                            \n\
++    gl_FragColor = v;                                                       \n\
++}";
++
++
++
++
++// This vertex shader is used when painting our bump map FX over
++// final composited screen FBO
++static std::string paint_water_vertices_vertex_shader = "                   \n\
++#ifdef GL_ES                                                                \n\
++precision mediump float;                                                    \n\
++#endif                                                                      \n\
++                                                                            \n\
++attribute vec3 position;                                                    \n\
++attribute vec2 texCoord0;                                                   \n\
++                                                                            \n\
++varying vec2 vTexCoord0;                                                    \n\
++                                                                            \n\
++void main ()                                                                \n\
++{                                                                           \n\
++    vTexCoord0 = texCoord0;                                                 \n\
++    gl_Position = vec4(position, 1.0);                                      \n\
++                                                                            \n\
++}";
++
++// This fragment shader is used to produce our dot3 bump mapping output,
++// blended over final composited glScreen FBO.
++// here we're using two input textures :
++//   1) The final composited FBO color attachment over which we're
++//      applying our bump map FX (baseTex)
++//   2) The updated bump map (waveTex)
++static std::string paint_water_vertices_fragment_shader = "                 \n\
++#ifdef GL_ES                                                                \n\
++precision mediump float;                                                    \n\
++#endif                                                                      \n\
++                                                                            \n\
++uniform sampler2D baseTex;                                                  \n\
++uniform sampler2D waveTex;                                                  \n\
++                                                                            \n\
++varying vec2 vTexCoord0;                                                    \n\
++                                                                            \n\
++uniform vec3  lightVec;                                                     \n\
++uniform float offsetScale;                                                  \n\
++                                                                            \n\
++void main ()                                                                \n\
++{                                                                           \n\
++    vec4 normal = texture2D (waveTex, vTexCoord0);                          \n\
++    float height = normal.w;                                                \n\
++    float diffuse = 0.75;                                                   \n\
++    vec4 offset;                                                            \n\
++                                                                            \n\
++    normal = normalize ((normal * 2.0) - 1.0);                              \n\
++                                                                            \n\
++    offset.x = normal.x * height * offsetScale/%d.0;                        \n\
++    offset.y = normal.y * height * offsetScale/%d.0;                        \n\
++    vec4 baseColor  = texture2D (baseTex, vTexCoord0 + offset.xy);          \n\
++                                                                            \n\
++    float diffFact = dot (normal.xyz, vec3(lightVec.xy, 0.0)) * diffuse;    \n\
++    gl_FragColor = vec4 (vec3 (baseColor) + diffFact, 1.0);                 \n\
++}";
++
++#endif // _COMPIZ_WATERSHADERS_H
++
+--- compiz-0.9.7.6.orig/plugins/resize/resize.xml.in
++++ compiz-0.9.7.6/plugins/resize/resize.xml.in
+@@ -28,7 +28,7 @@
+ 	    <option name="mode" type="int">
+ 		<_short>Default Resize Mode</_short>
+ 		<_long>Default mode used for window resizing</_long>
+-		<default>2</default>
++		<default>0</default>
+ 		<min>0</min>
+ 		<max>3</max>
+ 		<desc>
+@@ -57,9 +57,9 @@
+ 		<_short>Border Color</_short>
+ 		<_long>Border color used for outline and rectangle resize modes</_long>
+ 		<default>
+-		    <red>0xfbfb</red>
+-		    <green>0x8b8b</green>
+-		    <blue>0x0</blue>
++		    <red>0x2f2f</red>
++		    <green>0x2f2f</green>
++		    <blue>0x4f4f</blue>
+ 		    <alpha>0x9f9f</alpha>
+ 		</default>
+ 	    </option>
+@@ -67,10 +67,10 @@
+ 		<_short>Fill Color</_short>
+ 		<_long>Fill color used for rectangle resize mode</_long>
+ 		<default>
+-		    <red>0xfbfb</red>
+-		    <green>0x8b8b</green>
+-		    <blue>0x0</blue>
+-		    <alpha>0x1919</alpha>
++		    <red>0x2f2f</red>
++		    <green>0x2f2f</green>
++		    <blue>0x4f4f</blue>
++		    <alpha>0x4f4f</alpha>
+ 		</default>
+ 	    </option>
+ 	    <subgroup>
+--- compiz-0.9.7.6.orig/plugins/resize/src/resize.cpp
++++ compiz-0.9.7.6/plugins/resize/src/resize.cpp
+@@ -1525,60 +1525,113 @@ ResizeScreen::glPaintRectangle (const GL
+ 				unsigned short            *borderColor,
+ 				unsigned short            *fillColor)
+ {
+-    BoxRec   	   box;
+-    GLMatrix 	   sTransform (transform);
+-    GLint    	   origSrc, origDst;
+-    float_t	   fc[4], bc[4];
++    GLVertexBuffer *streamingBuffer = GLVertexBuffer::streamingBuffer ();
+ 
++    BoxRec   	    box;
++    GLMatrix 	    sTransform (transform);
++    GLfloat         vertexData [12];
++    GLfloat         vertexData2[24];
++    GLint    	    origSrc, origDst, origSrcAlpha, origDstAlpha;
++    GLushort	    fc[4], bc[4];
++
++#ifdef USE_GLES
++    glGetIntegerv (GL_BLEND_SRC_RGB, &origSrc);
++    glGetIntegerv (GL_BLEND_DST_RGB, &origDst);
++    glGetIntegerv (GL_BLEND_SRC_ALPHA, &origSrcAlpha);
++    glGetIntegerv (GL_BLEND_DST_ALPHA, &origDstAlpha);
++#else
+     glGetIntegerv (GL_BLEND_SRC, &origSrc);
+     glGetIntegerv (GL_BLEND_DST, &origDst);
++#endif
+ 
+     /* Premultiply the alpha values */
+-    
+-    bc[3] = (float) borderColor[3] / (float) 65535.0f;
++    bc[3] =  (float) borderColor[3] / (float) 65535.0f;
+     bc[0] = ((float) borderColor[0] / 65535.0f) * bc[3];
+     bc[1] = ((float) borderColor[1] / 65535.0f) * bc[3];
+     bc[2] = ((float) borderColor[2] / 65535.0f) * bc[3];
+ 
+     getPaintRectangle (&box);
+ 
+-    glPushMatrix ();
++    vertexData[0]  = box.x1;
++    vertexData[1]  = box.y1;
++    vertexData[2]  = 0.0f;
++    vertexData[3]  = box.x1;
++    vertexData[4]  = box.y2;
++    vertexData[5]  = 0.0f;
++    vertexData[6]  = box.x2;
++    vertexData[7]  = box.y1;
++    vertexData[8]  = 0.0f;
++    vertexData[9]  = box.x2;
++    vertexData[10] = box.y2;
++    vertexData[11] = 0.0f;
++
++    // FIXME: this is a quick work-around.
++    // GL_LINE_LOOP and GL_LINE_STRIP primitive types in the SGX Pvr X11 driver
++    // take special number of vertices (and reorder them). Thus, usage of
++    // those line primitive is currently not supported by our GLVertexBuffer
++    // implementation. This is a quick workaround to make it all work until
++    // we come up with a better GLVertexBuffer::render(...) function.
++
++    vertexData2[0]  = box.x1;
++    vertexData2[1]  = box.y1;
++    vertexData2[2]  = 0.0f;
++    vertexData2[3]  = box.x1;
++    vertexData2[4]  = box.y2;
++    vertexData2[5]  = 0.0f;
++    vertexData2[6]  = box.x1;
++    vertexData2[7]  = box.y2;
++    vertexData2[8]  = 0.0f;
++    vertexData2[9]  = box.x2;
++    vertexData2[10] = box.y2;
++    vertexData2[11] = 0.0f;
++    vertexData2[12] = box.x2;
++    vertexData2[13] = box.y2;
++    vertexData2[14] = 0.0f;
++    vertexData2[15] = box.x2;
++    vertexData2[16] = box.y1;
++    vertexData2[17] = 0.0f;
++    vertexData2[18] = box.x2;
++    vertexData2[19] = box.y1;
++    vertexData2[20] = 0.0f;
++    vertexData2[21] = box.x1;
++    vertexData2[22] = box.y1;
++    vertexData2[23] = 0.0f;
+ 
+     sTransform.toScreenSpace (output, -DEFAULT_Z_CAMERA);
+ 
+-    glLoadMatrixf (sTransform.getMatrix ());
+-
+-    glDisableClientState (GL_TEXTURE_COORD_ARRAY);
+-    glEnable (GL_BLEND);
+     glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ 
+     /* fill rectangle */
+     if (fillColor)
+     {
+-	fc[3] = (float) fillColor[3] / (float) 65535.0f;
+-	fc[0] = ((float) fillColor[0] / 65535.0f) * fc[3];
+-	fc[1] = ((float) fillColor[1] / 65535.0f) * fc[3];
+-	fc[2] = ((float) fillColor[2] / 65535.0f) * fc[3];
+-
+-	glColor4f (fc[0], fc[1], fc[2], fc[3]);
+-	glRecti (box.x1, box.y2, box.x2, box.y1);
++	fc[3] = fillColor[3];
++	fc[0] = fillColor[0] * fc[3];
++	fc[1] = fillColor[1] * fc[3];
++	fc[2] = fillColor[2] * fc[3];
++
++	streamingBuffer->begin (GL_TRIANGLE_STRIP);
++	streamingBuffer->addColors (1, fc);
++	streamingBuffer->addVertices (4, &vertexData[0]);
++	streamingBuffer->end ();
++	streamingBuffer->render (sTransform);
+     }
+ 
+     /* draw outline */
+-    glColor4f (bc[0], bc[1], bc[2], bc[3]);
+     glLineWidth (2.0);
+-    glBegin (GL_LINE_LOOP);
+-    glVertex2i (box.x1, box.y1);
+-    glVertex2i (box.x2, box.y1);
+-    glVertex2i (box.x2, box.y2);
+-    glVertex2i (box.x1, box.y2);
+-    glEnd ();
+-
+-    /* clean up */
+-    glColor4usv (defaultColor);
+-    glDisable (GL_BLEND);
+-    glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+-    glPopMatrix ();
++    streamingBuffer->begin (GL_LINES);
++    streamingBuffer->addColors (1, borderColor);
++    streamingBuffer->addVertices (8, &vertexData2[0]);
++    streamingBuffer->end ();
++    streamingBuffer->render (sTransform);
++
++    cScreen->damageScreen ();
++
++#ifdef USE_GLES
++    glBlendFuncSeparate (origSrc, origDst,
++                         origSrcAlpha, origDstAlpha);
++#else
++    glBlendFunc (origSrc, origDst);
++#endif
+ }
+ 
+ bool
+@@ -1589,6 +1642,7 @@ ResizeScreen::glPaintOutput (const GLScr
+ 			     unsigned int              mask)
+ {
+     bool status;
++    GLboolean isBlendingEnabled;
+ 
+     if (w)
+     {
+@@ -1605,6 +1659,9 @@ ResizeScreen::glPaintOutput (const GLScr
+ 	border = optionGetBorderColor ();
+ 	fill   = optionGetFillColor ();
+ 
++	glGetBooleanv (GL_BLEND, &isBlendingEnabled);
++	glEnable (GL_BLEND);
++
+ 	switch (mode) {
+ 	    case ResizeOptions::ModeOutline:
+ 		glPaintRectangle (sAttrib, transform, output, border, NULL);
+@@ -1614,6 +1671,9 @@ ResizeScreen::glPaintOutput (const GLScr
+ 	    default:
+ 		break;
+ 	}
++
++	if (!isBlendingEnabled)
++	    glDisable (GL_BLEND);
+     }
+ 
+     return status;
+@@ -1641,9 +1701,9 @@ ResizeWindow::glPaint (const GLWindowPai
+ 	status = gWindow->glPaint (attrib, transform, region,
+ 				   mask | PAINT_WINDOW_NO_CORE_INSTANCE_MASK);
+ 
+-	GLFragment::Attrib fragment (gWindow->lastPaintAttrib ());
++	GLWindowPaintAttrib lastAttrib (gWindow->lastPaintAttrib ());
+ 
+-	if (window->alpha () || fragment.getOpacity () != OPAQUE)
++	if (window->alpha () || lastAttrib.opacity != OPAQUE)
+ 	    mask |= PAINT_WINDOW_TRANSLUCENT_MASK;
+ 
+ 	rScreen->getPaintRectangle (&box);
+@@ -1661,13 +1721,8 @@ ResizeWindow::glPaint (const GLWindowPai
+ 			      (rScreen->geometry.y - y) / yScale - yOrigin,
+ 			      0.0f);
+ 
+-	glPushMatrix ();
+-	glLoadMatrixf (wTransform.getMatrix ());
+-
+-	gWindow->glDraw (wTransform, fragment, region,
++	gWindow->glDraw (wTransform, lastAttrib, region,
+ 			 mask | PAINT_WINDOW_TRANSFORMED_MASK);
+-
+-	glPopMatrix ();
+     }
+     else
+     {
+--- compiz-0.9.7.6.orig/plugins/annotate/src/annotate.cpp
++++ compiz-0.9.7.6/plugins/annotate/src/annotate.cpp
+@@ -629,11 +629,14 @@ AnnoScreen::glPaintOutput (const GLScree
+ 
+     if (status)
+     {
++	GLVertexBuffer *streamingBuffer = GLVertexBuffer::streamingBuffer ();
++	GLfloat         vertexData[18];
++	GLfloat         textureData[12];
+ 	CompRect	rect;
+ 	GLMatrix	sTransform = transform;
+ 	int		numRect;
+ 	int		pos = 0;
+-	float		vectorX, vectorY, offset;
++	float		offset;
+ 	int		angle;
+ 
+ 	offset = optionGetStrokeWidth () / 2;
+@@ -641,12 +644,6 @@ AnnoScreen::glPaintOutput (const GLScree
+ 	/* This replaced prepareXCoords (s, output, -DEFAULT_Z_CAMERA) */
+ 	sTransform.toScreenSpace (output, -DEFAULT_Z_CAMERA);
+ 
+-	glPushMatrix ();
+-	glLoadMatrixf (sTransform.getMatrix ());
+-
+-	glDisableClientState (GL_TEXTURE_COORD_ARRAY);
+-	glEnable (GL_BLEND);
+-
+ 	if (content && !region.isEmpty ())
+ 	{
+ 	    foreach (GLTexture *tex, texture)
+@@ -656,34 +653,66 @@ AnnoScreen::glPaintOutput (const GLScree
+ 
+ 	        tex->enable (GLTexture::Fast);
+ 
+-	        glBegin (GL_QUADS);
++	        streamingBuffer->begin (GL_TRIANGLES);
+ 
+ 	        while (numRect--)
+ 	        {
+-	            glTexCoord2f (
+-		        COMP_TEX_COORD_X (tex->matrix (), rect.at (pos).x1 ()),
+-		        COMP_TEX_COORD_Y (tex->matrix (), rect.at (pos).y2 ()));
+-	            glVertex2i (rect.at (pos).x1 (), rect.at (pos).y2 ());
+-
+-	            glTexCoord2f (
+-		        COMP_TEX_COORD_X (tex->matrix (), rect.at (pos).x2 ()),
+-		        COMP_TEX_COORD_Y (tex->matrix (), rect.at (pos).y2 ()));
+-	            glVertex2i (rect.at (pos).x2 (), rect.at (pos).y2 ());
+-
+-	            glTexCoord2f (
+-		        COMP_TEX_COORD_X (tex->matrix (), rect.at (pos).x2 ()),
+-		        COMP_TEX_COORD_Y (tex->matrix (), rect.at (pos).y1 ()));
+-	            glVertex2i (rect.at (pos).x2 (), rect.at (pos).y1 ());
+-
+-	            glTexCoord2f (
+-		        COMP_TEX_COORD_X (tex->matrix (), rect.at (pos).x1 ()),
+-		        COMP_TEX_COORD_Y (tex->matrix (), rect.at (pos).y1 ()));
+-	            glVertex2i (rect.at (pos).x1 (), rect.at (pos).y1 ());
++		    GLfloat tx1 = COMP_TEX_COORD_X (tex->matrix (),
++		                                       rect.at (pos).x1 ());
++		    GLfloat tx2 = COMP_TEX_COORD_X (tex->matrix (),
++		                                       rect.at (pos).x2 ());
++		    GLfloat ty1 = COMP_TEX_COORD_Y (tex->matrix (),
++		                                       rect.at (pos).y1 ());
++		    GLfloat ty2 = COMP_TEX_COORD_Y (tex->matrix (),
++		                                       rect.at (pos).y2 ());
++
++		    vertexData[0]  = rect.at (pos).x1 ();
++		    vertexData[1]  = rect.at (pos).y1 ();
++		    vertexData[2]  = 0.0f;
++		    vertexData[3]  = rect.at (pos).x1 ();
++		    vertexData[4]  = rect.at (pos).y2 ();
++		    vertexData[5]  = 0.0f;
++		    vertexData[6]  = rect.at (pos).x2 ();
++		    vertexData[7]  = rect.at (pos).y1 ();
++		    vertexData[8]  = 0.0f;
++		    vertexData[9]  = rect.at (pos).x1 ();
++		    vertexData[10] = rect.at (pos).y2 ();
++		    vertexData[11] = 0.0f;
++
++		    vertexData[12] = rect.at (pos).x2 ();
++		    vertexData[13] = rect.at (pos).y2 ();
++		    vertexData[14] = 0.0f;
++
++		    vertexData[15] = rect.at (pos).x2 ();
++		    vertexData[16] = rect.at (pos).y1 ();
++		    vertexData[17] = 0.0f;
++
++		    textureData[0]  = tx1;
++		    textureData[1]  = ty1;
++
++		    textureData[2]  = tx1;
++		    textureData[3]  = ty2;
++
++		    textureData[4]  = tx2;
++		    textureData[5]  = ty1;
++
++		    textureData[6]  = tx1;
++		    textureData[7]  = ty2;
++
++		    textureData[8]  = tx2;
++		    textureData[9]  = ty2;
++
++		    textureData[10] = tx2;
++		    textureData[11] = ty1;
+ 
++		    streamingBuffer->addVertices (6, vertexData);
++		    streamingBuffer->addTexCoords (0, 6, textureData);
+ 	            pos++;
+ 	        }
+ 
+-	        glEnd ();
++		streamingBuffer->end ();
++		streamingBuffer->render (sTransform);
++
+ 	        tex->disable ();
+ 	    }
+ 	}
+@@ -691,85 +720,130 @@ AnnoScreen::glPaintOutput (const GLScree
+ 	switch (drawMode)
+ 	{
+ 	case LineMode:
+-	    glColor4usv (optionGetStrokeColor ());
+ 	    glLineWidth (optionGetStrokeWidth ());
+-	    glBegin (GL_LINES);
+-	    glVertex2i (initialPointerX, initialPointerY);
+-	    glVertex2i (lineVector.x (), lineVector.y ());
+-	    glEnd ();
++
++	    streamingBuffer->begin (GL_LINES);
++
++	    streamingBuffer->addColors (1, optionGetStrokeColor ());
++
++	    vertexData[0] = initialPointerX;
++	    vertexData[1] = initialPointerY;
++	    vertexData[2] = 0.0f;
++	    vertexData[3] = lineVector.x ();
++	    vertexData[4] = lineVector.y ();
++	    vertexData[5] = 0.0f;
++	    streamingBuffer->addVertices (2, vertexData);
++
++	    streamingBuffer->end ();
++	    streamingBuffer->render (sTransform);
+ 	    break;
+ 
+ 	case RectangleMode:
++	    vertexData[0]  = rectangle.x1 ();
++	    vertexData[1]  = rectangle.y1 ();
++	    vertexData[2]  = 0.0f;
++	    vertexData[3]  = rectangle.x1 ();
++	    vertexData[4]  = rectangle.y2 ();
++	    vertexData[5]  = 0.0f;
++	    vertexData[6]  = rectangle.x2 ();
++	    vertexData[7]  = rectangle.y1 ();
++	    vertexData[8]  = 0.0f;
++	    vertexData[9]  = rectangle.x2 ();
++	    vertexData[10] = rectangle.y2 ();
++	    vertexData[11] = 0.0f;
++
+ 	    /* fill rectangle */
+-	    glColor4usv (optionGetFillColor ());
+-	    glRecti (rectangle.x1 (), rectangle.y2 (),
+-		     rectangle.x2 (), rectangle.y1 ());
++	    streamingBuffer->begin (GL_TRIANGLE_STRIP);
++
++	    streamingBuffer->addColors (1, optionGetFillColor ());
++	    streamingBuffer->addVertices (4, vertexData);
++
++	    streamingBuffer->end ();
++	    streamingBuffer->render (sTransform);
+ 
+ 	    /* draw rectangle outline */
+-	    glColor4usv (optionGetStrokeColor ());
+-	    glRecti (rectangle.x1 () - offset, rectangle.y2 (),
+-		     rectangle.x1 () + offset, rectangle.y1 ());
++/*	    streamingBuffer->begin ();
++
++	    streamingBuffer->addColors (1, optionGetStrokeColor ());
++
++	    vertexData[0] = rectangle.x1 () - offset;
++	    vertexData[3] = rectangle.x1 () - offset;
++	    streamingBuffer->addVertices (4, vertexData);
++
+ 	    glRecti (rectangle.x2 () - offset, rectangle.y2 (),
+ 		     rectangle.x2 () + offset, rectangle.y1 ());
+ 	    glRecti (rectangle.x1 () - offset, rectangle.y1 () + offset,
+ 		     rectangle.x2 () + offset, rectangle.y1 () - offset);
+ 	    glRecti (rectangle.x1 () - offset, rectangle.y2 () + offset,
+-		     rectangle.x2 () + offset, rectangle.y2 () - offset);
++		     rectangle.x2 () + offset, rectangle.y2 () - offset);*/
+ 	    break;
+ 
+ 	case EllipseMode:
+ 	    /* fill ellipse */
+-	    glColor4usv (optionGetFillColor ());
++	    streamingBuffer->begin (GL_TRIANGLE_FAN);
++
++	    streamingBuffer->addColors (1, optionGetFillColor ());
++
++	    vertexData[0] = ellipse.center.x ();
++	    vertexData[1] = ellipse.center.y ();
++	    vertexData[2] = 0.0f;
++	    streamingBuffer->addVertices (1, vertexData);
+ 
+-	    glBegin (GL_TRIANGLE_FAN);
+-	    glVertex2d (ellipse.center.x (), ellipse.center.y ());
+ 	    for (angle = 0; angle <= 360; angle += 1)
+ 	    {
+-		vectorX = ellipse.center.x () +
+-			 (ellipse.radiusX * sinf (angle * DEG2RAD));
+-		vectorY = ellipse.center.y () +
+-			 (ellipse.radiusY * cosf (angle * DEG2RAD));
+-		glVertex2d (vectorX, vectorY);
++		vertexData[0] = ellipse.center.x () +
++		                (ellipse.radiusX * sinf (angle * DEG2RAD));
++		vertexData[1] = ellipse.center.y () +
++		                (ellipse.radiusY * cosf (angle * DEG2RAD));
++		streamingBuffer->addVertices (1, vertexData);
+ 	    }
+-	    glVertex2d (ellipse.center.x (), ellipse.center.y () +
+-			ellipse.radiusY);
+-	    glEnd();
++
++	    vertexData[0] = ellipse.center.x ();
++	    vertexData[1] = ellipse.center.y () + ellipse.radiusY;
++	    streamingBuffer->addVertices (1, vertexData);
++
++	    streamingBuffer->end ();
++	    streamingBuffer->render (sTransform);
+ 
+ 	    /* draw ellipse outline */
+-	    glColor4usv (optionGetStrokeColor ());
+ 	    glLineWidth (optionGetStrokeWidth ());
+ 
+-	    glBegin (GL_TRIANGLE_STRIP);
+-	    glVertex2d (ellipse.center.x (), ellipse.center.y () +
+-			ellipse.radiusY - offset);
++	    streamingBuffer->begin (GL_TRIANGLE_STRIP);
++
++	    streamingBuffer->addColors (1, optionGetStrokeColor ());
++
++
++	    vertexData[0] = ellipse.center.x ();
++	    vertexData[1] = ellipse.center.y () + ellipse.radiusY - offset;
++	    vertexData[2] = 0.0f;
++	    streamingBuffer->addVertices (1, vertexData);
++
+ 	    for (angle = 360; angle >= 0; angle -= 1)
+ 	    {
+-		vectorX = ellipse.center.x () + ((ellipse.radiusX -
+-			  offset) * sinf (angle * DEG2RAD));
+-		vectorY = ellipse.center.y () + ((ellipse.radiusY -
+-			  offset) * cosf (angle * DEG2RAD));
+-		glVertex2d (vectorX, vectorY);
+-		vectorX = ellipse.center.x () + ((ellipse.radiusX +
+-			  offset) * sinf (angle * DEG2RAD));
+-		vectorY = ellipse.center.y () + ((ellipse.radiusY +
+-			  offset) * cosf (angle * DEG2RAD));
+-		glVertex2d (vectorX, vectorY);
++		vertexData[0] = ellipse.center.x () + ((ellipse.radiusX -
++		                offset) * sinf (angle * DEG2RAD));
++		vertexData[1] = ellipse.center.y () + ((ellipse.radiusY -
++				offset) * cosf (angle * DEG2RAD));
++		vertexData[2] = 0.0f;
++		vertexData[3] = ellipse.center.x () + ((ellipse.radiusX +
++		                offset) * sinf (angle * DEG2RAD));
++		vertexData[4] = ellipse.center.y () + ((ellipse.radiusY +
++		                offset) * cosf (angle * DEG2RAD));
++		vertexData[5] = 0.0f;
++		streamingBuffer->addVertices (2, vertexData);
+ 	    }
+-	    glVertex2d (ellipse.center.x (), ellipse.center.y () +
+-			ellipse.radiusY + offset);
+-	    glEnd();
++
++	    vertexData[0] = ellipse.center.x ();
++	    vertexData[1] = ellipse.center.y () + ellipse.radiusY + offset;
++	    streamingBuffer->addVertices (1, vertexData);
++
++	    streamingBuffer->end ();
++	    streamingBuffer->render (sTransform);
+ 	    break;
+ 
+ 	default:
+ 	    break;
+ 	}
+-
+-	/* clean up */
+-	glColor4usv (defaultColor);
+-	glDisable (GL_BLEND);
+-	glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+-
+-	glPopMatrix ();
+     }
+ 
+     return status;
+--- compiz-0.9.7.6.orig/plugins/copytex/src/copytex.cpp
++++ compiz-0.9.7.6/plugins/copytex/src/copytex.cpp
+@@ -112,6 +112,14 @@ CopyTexture::CopyTexture (CopyPixmap::Pt
+     GLenum            target;
+     GLTexture::Matrix matrix = _identity_matrix;
+ 
++#ifdef USE_GLES
++    target = GL_TEXTURE_2D;
++    matrix.xx = 1.0f / dim.width ();
++    matrix.yy = 1.0f / dim.height ();
++    matrix.x0 = -dim.x () * matrix.xx;
++    matrix.y0 = -dim.y () * matrix.yy;
++#else
++
+     if (GL::textureNonPowerOfTwo ||
+ 	(POWER_OF_TWO (dim.width ()) && POWER_OF_TWO (dim.height ())))
+     {
+@@ -129,6 +137,7 @@ CopyTexture::CopyTexture (CopyPixmap::Pt
+ 	matrix.x0 = -dim.x ();
+ 	matrix.y0 = -dim.y ();
+     }
++#endif
+ 
+     setData (target, matrix, false);
+     setGeometry (dim.x1 (), dim.y1 (), dim.x2 () - dim.x1 (), dim.y2 () - dim.y1 ());
+--- compiz-0.9.7.6.orig/src/main.cpp
++++ compiz-0.9.7.6/src/main.cpp
+@@ -122,11 +122,6 @@ CompManager::parseArguments (int argc, c
+ 	}
+     }
+ 
+-    if (plugins.empty ())
+-    {
+-    plugins.push_back ("ccp");
+-    }
+-
+     initialPlugins = plugins;
+ 
+     return true;
+--- compiz-0.9.7.6.orig/metadata/core.xml.in
++++ compiz-0.9.7.6/metadata/core.xml.in
+@@ -138,7 +138,7 @@
+ 			<option name="focus_prevention_match" type="match">
+ 			<_short>Focus Prevention Windows</_short>
+ 			<_long>Focus prevention windows</_long>
+-			<default>!(class=Polkit-gnome-authentication-agent-1)</default>
++			<default>any</default>
+ 			</option>
+ 		</group>
+ 		<group>
+@@ -173,7 +173,7 @@
+ 			<option name="minimize_window_key" type="key">
+ 			<_short>Minimize Window</_short>
+ 			<_long>Minimize active window</_long>
+-			<default>&lt;Control&gt;&lt;Alt&gt;KP_0</default>
++			<default>&lt;Alt&gt;F9</default>
+ 			</option>
+ 			<option name="minimize_window_button" type="button">
+ 			<_short>Minimize Window</_short>
+@@ -182,12 +182,12 @@
+ 			<option name="maximize_window_key" type="key">
+ 			<_short>Maximize Window</_short>
+ 			<_long>Maximize active window</_long>
+-			<default>&lt;Control&gt;&lt;Super&gt;Up</default>
++			<default>&lt;Alt&gt;F10</default>
+ 			</option>
+ 			<option name="unmaximize_window_key" type="key">
+ 			<_short>Unmaximize Window</_short>
+ 			<_long>Unmaximize active window</_long>
+-			<default>&lt;Control&gt;&lt;Super&gt;Down</default>
++			<default>&lt;Alt&gt;F5</default>
+ 			</option>
+ 			<option name="maximize_window_horizontally_key" type="key">
+ 			<_short>Maximize Window Horizontally</_short>
+@@ -210,7 +210,7 @@
+ 			<option name="show_desktop_key" type="key">
+ 			<_short>Show Desktop</_short>
+ 			<_long>Hide all windows and focus desktop</_long>
+-			<default>&lt;Control&gt;&lt;Super&gt;d</default>
++			<default>&lt;Control&gt;&lt;Alt&gt;d</default>
+ 			</option>
+ 			<option name="show_desktop_edge" type="edge">
+ 			<_short>Show Desktop</_short>
+@@ -220,7 +220,6 @@
+ 			<option name="toggle_window_maximized_key" type="key">
+ 			<_short>Toggle Window Maximized</_short>
+ 			<_long>Toggle active window maximized</_long>
+-            <default>&lt;Control&gt;&lt;Alt&gt;KP_5</default>
+ 			</option>
+ 			<option name="toggle_window_maximized_button" type="button">
+ 			<_short>Toggle Window Maximized</_short>
+@@ -245,14 +244,14 @@
+ 			<option name="hsize" type="int">
+ 			<_short>Horizontal Virtual Size</_short>
+ 			<_long>Screen size multiplier for horizontal virtual size</_long>
+-			<default>2</default>
++			<default>4</default>
+ 			<min>1</min>
+ 			<max>32</max>
+ 			</option>
+ 			<option name="vsize" type="int">
+ 			<_short>Vertical Virtual Size</_short>
+ 			<_long>Screen size multiplier for vertical virtual size</_long>
+-			<default>2</default>
++			<default>1</default>
+ 			<min>1</min>
+ 			<max>32</max>
+ 			</option>
+--- compiz-0.9.7.6.orig/cmake/CompizCommon.cmake
++++ compiz-0.9.7.6/cmake/CompizCommon.cmake
+@@ -18,6 +18,7 @@ cmake_policy (SET CMP0011 OLD)
+ 
+ set (CMAKE_SKIP_RPATH FALSE)
+ 
++option (BUILD_GLES "Build against GLESv2 instead of GL" OFF)
+ option (COMPIZ_BUILD_WITH_RPATH "Leave as ON unless building packages" ON)
+ option (COMPIZ_RUN_LDCONFIG "Leave OFF unless you need to run ldconfig after install")
+ option (COMPIZ_PACKAGING_ENABLED "Enable to manually set prefix, exec_prefix, libdir, includedir, datadir" OFF)
+@@ -75,6 +76,17 @@ elseif (IS_DIRECTORY ${CMAKE_SOURCE_DIR}
+     set(IS_BZR_REPO 0)
+ endif (IS_DIRECTORY ${CMAKE_SOURCE_DIR}/.bzr)
+ 
++set (USE_GLES ${BUILD_GLES})
++
++if (USE_GLES)
++    find_package(OpenGLES2)
++
++    if (NOT OPENGLES2_FOUND)
++	set (USE_GLES 0)
++	message (SEND_ERROR "OpenGLESv2 not found")
++    endif (NOT OPENGLES2_FOUND)
++endif (USE_GLES)
++
+ function (compiz_ensure_linkage)
+     find_program (LDCONFIG_EXECUTABLE ldconfig)
+     mark_as_advanced (FORCE LDCONFIG_EXECUTABLE)
+--- compiz-0.9.7.6.orig/cmake/CompizPlugin.cmake
++++ compiz-0.9.7.6/cmake/CompizPlugin.cmake
+@@ -257,6 +257,16 @@ macro (_build_compiz_plugin plugin)
+ 	    NO_DEFAULT_PATH
+ 	)
+ 
++	set (COMPIZ_CURRENT_PLUGIN ${plugin})
++	set (COMPIZ_CURRENT_XML_FILE ${_translated_xml})
++
++	# find extension files
++	file (GLOB _extension_files "${COMPIZ_CMAKE_MODULE_PATH}/plugin_extensions/*.cmake")
++
++	foreach (_file ${_extension_files})
++	    include (${_file})
++	endforeach ()
++
+ 	# generate pkgconfig file and install it and the plugin header file
+ 	if (_${plugin}_pkg AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/include/${plugin})
+ 	    if ("${PLUGIN_BUILDTYPE}" STREQUAL "local")
+@@ -269,11 +279,15 @@ macro (_build_compiz_plugin plugin)
+ 		    set (VERSION 0.0.1-git)
+ 		endif (NOT VERSION)
+ 
++		#add CFLAGSADD so pkg-config file has correct flags
++		set (COMPIZ_CFLAGS ${COMPIZ_CFLAGS} ${${_PLUGIN}_CFLAGSADD})
++
+ 		compiz_configure_file (
+ 		    ${_${plugin}_pkg}
+ 		    ${CMAKE_BINARY_DIR}/generated/compiz-${plugin}.pc
+ 		    COMPIZ_REQUIRES
+ 		    COMPIZ_CFLAGS
++		    PKGCONFIG_LIBS
+ 		)
+ 
+ 		install (
+@@ -287,16 +301,6 @@ macro (_build_compiz_plugin plugin)
+ 	    endif ()
+ 	endif ()
+ 
+-	set (COMPIZ_CURRENT_PLUGIN ${plugin})
+-	set (COMPIZ_CURRENT_XML_FILE ${_translated_xml})
+-
+-	# find extension files
+-	file (GLOB _extension_files "${COMPIZ_CMAKE_MODULE_PATH}/plugin_extensions/*.cmake")
+-
+-	foreach (_file ${_extension_files})
+-	    include (${_file})
+-	endforeach ()
+-
+ 	# find files for build
+ 	file (GLOB _h_files "${CMAKE_CURRENT_SOURCE_DIR}/src/*.h")
+ 	file (GLOB _h_ins_files "${CMAKE_CURRENT_SOURCE_DIR}/include/${plugin}/*.h")
+--- compiz-0.9.7.6.orig/cmake/base.cmake
++++ compiz-0.9.7.6/cmake/base.cmake
+@@ -24,6 +24,7 @@ function (_print_configure_results)
+     compiz_print_configure_header ("Compiz")
+     compiz_color_message ("\n${_escape}[4mOptional features:${_escape}[0m\n")
+ 
++    compiz_print_result_message ("GLESv2" USE_GLES)
+     compiz_print_result_message ("gtk window decorator" USE_GTK)
+     compiz_print_result_message ("metacity theme support" USE_METACITY)
+     compiz_print_result_message ("gconf schemas" USE_GCONF)
+@@ -46,7 +47,8 @@ function (_check_compiz_cmake_macro)
+     endif ()
+     add_custom_target (findcompiz_install
+ 	${CMAKE_COMMAND} -E make_directory ${COMPIZ_DESTDIR}${CMAKE_ROOT}/Modules &&
+-	${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/cmake/FindCompiz.cmake ${COMPIZ_DESTDIR}${CMAKE_ROOT}/Modules
++	${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/cmake/FindCompiz.cmake ${COMPIZ_DESTDIR}${CMAKE_ROOT}/Modules &&
++	${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/cmake/FindOpenGLES2.cmake ${COMPIZ_DESTDIR}${CMAKE_ROOT}/Modules
+     )
+ endfunction ()
+ 
+--- compiz-0.9.7.6.orig/cmake/CMakeLists.txt
++++ compiz-0.9.7.6/cmake/CMakeLists.txt
+@@ -15,6 +15,8 @@ list (APPEND _PluginExtensionFiles
+       plugin_extensions/CompizGenInstallData.cmake)
+ list (APPEND _PluginExtensionFiles
+       plugin_extensions/CompizGenInstallImages.cmake)
++list (APPEND _PluginExtensionFiles
++      plugin_extensions/CompizOpenGLFixups.cmake)
+ 
+ if (USE_GCONF)
+     list (APPEND _files CompizGconf.cmake)
+--- /dev/null
++++ compiz-0.9.7.6/cmake/FindOpenGLES2.cmake
+@@ -0,0 +1,51 @@
++# - Try to find OpenGLES
++# Once done this will define
++#  
++#  OPENGLES2_FOUND        - system has OpenGLES
++#  OPENGLES2_INCLUDE_DIR  - the GLES include directory
++#  OPENGLES2_LIBRARY	  - the GLES library
++#  OPENGLES2_LIBRARIES    - Link this to use OpenGLES
++#   
++
++FIND_PATH(OPENGLES2_INCLUDE_DIR GLES2/gl2.h
++  /usr/openwin/share/include
++  /opt/graphics/OpenGL/include /usr/X11R6/include
++  /usr/include
++)
++
++FIND_LIBRARY(OPENGLES2_LIBRARY
++  NAMES GLESv2
++  PATHS /opt/graphics/OpenGL/lib
++        /usr/openwin/lib
++        /usr/shlib /usr/X11R6/lib
++        /usr/lib
++)
++
++FIND_LIBRARY(OPENGLES2_EGL_LIBRARY
++    NAMES EGL
++    PATHS /usr/shlib /usr/X11R6/lib
++          /usr/lib
++)
++
++# On Unix OpenGL most certainly always requires X11.
++# Feel free to tighten up these conditions if you don't 
++# think this is always true.
++# It's not true on OSX.
++
++IF (OPENGLES2_LIBRARY)
++  IF(NOT X11_FOUND)
++    INCLUDE(FindX11)
++  ENDIF(NOT X11_FOUND)
++  IF (X11_FOUND)
++    IF (NOT APPLE)
++      SET (OPENGLES2_LIBRARIES ${X11_LIBRARIES})
++    ENDIF (NOT APPLE)
++  ENDIF (X11_FOUND)
++ENDIF(OPENGLES2_LIBRARY)
++
++SET( OPENGLES2_FOUND "NO" )
++IF(OPENGLES2_LIBRARY AND OPENGLES2_EGL_LIBRARY)
++    SET( OPENGLES2_LIBRARIES  ${OPENGLES2_LIBRARY} ${OPENGLES2_EGL_LIBRARY} ${OPENGLES2_LIBRARIES})
++    SET( OPENGLES2_FOUND "YES" )
++ENDIF(OPENGLES2_LIBRARY AND OPENGLES2_EGL_LIBRARY)
++
+--- /dev/null
++++ compiz-0.9.7.6/cmake/plugin_extensions/CompizOpenGLFixups.cmake
+@@ -0,0 +1,22 @@
++
++# modify pkg-config libs for opengl based on if we found GLES or not
++if (${COMPIZ_CURRENT_PLUGIN} STREQUAL "opengl")
++    if (USE_GLES)
++	set (PKGCONFIG_LIBS "-lGLESv2 -lEGL")
++    else (USE_GLES)
++	set (PKGCONFIG_LIBS "-lGL")
++    endif (USE_GLES)
++endif (${COMPIZ_CURRENT_PLUGIN} STREQUAL "opengl")
++
++# if plugin is using opengl plugin check for GLES library and set correct define
++if (NOT "${${_PLUGIN}_PLUGINDEPS}" STREQUAL "")
++    string (REGEX MATCH "opengl" opengl_found ${${_PLUGIN}_PLUGINDEPS})
++
++    if (opengl_found STREQUAL "opengl")
++	if (USE_GLES)
++	    set (${_PLUGIN}_CFLAGSADD ${${_PLUGIN}_CFLAGSADD} " -DUSE_GLES")
++	    string (REPLACE ";" " " ${_PLUGIN}_CFLAGSADD ${${_PLUGIN}_CFLAGSADD})
++	endif (USE_GLES)
++    endif (opengl_found STREQUAL "opengl")
++endif (NOT "${${_PLUGIN}_PLUGINDEPS}" STREQUAL "")
++

=== added symlink 'debian/patches/series.armel'
=== target is u'series.armhf'
=== added file 'debian/patches/series.armhf'
--- debian/patches/series.armhf	1970-01-01 00:00:00 +0000
+++ debian/patches/series.armhf	2012-04-10 14:55:03 +0000
@@ -0,0 +1,1 @@
+compiz-package-gles2.patch

=== modified file 'debian/rules'
--- debian/rules	2012-03-30 11:25:32 +0000
+++ debian/rules	2012-04-10 14:55:03 +0000
@@ -3,15 +3,40 @@
 
 # Uncomment this to turn on verbose mode.
 #export DH_VERBOSE=1
+DEB_HOST_ARCH := $(shell dpkg-architecture -qDEB_HOST_ARCH)
+gles2_architectures := armel armhf
 
 CORE_ABIVERSION := $(shell sed -rn 's/^\#define[[:space:]]+CORE_ABIVERSION[[:space:]]+//p' include/core/abiversion.h )
 
 DEFAULT_PLUGINS = "ccp"
 
+override_dh_quilt_patch:
+	dh_quilt_patch
+	if test -r debian/patches/series.$(DEB_HOST_ARCH); then \
+	  pc=".pc.$(DEB_HOST_ARCH)"; \
+	  test -d "$(CURDIR)/$$pc" || mkdir "$(CURDIR)/$$pc"; \
+	  cp debian/patches/series.$(DEB_HOST_ARCH) $(CURDIR)/$$pc/series; \
+	  cd $(CURDIR); \
+	  QUILT_PC="$$pc" quilt upgrade || true; \
+	  QUILT_PC="$$pc" QUILT_PATCHES="debian/patches/" quilt push -a || true; \
+	fi; \
+
+override_dh_quilt_unpatch:
+	if test -r debian/patches/series.$(DEB_HOST_ARCH); then \
+	  pc=".pc.$(DEB_HOST_ARCH)"; \
+	  cd $(CURDIR); \
+	  QUILT_PC="$$pc" QUILT_PATCHES="debian/patches/" quilt pop -a || true; \
+	fi; \
+	dh_quilt_unpatch
+
 override_dh_auto_configure:
 	# currently, segfault if CMAKE_BUILD_TYPE=Release
 	LDFLAGS=$(shell echo $$LDFLAGS | sed -e 's/\-Wl,-Bsymbolic-functions //')
+ifeq ($(DEB_HOST_ARCH),$(findstring $(DEB_HOST_ARCH), $(gles2_architectures)))
+	dh_auto_configure -- -DCOMPIZ_BUILD_WITH_RPATH=FALSE -DCOMPIZ_DEFAULT_PLUGINS=\"$(DEFAULT_PLUGINS)\" -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCOMPIZ_PACKAGING_ENABLED=TRUE -DUSE_GSETTINGS=OFF -DCOMPIZ_DISABLE_GS_SCHEMAS_INSTALL=ON -DCOMPIZ_DISABLE_PLUGIN_KDE=ON -DCOMPIZ_BUILD_TESTING=OFF -DUSE_KDE4=OFF -DBUILD_GLES=ON
+else
 	dh_auto_configure -- -DCOMPIZ_BUILD_WITH_RPATH=FALSE -DCOMPIZ_DEFAULT_PLUGINS=\"$(DEFAULT_PLUGINS)\" -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCOMPIZ_PACKAGING_ENABLED=TRUE -DUSE_GSETTINGS=OFF -DCOMPIZ_DISABLE_GS_SCHEMAS_INSTALL=ON -DCOMPIZ_DISABLE_PLUGIN_KDE=ON -DCOMPIZ_BUILD_TESTING=OFF -DUSE_KDE4=OFF
+endif
 
 override_dh_install:
 	# Language packs
@@ -40,8 +65,15 @@
 	# DESTDIR together is completely broken upstream
 	# So, doing the same in debian/rules to find a way to install things in the
 	# right place, sorry for the kittens
-	cmake_dir=`cmake --system-information 2> /dev/null | grep "^CMAKE_ROOT " | sed -e 's/.*"\(.*\)"/\1/'` && \
-	mkdir -p debian/tmp$${cmake_dir}/Modules && cp cmake/FindCompiz.cmake debian/tmp$${cmake_dir}/Modules
+ifeq ($(DEB_HOST_ARCH),$(findstring $(DEB_HOST_ARCH), $(gles2_architectures)))
+	cmake_dir=`cmake --system-information 2> /dev/null | grep "^CMAKE_ROOT " | sed -e 's/.*"\(.*\)"/\1/'` && \
+	mkdir -p debian/tmp$${cmake_dir}/Modules && \
+	cp cmake/FindCompiz.cmake debian/tmp$${cmake_dir}/Modules && cp cmake/FindOpenGLES2.cmake debian/tmp$${cmake_dir}/Modules
+else
+	cmake_dir=`cmake --system-information 2> /dev/null | grep "^CMAKE_ROOT " | sed -e 's/.*"\(.*\)"/\1/'` && \
+	mkdir -p debian/tmp$${cmake_dir}/Modules && \
+	cp cmake/FindCompiz.cmake debian/tmp$${cmake_dir}/Modules
+endif
 
 	# remove .a files
 	rm -f debian/tmp/usr/lib/*.a
@@ -55,5 +87,5 @@
 	# test broken right now :(
 
 %:
-	dh $@
+	dh --with quilt $@
 


Follow ups