am 9a12a3c8: am ba799098: Merge changes I76513387,I335fb671 into gingerbread

Merge commit '9a12a3c8d4bb20042cf69e07d268e3a04ac71f96'

* commit '9a12a3c8d4bb20042cf69e07d268e3a04ac71f96':
  Remove dead code, and make the animation a setting.
  turn off the electron beam
diff --git a/include/surfaceflinger/ISurfaceComposer.h b/include/surfaceflinger/ISurfaceComposer.h
index b181781..ac69a06 100644
--- a/include/surfaceflinger/ISurfaceComposer.h
+++ b/include/surfaceflinger/ISurfaceComposer.h
@@ -119,6 +119,8 @@
             uint32_t* width, uint32_t* height, PixelFormat* format,
             uint32_t reqWidth, uint32_t reqHeight) = 0;
 
+    virtual status_t turnElectronBeamOff(int32_t mode) = 0;
+
     /* Signal surfaceflinger that there might be some work to do
      * This is an ASYNCHRONOUS call.
      */
@@ -143,7 +145,8 @@
         FREEZE_DISPLAY,
         UNFREEZE_DISPLAY,
         SIGNAL,
-        CAPTURE_SCREEN
+        CAPTURE_SCREEN,
+        TURN_ELECTRON_BEAM_OFF
     };
 
     virtual status_t    onTransact( uint32_t code,
diff --git a/libs/surfaceflinger_client/ISurfaceComposer.cpp b/libs/surfaceflinger_client/ISurfaceComposer.cpp
index d676f5e..d72561f 100644
--- a/libs/surfaceflinger_client/ISurfaceComposer.cpp
+++ b/libs/surfaceflinger_client/ISurfaceComposer.cpp
@@ -142,6 +142,15 @@
         return reply.readInt32();
     }
 
+    virtual status_t turnElectronBeamOff(int32_t mode)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        data.writeInt32(mode);
+        remote()->transact(BnSurfaceComposer::TURN_ELECTRON_BEAM_OFF, data, &reply);
+        return reply.readInt32();
+    }
+
     virtual void signal() const
     {
         Parcel data, reply;
@@ -224,6 +233,12 @@
             reply->writeInt32(f);
             reply->writeInt32(res);
         } break;
+        case TURN_ELECTRON_BEAM_OFF: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
+            int32_t mode = data.readInt32();
+            status_t res = turnElectronBeamOff(mode);
+            reply->writeInt32(res);
+        }
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
index 1d09f84..fe9a5ab 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
@@ -359,7 +359,7 @@
 
 DisplayHardwareBase::DisplayHardwareBase(const sp<SurfaceFlinger>& flinger,
         uint32_t displayIndex) 
-    : mCanDraw(true)
+    : mCanDraw(true), mScreenAcquired(true)
 {
     mDisplayEventThread = new DisplayEventThread(flinger);
     if (mDisplayEventThread->initCheck() != NO_ERROR) {
@@ -374,18 +374,21 @@
     mDisplayEventThread->requestExitAndWait();
 }
 
+void DisplayHardwareBase::setCanDraw(bool canDraw)
+{
+    mCanDraw = canDraw;
+}
 
 bool DisplayHardwareBase::canDraw() const
 {
-    return mCanDraw;
+    return mCanDraw && mScreenAcquired;
 }
 
 void DisplayHardwareBase::releaseScreen() const
 {
     status_t err = mDisplayEventThread->releaseScreen();
     if (err >= 0) {
-        //LOGD("screen given-up");
-        mCanDraw = false;
+        mScreenAcquired = false;
     }
 }
 
@@ -393,9 +396,14 @@
 {
     status_t err = mDisplayEventThread->acquireScreen();
     if (err >= 0) {
-        //LOGD("screen returned");
         mCanDraw = true;
+        mScreenAcquired = true;
     }
 }
 
+bool DisplayHardwareBase::isScreenAcquired() const
+{
+    return mScreenAcquired;
+}
+
 }; // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h
index 8369bb8..fa6a0c4 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h
@@ -40,7 +40,11 @@
     // console managment
     void releaseScreen() const;
     void acquireScreen() const;
+    bool isScreenAcquired() const;
+
     bool canDraw() const;
+    void setCanDraw(bool canDraw);
+
 
 private:
     class DisplayEventThreadBase : public Thread {
@@ -89,6 +93,7 @@
 
     sp<DisplayEventThreadBase>  mDisplayEventThread;
     mutable int                 mCanDraw;
+    mutable int                 mScreenAcquired;
 };
 
 }; // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e6bdfd1..97365aa 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -430,14 +430,14 @@
         hw.acquireScreen();
     }
 
-    if (mDeferReleaseConsole && hw.canDraw()) {
+    if (mDeferReleaseConsole && hw.isScreenAcquired()) {
         // We got the release signal before the acquire signal
         mDeferReleaseConsole = false;
         hw.releaseScreen();
     }
 
     if (what & eConsoleReleased) {
-        if (hw.canDraw()) {
+        if (hw.isScreenAcquired()) {
             hw.releaseScreen();
         } else {
             mDeferReleaseConsole = true;
@@ -1558,6 +1558,7 @@
         case FREEZE_DISPLAY:
         case UNFREEZE_DISPLAY:
         case BOOT_FINISHED:
+        case TURN_ELECTRON_BEAM_OFF:
         {
             // codes that require permission check
             IPCThreadState* ipc = IPCThreadState::self();
@@ -1651,6 +1652,231 @@
     return err;
 }
 
+
+// ---------------------------------------------------------------------------
+
+status_t SurfaceFlinger::turnElectronBeamOffImplLocked()
+{
+    status_t result = PERMISSION_DENIED;
+
+    if (!GLExtensions::getInstance().haveFramebufferObject())
+        return INVALID_OPERATION;
+
+    // get screen geometry
+    const int dpy = 0;
+    const DisplayHardware& hw(graphicPlane(dpy).displayHardware());
+    if (!hw.canDraw()) {
+        // we're already off
+        return NO_ERROR;
+    }
+
+    const uint32_t hw_w = hw.getWidth();
+    const uint32_t hw_h = hw.getHeight();
+    const Region screenBounds(hw.bounds());
+    GLfloat u = 1;
+    GLfloat v = 1;
+
+    // make sure to clear all GL error flags
+    while ( glGetError() != GL_NO_ERROR ) ;
+
+    // create a FBO
+    GLuint name, tname;
+    glGenTextures(1, &tname);
+    glBindTexture(GL_TEXTURE_2D, tname);
+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, hw_w, hw_h, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
+    if (glGetError() != GL_NO_ERROR) {
+        GLint tw = (2 << (31 - clz(hw_w)));
+        GLint th = (2 << (31 - clz(hw_h)));
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tw, th, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
+        u = GLfloat(hw_w) / tw;
+        v = GLfloat(hw_h) / th;
+    }
+    glGenFramebuffersOES(1, &name);
+    glBindFramebufferOES(GL_FRAMEBUFFER_OES, name);
+    glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tname, 0);
+
+    GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
+    if (status == GL_FRAMEBUFFER_COMPLETE_OES) {
+        // redraw the screen entirely...
+        glClearColor(0,0,0,1);
+        glClear(GL_COLOR_BUFFER_BIT);
+        const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
+        const size_t count = layers.size();
+        for (size_t i=0 ; i<count ; ++i) {
+            const sp<LayerBase>& layer(layers[i]);
+            layer->drawForSreenShot();
+        }
+        // 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} };
+        glEnable(GL_TEXTURE_2D);
+        glBindTexture(GL_TEXTURE_2D, tname);
+        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+        glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
+        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+        glVertexPointer(2, GL_FLOAT, 0, vtx);
+
+        class s_curve_interpolator {
+            const float nbFrames, s, v;
+        public:
+            s_curve_interpolator(int nbFrames, float s)
+                : nbFrames(1.0f / (nbFrames-1)), s(s),
+                  v(1.0f + expf(-s + 0.5f*s)) {
+            }
+            float operator()(int f) {
+                const float x = f * nbFrames;
+                return ((1.0f/(1.0f + expf(-x*s + 0.5f*s))) - 0.5f) * v + 0.5f;
+            }
+        };
+
+        class v_stretch {
+            const GLfloat hw_w, hw_h;
+        public:
+            v_stretch(uint32_t hw_w, uint32_t hw_h)
+                : hw_w(hw_w), hw_h(hw_h) {
+            }
+            void operator()(GLfloat* vtx, float v) {
+                const GLfloat w = hw_w + (hw_w * v);
+                const GLfloat h = hw_h - (hw_h * v);
+                const GLfloat x = (hw_w - w) * 0.5f;
+                const GLfloat y = (hw_h - h) * 0.5f;
+                vtx[0] = x;         vtx[1] = y;
+                vtx[2] = x;         vtx[3] = y + h;
+                vtx[4] = x + w;     vtx[5] = y + h;
+                vtx[6] = x + w;     vtx[7] = y;
+            }
+        };
+
+        class h_stretch {
+            const GLfloat hw_w, hw_h;
+        public:
+            h_stretch(uint32_t hw_w, uint32_t hw_h)
+                : hw_w(hw_w), hw_h(hw_h) {
+            }
+            void operator()(GLfloat* vtx, float v) {
+                const GLfloat w = hw_w - (hw_w * v);
+                const GLfloat h = 1.0f;
+                const GLfloat x = (hw_w - w) * 0.5f;
+                const GLfloat y = (hw_h - h) * 0.5f;
+                vtx[0] = x;         vtx[1] = y;
+                vtx[2] = x;         vtx[3] = y + h;
+                vtx[4] = x + w;     vtx[5] = y + h;
+                vtx[6] = x + w;     vtx[7] = y;
+            }
+        };
+
+        // the full animation is 24 frames
+        const int nbFrames = 12;
+
+        v_stretch vverts(hw_w, hw_h);
+        s_curve_interpolator itr(nbFrames, 7.5f);
+        s_curve_interpolator itg(nbFrames, 8.0f);
+        s_curve_interpolator itb(nbFrames, 8.5f);
+        glEnable(GL_BLEND);
+        glBlendFunc(GL_ONE, GL_ONE);
+        for (int i=0 ; i<nbFrames ; i++) {
+            float x, y, w, h;
+            const float vr = itr(i);
+            const float vg = itg(i);
+            const float vb = itb(i);
+
+            // clear screen
+            glColorMask(1,1,1,1);
+            glClear(GL_COLOR_BUFFER_BIT);
+            glEnable(GL_TEXTURE_2D);
+
+            // draw the red plane
+            vverts(vtx, vr);
+            glColorMask(1,0,0,1);
+            glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+            // draw the green plane
+            vverts(vtx, vg);
+            glColorMask(0,1,0,1);
+            glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+            // draw the blue plane
+            vverts(vtx, vb);
+            glColorMask(0,0,1,1);
+            glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+            // draw the white highlight (we use the last vertices)
+            glDisable(GL_TEXTURE_2D);
+            glColorMask(1,1,1,1);
+            glColor4f(vg, vg, vg, 1);
+            glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+            hw.flip(screenBounds);
+        }
+
+        h_stretch hverts(hw_w, hw_h);
+        glDisable(GL_BLEND);
+        glDisable(GL_TEXTURE_2D);
+        glColorMask(1,1,1,1);
+        for (int i=0 ; i<nbFrames ; i++) {
+            const float v = itg(i);
+            hverts(vtx, v);
+            glClear(GL_COLOR_BUFFER_BIT);
+            glColor4f(1-v, 1-v, 1-v, 1);
+            glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+            hw.flip(screenBounds);
+        }
+
+        glColorMask(1,1,1,1);
+        glEnable(GL_SCISSOR_TEST);
+        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+        result = NO_ERROR;
+    } else {
+        // release FBO resources
+        glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
+        result = BAD_VALUE;
+    }
+
+    glDeleteFramebuffersOES(1, &name);
+    glDeleteTextures(1, &tname);
+
+    if (result == NO_ERROR) {
+        DisplayHardware& hw(graphicPlane(dpy).editDisplayHardware());
+        hw.setCanDraw(false);
+    }
+
+    return result;
+}
+
+status_t SurfaceFlinger::turnElectronBeamOff(int32_t mode)
+{
+    if (!GLExtensions::getInstance().haveFramebufferObject())
+        return INVALID_OPERATION;
+
+    class MessageTurnElectronBeamOff : public MessageBase {
+        SurfaceFlinger* flinger;
+        status_t result;
+    public:
+        MessageTurnElectronBeamOff(SurfaceFlinger* flinger)
+            : flinger(flinger), result(PERMISSION_DENIED) {
+        }
+        status_t getResult() const {
+            return result;
+        }
+        virtual bool handler() {
+            Mutex::Autolock _l(flinger->mStateLock);
+            result = flinger->turnElectronBeamOffImplLocked();
+            return true;
+        }
+    };
+
+    sp<MessageBase> msg = new MessageTurnElectronBeamOff(this);
+    status_t res = postMessageSync(msg);
+    if (res == NO_ERROR) {
+        res = static_cast<MessageTurnElectronBeamOff*>( msg.get() )->getResult();
+    }
+    return res;
+}
+
 // ---------------------------------------------------------------------------
 
 status_t SurfaceFlinger::captureScreenImplLocked(DisplayID dpy,
@@ -2115,6 +2341,10 @@
     return *mHw;
 }
 
+DisplayHardware& GraphicPlane::editDisplayHardware() {
+    return *mHw;
+}
+
 const Transform& GraphicPlane::transform() const {
     return mGlobalTransform;
 }
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 732e57e..3470d87 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -141,6 +141,7 @@
         int                     getHeight() const;
 
         const DisplayHardware&  displayHardware() const;
+        DisplayHardware&        editDisplayHardware();
         const Transform&        transform() const;
         EGLDisplay              getEGLDisplay() const;
         
@@ -200,6 +201,7 @@
                                                       PixelFormat* format,
                                                       uint32_t reqWidth,
                                                       uint32_t reqHeight);
+    virtual status_t                    turnElectronBeamOff(int32_t mode);
 
             void                        screenReleased(DisplayID dpy);
             void                        screenAcquired(DisplayID dpy);
@@ -326,6 +328,8 @@
                     uint32_t* width, uint32_t* height, PixelFormat* format,
                     uint32_t reqWidth = 0, uint32_t reqHeight = 0);
 
+            status_t turnElectronBeamOffImplLocked();
+
             friend class FreezeLock;
             sp<FreezeLock> getFreezeLock() const;
             inline void incFreezeCount() {