compiz team mailing list archive
-
compiz team
-
Mailing list archive
-
Message #31958
[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 ®ion,
+- unsigned int mask)
++DecorWindow::glDraw (const GLMatrix &transform,
++ const GLWindowPaintAttrib &attrib,
++ const CompRegion ®ion,
++ 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 ®ion,
+- unsigned int mask)
++DecorWindow::glDecorate (const GLMatrix &transform,
++ const GLWindowPaintAttrib &attrib,
++ const CompRegion ®ion,
++ 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 & !(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><Control><Alt>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><Super>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 ¶ms)
++ {
++ 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 ®ion,
++ 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 ¶ms)
++{
++ 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 ¶ms)
++ {
++ 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 ®ion,
+- unsigned int mask)
+- WRAPABLE_DEF (glDraw, transform, fragment, region, mask)
++GLWindowInterface::glDraw (const GLMatrix &transform,
++ const GLWindowPaintAttrib &attrib,
++ const CompRegion ®ion,
++ 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 ®ion)
+ {
+ 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 ®ion,
+- bool transformed);
++ void paintBackground (const GLMatrix &transform,
++ const CompRegion ®ion,
++ bool transformed);
+
+ void paintOutputRegion (const GLMatrix &transform,
+ const CompRegion ®ion,
+@@ -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 ®ion,
+- bool transformed)
++PrivateGLScreen::paintBackground (const GLMatrix &transform,
++ const CompRegion ®ion,
++ 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 ®ion,
++ 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 ®ion,
+- unsigned int mask)
++GLWindow::glDraw (const GLMatrix &transform,
++ const GLWindowPaintAttrib &attrib,
++ const CompRegion ®ion,
++ unsigned int mask)
+ {
+ WRAPABLE_HND_FUNCTN_RETURN (bool, glDraw, transform,
+- fragment, region, mask)
++ attrib, region, mask)
+
+ const CompRegion ® = (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 ¶ms);
++
++ std::string createVertexShader (const GLShaderParameters ¶ms);
++ std::string createFragmentShader (const GLShaderParameters ¶ms);
++
++ 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 ¶ms)
++{
++ 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 ¶ms)
++{
++ 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 ¶ms)
++{
++ 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 ¶ms)
++{
++ 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 ¶ms) = 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 ¶ms);
++
++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 ®ion,
++ 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 ¶ms);
+
+ /**
+- * 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 ®ion,
+- unsigned int mask);
++ virtual bool glDraw (const GLMatrix &matrix,
++ const GLWindowPaintAttrib &attrib,
++ const CompRegion ®ion,
++ 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 ®ion,
+ 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 ®ion,
++ 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 ®ion, 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 ®ion,
+- unsigned int mask)
++SvgWindow::glDraw (const GLMatrix &transform,
++ const GLWindowPaintAttrib &attrib,
++ const CompRegion ®ion,
++ 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 ®ion,
++ 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 ®ion,
++ 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><Control><Alt>KP_0</default>
++ <default><Alt>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><Control><Super>Up</default>
++ <default><Alt>F10</default>
+ </option>
+ <option name="unmaximize_window_key" type="key">
+ <_short>Unmaximize Window</_short>
+ <_long>Unmaximize active window</_long>
+- <default><Control><Super>Down</default>
++ <default><Alt>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><Control><Super>d</default>
++ <default><Control><Alt>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><Control><Alt>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