Add support for render-ahead

For periods of time during which latency is less important
allow a client to request a deeper render-ahead pipeline.

The latency tradeoff results in less overall visual jank

Test: none, only used by macrobench

Change-Id: I516203b70bdc75b6415fa08bf9c4fb1b598b0102
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index f4d8051..609d26c 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -17,6 +17,7 @@
 #include "CanvasContext.h"
 #include <GpuMemoryTracker.h>
 
+#include "../Properties.h"
 #include "AnimationContext.h"
 #include "Caches.h"
 #include "EglManager.h"
@@ -34,7 +35,6 @@
 #include "renderstate/Stencil.h"
 #include "utils/GLUtils.h"
 #include "utils/TimeUtils.h"
-#include "../Properties.h"
 
 #include <cutils/properties.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
@@ -194,6 +194,7 @@
     if (hasSurface) {
         mHaveNewSurface = true;
         mSwapHistory.clear();
+        updateBufferCount();
     } else {
         mRenderThread.removeFrameCallback(this);
     }
@@ -427,6 +428,9 @@
 
     waitOnFences();
 
+    frame.setPresentTime(mCurrentFrameInfo->get(FrameInfoIndex::Vsync) +
+                         (mRenderThread.timeLord().frameIntervalNanos() * (mRenderAheadDepth + 1)));
+
     bool requireSwap = false;
     bool didSwap =
             mRenderPipeline->swapBuffers(frame, drew, windowDirty, mCurrentFrameInfo, &requireSwap);
@@ -705,6 +709,26 @@
     return mFrameNumber;
 }
 
+void overrideBufferCount(const sp<Surface>& surface, int bufferCount) {
+    struct SurfaceExposer : Surface {
+        using Surface::setBufferCount;
+    };
+    // Protected is just a sign, not a cop
+    ((*surface.get()).*&SurfaceExposer::setBufferCount)(bufferCount);
+}
+
+void CanvasContext::updateBufferCount() {
+    overrideBufferCount(mNativeSurface, 3 + mRenderAheadDepth);
+}
+
+void CanvasContext::setRenderAheadDepth(int renderAhead) {
+    if (renderAhead < 0 || renderAhead > 2 || renderAhead == mRenderAheadDepth) {
+        return;
+    }
+    mRenderAheadDepth = renderAhead;
+    updateBufferCount();
+}
+
 SkRect CanvasContext::computeDirtyRect(const Frame& frame, SkRect* dirty) {
     if (frame.width() != mLastFrameWidth || frame.height() != mLastFrameHeight) {
         // can't rely on prior content of window if viewport size changes