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

Commit aab758e8 authored by Mathias Agopian's avatar Mathias Agopian Committed by Joe Onorato
Browse files

turn off the electron beam

Change-Id: I335fb6719f1d5a3f1c6f37a046fd1c2c4ed2bbc6
parent 844a6b3c
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -118,6 +118,8 @@ public:
            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.
     */
@@ -142,7 +144,8 @@ public:
        FREEZE_DISPLAY,
        UNFREEZE_DISPLAY,
        SIGNAL,
        CAPTURE_SCREEN
        CAPTURE_SCREEN,
        TURN_ELECTRON_BEAM_OFF
    };

    virtual status_t    onTransact( uint32_t code,
+15 −0
Original line number Diff line number Diff line
@@ -142,6 +142,15 @@ 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 void signal() const
    {
        Parcel data, reply;
@@ -224,6 +233,12 @@ 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);
        }
        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
+13 −5
Original line number Diff line number Diff line
@@ -359,7 +359,7 @@ status_t DisplayHardwareBase::ConsoleManagerThread::initCheck() const

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 @@ DisplayHardwareBase::~DisplayHardwareBase()
    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 @@ void DisplayHardwareBase::acquireScreen() const
{
    status_t err = mDisplayEventThread->acquireScreen();
    if (err >= 0) {
        //LOGD("screen returned");
        mCanDraw = true;
        mScreenAcquired = true;
    }
}

bool DisplayHardwareBase::isScreenAcquired() const
{
    return mScreenAcquired;
}

}; // namespace android
+5 −0
Original line number Diff line number Diff line
@@ -40,7 +40,11 @@ public:
    // 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 @@ private:

    sp<DisplayEventThreadBase>  mDisplayEventThread;
    mutable int                 mCanDraw;
    mutable int                 mScreenAcquired;
};

}; // namespace android
+232 −2
Original line number Diff line number Diff line
@@ -423,14 +423,14 @@ void SurfaceFlinger::handleConsoleEvents()
        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;
@@ -1456,6 +1456,7 @@ status_t SurfaceFlinger::onTransact(
        case FREEZE_DISPLAY:
        case UNFREEZE_DISPLAY:
        case BOOT_FINISHED:
        case TURN_ELECTRON_BEAM_OFF:
        {
            // codes that require permission check
            IPCThreadState* ipc = IPCThreadState::self();
@@ -1544,6 +1545,231 @@ status_t SurfaceFlinger::onTransact(
    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,
@@ -2005,6 +2231,10 @@ const DisplayHardware& GraphicPlane::displayHardware() const {
    return *mHw;
}

DisplayHardware& GraphicPlane::editDisplayHardware() {
    return *mHw;
}

const Transform& GraphicPlane::transform() const {
    return mGlobalTransform;
}
Loading