add support for up to 16 buffers per surface

also increase the dirtyregion size from 1 to 6 rectangles.
Overall we now need 27KiB process instead of 4KiB

Change-Id: Iebda5565015158f49d9ca8dbcf55e6ad04855be3
diff --git a/include/private/surfaceflinger/SharedBufferStack.h b/include/private/surfaceflinger/SharedBufferStack.h
index 9b5a1e0..3b9768b 100644
--- a/include/private/surfaceflinger/SharedBufferStack.h
+++ b/include/private/surfaceflinger/SharedBufferStack.h
@@ -58,7 +58,7 @@
 // When changing these values, the COMPILE_TIME_ASSERT at the end of this
 // file need to be updated.
 const unsigned int NUM_LAYERS_MAX  = 31;
-const unsigned int NUM_BUFFER_MAX  = 4;
+const unsigned int NUM_BUFFER_MAX  = 16;
 const unsigned int NUM_DISPLAY_MAX = 4;
 
 // ----------------------------------------------------------------------------
@@ -69,7 +69,11 @@
 
 // ----------------------------------------------------------------------------
 
-// should be 128 bytes (32 longs)
+// 4 * (11 + 7 + (1 + 2*NUM_RECT_MAX) * NUM_BUFFER_MAX) * NUM_LAYERS_MAX
+// 4 * (11 + 7 + (1 + 2*6)*16) * 31
+// 904 * 31
+// = ~27 KiB (28024)
+
 class SharedBufferStack
 {
     friend class SharedClient;
@@ -78,8 +82,8 @@
     friend class SharedBufferServer;
 
 public:
-    struct FlatRegion { // 12 bytes
-        static const unsigned int NUM_RECT_MAX = 1;
+    struct FlatRegion { // 52 bytes = 4 * (1 + 2*N)
+        static const unsigned int NUM_RECT_MAX = 6;
         uint32_t    count;
         uint16_t    rects[4*NUM_RECT_MAX];
     };
@@ -106,9 +110,10 @@
     volatile int32_t reallocMask;
 
     int32_t     identity;       // surface's identity (const)
-    int32_t     reserved32[9];
+    int32_t     reserved32[6];
     Statistics  stats;
-    FlatRegion  dirtyRegion[NUM_BUFFER_MAX];    // 12*4=48 bytes
+    int32_t     reserved;
+    FlatRegion  dirtyRegion[NUM_BUFFER_MAX]; // 832 bytes
 };
 
 // ----------------------------------------------------------------------------
@@ -349,8 +354,7 @@
 
 // ---------------------------------------------------------------------------
 
-COMPILE_TIME_ASSERT(sizeof(SharedClient) <= 4096)
-COMPILE_TIME_ASSERT(sizeof(SharedBufferStack) == 128)
+COMPILE_TIME_ASSERT(sizeof(SharedClient) <= 32768)
 COMPILE_TIME_ASSERT(sizeof(surface_flinger_cblk_t) <= 4096)
 
 // ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger_client/SharedBufferStack.cpp b/libs/surfaceflinger_client/SharedBufferStack.cpp
index a17e8ac..5c4f920 100644
--- a/libs/surfaceflinger_client/SharedBufferStack.cpp
+++ b/libs/surfaceflinger_client/SharedBufferStack.cpp
@@ -73,13 +73,25 @@
         return BAD_INDEX;
 
     // in the current implementation we only send a single rectangle
-    const Rect bounds(dirty.getBounds());
+    size_t count;
+    Rect const* r = dirty.getArray(&count);
     FlatRegion& reg(dirtyRegion[buffer]);
-    reg.count = 1;
-    reg.rects[0] = uint16_t(bounds.left);
-    reg.rects[1] = uint16_t(bounds.top);
-    reg.rects[2] = uint16_t(bounds.right);
-    reg.rects[3] = uint16_t(bounds.bottom);
+    if (count > FlatRegion::NUM_RECT_MAX) {
+        const Rect bounds(dirty.getBounds());
+        reg.count = 1;
+        reg.rects[0] = uint16_t(bounds.left);
+        reg.rects[1] = uint16_t(bounds.top);
+        reg.rects[2] = uint16_t(bounds.right);
+        reg.rects[3] = uint16_t(bounds.bottom);
+    } else {
+        reg.count = count;
+        for (size_t i=0 ; i<count ; i++) {
+            reg.rects[i*4 + 0] = uint16_t(r[i].left);
+            reg.rects[i*4 + 1] = uint16_t(r[i].top);
+            reg.rects[i*4 + 2] = uint16_t(r[i].right);
+            reg.rects[i*4 + 3] = uint16_t(r[i].bottom);
+        }
+    }
     return NO_ERROR;
 }
 
@@ -90,7 +102,21 @@
         return res;
 
     const FlatRegion& reg(dirtyRegion[buffer]);
-    res.set(Rect(reg.rects[0], reg.rects[1], reg.rects[2], reg.rects[3]));
+    if (reg.count > FlatRegion::NUM_RECT_MAX)
+        return res;
+
+    if (reg.count == 1) {
+        res.set(Rect(reg.rects[0], reg.rects[1], reg.rects[2], reg.rects[3]));
+    } else {
+        for (size_t i=0 ; i<reg.count ; i++) {
+            const Rect r(
+                    reg.rects[i*4 + 0],
+                    reg.rects[i*4 + 1],
+                    reg.rects[i*4 + 2],
+                    reg.rects[i*4 + 3]);
+            res.orSelf(r);
+        }
+    }
     return res;
 }
 
@@ -280,7 +306,7 @@
 {
     SharedBufferStack& stack( *mSharedStack );
 
-    if (stack.head == tail && stack.available == 2) {
+    if (stack.head == tail && stack.available == mNumBuffers) {
         LOGW("dequeue: tail=%d, head=%d, avail=%d, queued=%d",
                 tail, stack.head, stack.available, stack.queued);
     }