Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 92efd84f authored by Mathias Agopian's avatar Mathias Agopian
Browse files

screen-off animation won't be handled by SF anymore

Change-Id: Idc41386804ae7d7eb981c36e1bc55c270870c8d0
parent 92a979a9
Loading
Loading
Loading
Loading
+0 −13
Original line number Diff line number Diff line
@@ -89,11 +89,6 @@ public:
        eSynchronous            = 0x01,
    };

    enum {
        eElectronBeamAnimationOn  = 0x01,
        eElectronBeamAnimationOff = 0x10
    };

    /* create connection with surface flinger, requires
     * ACCESS_SURFACE_FLINGER permission
     */
@@ -123,12 +118,6 @@ public:
            uint32_t reqWidth, uint32_t reqHeight,
            uint32_t minLayerZ, uint32_t maxLayerZ) = 0;

    /* triggers screen off animation */
    virtual status_t turnElectronBeamOff(int32_t mode) = 0;

    /* triggers screen on animation */
    virtual status_t turnElectronBeamOn(int32_t mode) = 0;

    /* verify that an ISurfaceTexture was created by SurfaceFlinger.
     */
    virtual bool authenticateSurfaceTexture(
@@ -166,8 +155,6 @@ public:
        SET_TRANSACTION_STATE,
        SET_ORIENTATION,
        CAPTURE_SCREEN,
        TURN_ELECTRON_BEAM_OFF,
        TURN_ELECTRON_BEAM_ON,
        AUTHENTICATE_SURFACE,
        CREATE_DISPLAY_EVENT_CONNECTION,
        BLANK,
+0 −30
Original line number Diff line number Diff line
@@ -123,24 +123,6 @@ public:
        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 status_t turnElectronBeamOn(int32_t mode)
    {
        Parcel data, reply;
        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
        data.writeInt32(mode);
        remote()->transact(BnSurfaceComposer::TURN_ELECTRON_BEAM_ON, data, &reply);
        return reply.readInt32();
    }

    virtual bool authenticateSurfaceTexture(
            const sp<ISurfaceTexture>& surfaceTexture) const
    {
@@ -291,18 +273,6 @@ status_t BnSurfaceComposer::onTransact(
            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);
        } break;
        case TURN_ELECTRON_BEAM_ON: {
            CHECK_INTERFACE(ISurfaceComposer, data, reply);
            int32_t mode = data.readInt32();
            status_t res = turnElectronBeamOn(mode);
            reply->writeInt32(res);
        } break;
        case AUTHENTICATE_SURFACE: {
            CHECK_INTERFACE(ISurfaceComposer, data, reply);
            sp<ISurfaceTexture> surfaceTexture =
+0 −473
Original line number Diff line number Diff line
@@ -86,7 +86,6 @@ SurfaceFlinger::SurfaceFlinger()
        mBootTime(systemTime()),
        mVisibleRegionsDirty(false),
        mHwWorkListDirty(false),
        mElectronBeamAnimationMode(0),
        mDebugRegion(0),
        mDebugDDMS(0),
        mDebugDisableHWC(0),
@@ -1619,11 +1618,6 @@ void SurfaceFlinger::onScreenAcquired() {
    getHwComposer().acquire();
    hw.acquireScreen();
    mEventThread->onScreenAcquired();
    // this is a temporary work-around, eventually this should be called
    // by the power-manager
    SurfaceFlinger::turnElectronBeamOn(mElectronBeamAnimationMode);
    // from this point on, SF will process updates again
    repaintEverything();
}

void SurfaceFlinger::onScreenReleased() {
@@ -1906,8 +1900,6 @@ status_t SurfaceFlinger::onTransact(
        case SET_TRANSACTION_STATE:
        case SET_ORIENTATION:
        case BOOT_FINISHED:
        case TURN_ELECTRON_BEAM_OFF:
        case TURN_ELECTRON_BEAM_ON:
        case BLANK:
        case UNBLANK:
        {
@@ -2085,471 +2077,6 @@ status_t SurfaceFlinger::renderScreenToTextureLocked(DisplayID dpy,

// ---------------------------------------------------------------------------

class VSyncWaiter {
    DisplayEventReceiver::Event buffer[4];
    sp<Looper> looper;
    sp<IDisplayEventConnection> events;
    sp<BitTube> eventTube;
public:
    VSyncWaiter(const sp<EventThread>& eventThread) {
        looper = new Looper(true);
        events = eventThread->createEventConnection();
        eventTube = events->getDataChannel();
        looper->addFd(eventTube->getFd(), 0, ALOOPER_EVENT_INPUT, 0, 0);
        events->requestNextVsync();
    }

    void wait() {
        ssize_t n;

        looper->pollOnce(-1);
        // we don't handle any errors here, it doesn't matter
        // and we don't want to take the risk to get stuck.

        // drain the events...
        while ((n = DisplayEventReceiver::getEvents(
                eventTube, buffer, 4)) > 0) ;

        events->requestNextVsync();
    }
};

status_t SurfaceFlinger::electronBeamOffAnimationImplLocked()
{
    // get screen geometry
    const DisplayDevice& hw(getDefaultDisplayDevice());
    const uint32_t hw_w = hw.getWidth();
    const uint32_t hw_h = hw.getHeight();
    const Region screenBounds(hw.getBounds());

    GLfloat u, v;
    GLuint tname;
    status_t result = renderScreenToTextureLocked(0, &tname, &u, &v);
    if (result != NO_ERROR) {
        return result;
    }

    GLfloat vtx[8];
    const GLfloat texCoords[4][2] = { {0,0}, {0,v}, {u,v}, {u,0} };
    glBindTexture(GL_TEXTURE_2D, tname);
    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glVertexPointer(2, GL_FLOAT, 0, vtx);

    /*
     * Texture coordinate mapping
     *
     *                 u
     *    1 +----------+---+
     *      |     |    |   |  image is inverted
     *      |     V    |   |  w.r.t. the texture
     *  1-v +----------+   |  coordinates
     *      |              |
     *      |              |
     *      |              |
     *    0 +--------------+
     *      0              1
     *
     */

    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;
        }
    };

    VSyncWaiter vsync(mEventThread);

    // the full animation is 24 frames
    char value[PROPERTY_VALUE_MAX];
    property_get("debug.sf.electron_frames", value, "24");
    int nbFrames = (atoi(value) + 1) >> 1;
    if (nbFrames <= 0) // just in case
        nbFrames = 24;

    s_curve_interpolator itr(nbFrames, 7.5f);
    s_curve_interpolator itg(nbFrames, 8.0f);
    s_curve_interpolator itb(nbFrames, 8.5f);

    v_stretch vverts(hw_w, hw_h);

    glMatrixMode(GL_TEXTURE);
    glLoadIdentity();
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

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

        // wait for vsync
        vsync.wait();

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

        // wait for vsync
        vsync.wait();

        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);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDeleteTextures(1, &tname);
    glDisable(GL_TEXTURE_2D);
    glDisable(GL_BLEND);
    return NO_ERROR;
}

status_t SurfaceFlinger::electronBeamOnAnimationImplLocked()
{
    status_t result = PERMISSION_DENIED;

    if (!GLExtensions::getInstance().haveFramebufferObject())
        return INVALID_OPERATION;


    // get screen geometry
    const DisplayDevice& hw(getDefaultDisplayDevice());
    const uint32_t hw_w = hw.getWidth();
    const uint32_t hw_h = hw.getHeight();
    const Region screenBounds(hw.bounds());

    GLfloat u, v;
    GLuint tname;
    result = renderScreenToTextureLocked(0, &tname, &u, &v);
    if (result != NO_ERROR) {
        return result;
    }

    GLfloat vtx[8];
    const GLfloat texCoords[4][2] = { {0,v}, {0,0}, {u,0}, {u,v} };
    glBindTexture(GL_TEXTURE_2D, tname);
    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    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;
        }
    };

    VSyncWaiter vsync(mEventThread);

    // the full animation is 12 frames
    int nbFrames = 8;
    s_curve_interpolator itr(nbFrames, 7.5f);
    s_curve_interpolator itg(nbFrames, 8.0f);
    s_curve_interpolator itb(nbFrames, 8.5f);

    h_stretch hverts(hw_w, hw_h);
    glDisable(GL_BLEND);
    glDisable(GL_TEXTURE_2D);
    glColorMask(1,1,1,1);
    for (int i=nbFrames-1 ; i>=0 ; i--) {
        const float v = itg(i);
        hverts(vtx, v);

        // wait for vsync
        vsync.wait();

        glClear(GL_COLOR_BUFFER_BIT);
        glColor4f(1-v, 1-v, 1-v, 1);
        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
        hw.flip(screenBounds);
    }

    nbFrames = 4;
    v_stretch vverts(hw_w, hw_h);
    glEnable(GL_BLEND);
    glBlendFunc(GL_ONE, GL_ONE);
    for (int i=nbFrames-1 ; i>=0 ; i--) {
        float x, y, w, h;
        const float vr = itr(i);
        const float vg = itg(i);
        const float vb = itb(i);

        // wait for vsync
        vsync.wait();

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

        hw.flip(screenBounds);
    }

    glColorMask(1,1,1,1);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDeleteTextures(1, &tname);
    glDisable(GL_TEXTURE_2D);
    glDisable(GL_BLEND);

    return NO_ERROR;
}

// ---------------------------------------------------------------------------

status_t SurfaceFlinger::turnElectronBeamOffImplLocked(int32_t mode)
{
    ATRACE_CALL();

    DisplayDevice& hw(const_cast<DisplayDevice&>(getDefaultDisplayDevice()));
    if (!hw.canDraw()) {
        // we're already off
        return NO_ERROR;
    }

    // turn off hwc while we're doing the animation
    getHwComposer().disable();
    // and make sure to turn it back on (if needed) next time we compose
    invalidateHwcGeometry();

    if (mode & ISurfaceComposer::eElectronBeamAnimationOff) {
        electronBeamOffAnimationImplLocked();
    }

    // always clear the whole screen at the end of the animation
    glClearColor(0,0,0,1);
    glClear(GL_COLOR_BUFFER_BIT);
    hw.flip( Region(hw.bounds()) );

    return NO_ERROR;
}

status_t SurfaceFlinger::turnElectronBeamOff(int32_t mode)
{
    class MessageTurnElectronBeamOff : public MessageBase {
        SurfaceFlinger* flinger;
        int32_t mode;
        status_t result;
    public:
        MessageTurnElectronBeamOff(SurfaceFlinger* flinger, int32_t mode)
            : flinger(flinger), mode(mode), result(PERMISSION_DENIED) {
        }
        status_t getResult() const {
            return result;
        }
        virtual bool handler() {
            Mutex::Autolock _l(flinger->mStateLock);
            result = flinger->turnElectronBeamOffImplLocked(mode);
            return true;
        }
    };

    sp<MessageBase> msg = new MessageTurnElectronBeamOff(this, mode);
    status_t res = postMessageSync(msg);
    if (res == NO_ERROR) {
        res = static_cast<MessageTurnElectronBeamOff*>( msg.get() )->getResult();

        // work-around: when the power-manager calls us we activate the
        // animation. eventually, the "on" animation will be called
        // by the power-manager itself
        mElectronBeamAnimationMode = mode;
    }
    return res;
}

// ---------------------------------------------------------------------------

status_t SurfaceFlinger::turnElectronBeamOnImplLocked(int32_t mode)
{
    DisplayDevice& hw(const_cast<DisplayDevice&>(getDefaultDisplayDevice()));
    if (hw.canDraw()) {
        // we're already on
        return NO_ERROR;
    }
    if (mode & ISurfaceComposer::eElectronBeamAnimationOn) {
        electronBeamOnAnimationImplLocked();
    }

    // make sure to redraw the whole screen when the animation is done
    hw.dirtyRegion.set(hw.bounds());
    signalTransaction();

    return NO_ERROR;
}

status_t SurfaceFlinger::turnElectronBeamOn(int32_t mode)
{
    class MessageTurnElectronBeamOn : public MessageBase {
        SurfaceFlinger* flinger;
        int32_t mode;
        status_t result;
    public:
        MessageTurnElectronBeamOn(SurfaceFlinger* flinger, int32_t mode)
            : flinger(flinger), mode(mode), result(PERMISSION_DENIED) {
        }
        status_t getResult() const {
            return result;
        }
        virtual bool handler() {
            Mutex::Autolock _l(flinger->mStateLock);
            result = flinger->turnElectronBeamOnImplLocked(mode);
            return true;
        }
    };

    postMessageAsync( new MessageTurnElectronBeamOn(this, mode) );
    return NO_ERROR;
}

// ---------------------------------------------------------------------------

status_t SurfaceFlinger::captureScreenImplLocked(DisplayID dpy,
        sp<IMemoryHeap>* heap,
        uint32_t* w, uint32_t* h, PixelFormat* f,
+0 −8
Original line number Diff line number Diff line
@@ -195,8 +195,6 @@ private:
        uint32_t* width, uint32_t* height, PixelFormat* format,
        uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ,
        uint32_t maxLayerZ);
    virtual status_t turnElectronBeamOff(int32_t mode);
    virtual status_t turnElectronBeamOn(int32_t mode);
    // called when screen needs to turn off
    virtual void blank();
    // called when screen is turning back on
@@ -307,11 +305,6 @@ private:
        uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ,
        uint32_t maxLayerZ);

    status_t turnElectronBeamOffImplLocked(int32_t mode);
    status_t turnElectronBeamOnImplLocked(int32_t mode);
    status_t electronBeamOffAnimationImplLocked();
    status_t electronBeamOnAnimationImplLocked();

    /* ------------------------------------------------------------------------
     * EGL
     */
@@ -404,7 +397,6 @@ private:
    State mDrawingState;
    bool mVisibleRegionsDirty;
    bool mHwWorkListDirty;
    int32_t mElectronBeamAnimationMode;
    DefaultKeyedVector<int32_t, DisplayDevice> mDisplays;

    // don't use a lock for these, we don't care