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/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);