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
