Add a LayerScreenshot

A LayerScreenshot is a special type of layer that contains a screenshot of
the screen acquired when its created. It works just like LayerDim.

Make sure to call compositionComplete() after rendering into a FBO.

Bug: 5446982, 5467587, 5466259
Change-Id: I5d8a1b4c327f9973d950cd4f4c0bca7f62825cd4
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 595ec1e..ad1995d 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -50,6 +50,7 @@
 #include "DdmConnection.h"
 #include "Layer.h"
 #include "LayerDim.h"
+#include "LayerScreenshot.h"
 #include "SurfaceFlinger.h"
 
 #include "DisplayHardware/DisplayHardware.h"
@@ -1358,6 +1359,9 @@
         case eFXSurfaceDim:
             layer = createDimSurface(client, d, w, h, flags);
             break;
+        case eFXSurfaceScreenshot:
+            layer = createScreenshotSurface(client, d, w, h, flags);
+            break;
     }
 
     if (layer != 0) {
@@ -1420,7 +1424,19 @@
         uint32_t w, uint32_t h, uint32_t flags)
 {
     sp<LayerDim> layer = new LayerDim(this, display, client);
-    layer->initStates(w, h, flags);
+    return layer;
+}
+
+sp<LayerScreenshot> SurfaceFlinger::createScreenshotSurface(
+        const sp<Client>& client, DisplayID display,
+        uint32_t w, uint32_t h, uint32_t flags)
+{
+    sp<LayerScreenshot> layer = new LayerScreenshot(this, display, client);
+    status_t err = layer->capture();
+    if (err != NO_ERROR) {
+        layer.clear();
+        LOGW("createScreenshotSurface failed (%s)", strerror(-err));
+    }
     return layer;
 }
 
@@ -1783,6 +1799,13 @@
 
 // ---------------------------------------------------------------------------
 
+status_t SurfaceFlinger::renderScreenToTexture(DisplayID dpy,
+        GLuint* textureName, GLfloat* uOut, GLfloat* vOut)
+{
+    Mutex::Autolock _l(mStateLock);
+    return renderScreenToTextureLocked(dpy, textureName, uOut, vOut);
+}
+
 status_t SurfaceFlinger::renderScreenToTextureLocked(DisplayID dpy,
         GLuint* textureName, GLfloat* uOut, GLfloat* vOut)
 {
@@ -1833,6 +1856,8 @@
         layer->drawForSreenShot();
     }
 
+    hw.compositionComplete();
+
     // back to main framebuffer
     glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
     glDisable(GL_SCISSOR_TEST);
@@ -1848,11 +1873,6 @@
 
 status_t SurfaceFlinger::electronBeamOffAnimationImplLocked()
 {
-    status_t result = PERMISSION_DENIED;
-
-    if (!GLExtensions::getInstance().haveFramebufferObject())
-        return INVALID_OPERATION;
-
     // get screen geometry
     const DisplayHardware& hw(graphicPlane(0).displayHardware());
     const uint32_t hw_w = hw.getWidth();
@@ -1861,7 +1881,7 @@
 
     GLfloat u, v;
     GLuint tname;
-    result = renderScreenToTextureLocked(0, &tname, &u, &v);
+    status_t result = renderScreenToTextureLocked(0, &tname, &u, &v);
     if (result != NO_ERROR) {
         return result;
     }
@@ -2038,10 +2058,6 @@
         return result;
     }
 
-    // back to main framebuffer
-    glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
-    glDisable(GL_SCISSOR_TEST);
-
     GLfloat vtx[8];
     const GLfloat texCoords[4][2] = { {0,v}, {0,0}, {u,0}, {u,v} };
     glBindTexture(GL_TEXTURE_2D, tname);