created an new EGL extension called ANDROID_swap_rectangle

ANDROID_swap_rectangle allows to specify the rectangle affected by eglSwapBuffers(), anything outside of this rectangle is unchanged. in particular EGL_BUFFER_DESTROYED only applies to that rectangle. This extension as well as EGL_BUFFER_PRESERVED allow major optimizations on surfaceflinger, which can redraw only the dirty area during compositing.

However, ANDROID_swap_rectangle allows further optimizations in EGL by reducing the amount of copy-back needed. ANDROID_swap_rectangle is particularily important for software implementations.
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index 374f2e2..fc29d73 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -195,17 +195,19 @@
      * Create our main surface
      */
 
-    
     surface = eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL);
     checkEGLErrors("eglCreateDisplaySurfaceANDROID");
 
-    
     if (eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &dummy) == EGL_TRUE) {
         if (dummy == EGL_BUFFER_PRESERVED) {
             mFlags |= BUFFER_PRESERVED;
         }
     }
-    
+
+    if (strstr(egl_extensions, "ANDROID_swap_rectangle")) {
+        mFlags |= SWAP_RECTANGLE;
+    }
+
     mDpiX = mNativeWindow->xdpi;
     mDpiX = mNativeWindow->ydpi;
     mRefreshRate = mNativeWindow->getDevice()->fps; 
@@ -304,11 +306,12 @@
     EGLDisplay dpy = mDisplay;
     EGLSurface surface = mSurface;
 
-    if (mFlags & BUFFER_PRESERVED) {
+    if (mFlags & SWAP_RECTANGLE) {
         Region newDirty(dirty);
         newDirty.andSelf(Rect(mWidth, mHeight));
         const Rect& b(newDirty.bounds());
-        //mNativeWindow->setSwapRectangle(b);
+        eglSetSwapRectangleANDROID(dpy, surface,
+                b.left, b.top, b.width(), b.height());
     } 
 
     mPageFlipCount++;
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
index c9c75e2..c3dbff1 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
@@ -50,6 +50,7 @@
         BUFFER_PRESERVED        = 0x00010000,
         UPDATE_ON_DEMAND        = 0x00020000,   // video driver feature
         SLOW_CONFIG             = 0x00040000,   // software
+        SWAP_RECTANGLE          = 0x00080000,
     };
 
     DisplayHardware(
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index 5fd979e..b8c246c 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -803,12 +803,14 @@
     mInvalidRegion.orSelf(mDirtyRegion);
 
     uint32_t flags = hw.getFlags();
-    if (flags & DisplayHardware::BUFFER_PRESERVED) {
-        // here we assume DisplayHardware::flip()'s  implementation
-        // performs the copy-back optimization.
+    if ((flags & DisplayHardware::SWAP_RECTANGLE) || 
+        (flags & DisplayHardware::BUFFER_PRESERVED)) 
+    {
+        // we can redraw only what's dirty
     } else {
         if (flags & DisplayHardware::UPDATE_ON_DEMAND) {
-            // we need to fully redraw the part that will be updated
+            // we need to redraw the rectangle that will be updated
+            // (pushed to the framebuffer).
             mDirtyRegion.set(mInvalidRegion.bounds());
         } else {
             // we need to redraw everything
@@ -890,7 +892,9 @@
 {
      const DisplayHardware& hw(graphicPlane(0).displayHardware());
      const uint32_t flags = hw.getFlags();
-     if (!(flags & DisplayHardware::BUFFER_PRESERVED)) {
+
+     if (!((flags & DisplayHardware::SWAP_RECTANGLE) ||
+             (flags & DisplayHardware::BUFFER_PRESERVED))) {
          const Region repaint((flags & DisplayHardware::UPDATE_ON_DEMAND) ?
                  mDirtyRegion.bounds() : hw.bounds());
          composeSurfaces(repaint);