EGL or GLES 2 do not have a standard way to do partial back-to-front
copies. Unfortunately compiz relies on blitting sub-rects from back
buffer to front buffer for updating only the damaged regions. Compiz'
rendering does not honour damage regions, but renders all over,
sometimes leading to visual artifacts if one simply calls
eglSwapBuffers().

The fix: All output rendering is diverted into a framebuffer object
(FBO), if the FBO is successfully created. Then, only the damage regions
are blitted to the back buffer, followed by eglSwapBuffers().

For full screen damage, the FBO step is skipped.

This patch fixes rendering artifacts in the scale plugin, on GLES 2.

Signed-off-by: Pekka Paalanen <[email protected]>
---
 plugins/opengl/src/privates.h |    5 ++
 plugins/opengl/src/screen.cpp |  110 +++++++++++++++++++++++++++++++++++++---
 2 files changed, 106 insertions(+), 9 deletions(-)

diff --git a/plugins/opengl/src/privates.h b/plugins/opengl/src/privates.h
index dc2c000..4ea1dac 100644
--- a/plugins/opengl/src/privates.h
+++ b/plugins/opengl/src/privates.h
@@ -32,6 +32,10 @@
 #include <opengl/opengl.h>
 #include <core/atoms.h>
 
+#ifdef USE_GLES
+#include <opengl/framebufferobject.h>
+#endif
+
 #include "privatetexture.h"
 #include "privatevertexbuffer.h"
 #include "opengl_options.h"
@@ -112,6 +116,7 @@ class PrivateGLScreen :
        #ifdef USE_GLES
        EGLContext ctx;
        EGLSurface surface;
+       GLFramebufferObject *scratchFbo;
        #else
        GLXContext ctx;
 
diff --git a/plugins/opengl/src/screen.cpp b/plugins/opengl/src/screen.cpp
index c6d61c2..5680f23 100644
--- a/plugins/opengl/src/screen.cpp
+++ b/plugins/opengl/src/screen.cpp
@@ -328,6 +328,9 @@ GLScreen::GLScreen (CompScreen *s) :
     if (GL::textureFromPixmap)
        registerBindPixmap (EglTexture::bindPixmapToTexture);
 
+    priv->scratchFbo = new GLFramebufferObject;
+    priv->scratchFbo->allocate (*screen);
+
     #else
 
     Display             *dpy = s->dpy ();
@@ -825,6 +828,8 @@ GLScreen::~GLScreen ()
     Display *xdpy = screen->dpy ();
     EGLDisplay dpy = eglGetDisplay (xdpy);
 
+    delete priv->scratchFbo;
+
     eglMakeCurrent (dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
     eglDestroyContext (dpy, priv->ctx);
     eglDestroySurface (dpy, priv->surface);
@@ -847,7 +852,9 @@ PrivateGLScreen::PrivateGLScreen (GLScreen   *gs) :
     projection (NULL),
     clearBuffers (true),
     lighting (false),
-    #ifndef USE_GLES
+    #ifdef USE_GLES
+    scratchFbo (NULL),
+    #else
     getProcAddress (0),
     #endif
     outputRegion (),
@@ -1033,6 +1040,9 @@ PrivateGLScreen::outputChangeNotify ()
 {
     screen->outputChangeNotify ();
 
+#ifdef USE_GLES
+    scratchFbo->allocate (*screen);
+#endif
     updateView ();
 }
 
@@ -1357,6 +1367,20 @@ PrivateGLScreen::paintOutputs (CompOutput::ptrList 
&outputs,
 {
     XRectangle r;
 
+#ifdef USE_GLES
+    GLFramebufferObject *oldFbo = NULL;
+    bool useFbo = false;
+
+    // FIXME: does not work if screen dimensions exceed max texture size
+    if (!(mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK))
+    {
+       oldFbo = scratchFbo->bind ();
+       useFbo = scratchFbo->checkStatus () && scratchFbo->tex ();
+       if (!useFbo)
+           GLFramebufferObject::rebind (oldFbo);
+    }
+#endif
+
     if (clearBuffers)
     {
        if (mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK)
@@ -1424,16 +1448,84 @@ PrivateGLScreen::paintOutputs (CompOutput::ptrList 
&outputs,
     #ifdef USE_GLES
     Display *xdpy = screen->dpy ();
 
-    glFlush ();
-    if (mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK)
+    if (useFbo)
     {
-       eglSwapBuffers (eglGetDisplay (xdpy), surface);
-    }
-    else
-    {
-       #warning use proper extension for this
-       eglSwapBuffers (eglGetDisplay (xdpy), surface);
+       GLMatrix sTransform;
+       GLfloat vertexData[18];
+       GLfloat textureData[12];
+       const GLTexture::Matrix & texmatrix = scratchFbo->tex ()->matrix ();
+       GLVertexBuffer *streamingBuffer = GLVertexBuffer::streamingBuffer ();
+
+       BoxPtr pBox = const_cast <Region> (tmpRegion.handle ())->rects;
+       int nBox    = const_cast <Region> (tmpRegion.handle ())->numRects;
+
+       streamingBuffer->begin (GL_TRIANGLES);
+
+       while (nBox--)
+       {
+           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[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;
+
+           textureData[8]  = tx2;
+           textureData[9]  = ty2;
+
+           textureData[10] = tx2;
+           textureData[11] = ty1;
+
+           streamingBuffer->addVertices (6, vertexData);
+           streamingBuffer->addTexCoords (0, 6, textureData);
+
+           pBox++;
+       }
+
+       streamingBuffer->end ();
+
+       GLFramebufferObject::rebind (oldFbo);
+
+       scratchFbo->tex ()-> enable (GLTexture::Fast);
+       sTransform.toScreenSpace (&screen->fullscreenOutput (), 
-DEFAULT_Z_CAMERA);
+       streamingBuffer->render (sTransform);
+       scratchFbo->tex ()-> disable ();
     }
+    eglSwapBuffers (eglGetDisplay (xdpy), surface);
     eglWaitGL ();
     XFlush (xdpy);
 
-- 
1.7.3.4

_______________________________________________
dev mailing list
[email protected]
http://lists.compiz.org/mailman/listinfo/dev

Reply via email to