From 9daa5c9b9dd286cbbf5d43f7e45a5e9e4048e855 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Tue, 12 Oct 2010 16:05:48 -0700 Subject: [PATCH] implement part of [3094280] New animation for screen on and screen off add support for screen on animation Change-Id: If50cf52ae04b95b42da7d74cf7fa96d5cb54d238 --- include/surfaceflinger/ISurfaceComposer.h | 4 +- .../ISurfaceComposer.cpp | 15 + .../DisplayHardware/DisplayHardwareBase.cpp | 1 - services/surfaceflinger/SurfaceFlinger.cpp | 517 +++++++++++++----- services/surfaceflinger/SurfaceFlinger.h | 7 + 5 files changed, 394 insertions(+), 150 deletions(-) diff --git a/include/surfaceflinger/ISurfaceComposer.h b/include/surfaceflinger/ISurfaceComposer.h index 1a1821c14..de447be64 100644 --- a/include/surfaceflinger/ISurfaceComposer.h +++ b/include/surfaceflinger/ISurfaceComposer.h @@ -119,6 +119,7 @@ public: uint32_t reqWidth, uint32_t reqHeight) = 0; virtual status_t turnElectronBeamOff(int32_t mode) = 0; + virtual status_t turnElectronBeamOn(int32_t mode) = 0; /* Signal surfaceflinger that there might be some work to do * This is an ASYNCHRONOUS call. @@ -145,7 +146,8 @@ public: UNFREEZE_DISPLAY, SIGNAL, CAPTURE_SCREEN, - TURN_ELECTRON_BEAM_OFF + TURN_ELECTRON_BEAM_OFF, + TURN_ELECTRON_BEAM_ON }; virtual status_t onTransact( uint32_t code, diff --git a/libs/surfaceflinger_client/ISurfaceComposer.cpp b/libs/surfaceflinger_client/ISurfaceComposer.cpp index d72561fd7..969ee7985 100644 --- a/libs/surfaceflinger_client/ISurfaceComposer.cpp +++ b/libs/surfaceflinger_client/ISurfaceComposer.cpp @@ -151,6 +151,15 @@ public: 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 void signal() const { Parcel data, reply; @@ -239,6 +248,12 @@ status_t BnSurfaceComposer::onTransact( status_t res = turnElectronBeamOff(mode); reply->writeInt32(res); } + case TURN_ELECTRON_BEAM_ON: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + int32_t mode = data.readInt32(); + status_t res = turnElectronBeamOn(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 fe9a5ab33..90865da80 100644 --- a/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp +++ b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp @@ -396,7 +396,6 @@ void DisplayHardwareBase::acquireScreen() const { status_t err = mDisplayEventThread->acquireScreen(); if (err >= 0) { - mCanDraw = true; mScreenAcquired = true; } } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index a919ddf8d..373496971 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -80,6 +80,7 @@ SurfaceFlinger::SurfaceFlinger() mVisibleRegionsDirty(false), mDeferReleaseConsole(false), mFreezeDisplay(false), + mElectronBeamAnimation(false), mFreezeCount(0), mFreezeDisplayTime(0), mDebugRegion(0), @@ -421,6 +422,10 @@ void SurfaceFlinger::handleConsoleEvents() int what = android_atomic_and(0, &mConsoleSignals); if (what & eConsoleAcquired) { hw.acquireScreen(); + // this is a temporary work-around, eventually this should be called + // by the power-manager + if (mElectronBeamAnimation) + SurfaceFlinger::turnElectronBeamOn(0); } if (mDeferReleaseConsole && hw.isScreenAcquired()) { @@ -1457,6 +1462,7 @@ status_t SurfaceFlinger::onTransact( case UNFREEZE_DISPLAY: case BOOT_FINISHED: case TURN_ELECTRON_BEAM_OFF: + case TURN_ELECTRON_BEAM_ON: { // codes that require permission check IPCThreadState* ipc = IPCThreadState::self(); @@ -1545,27 +1551,18 @@ status_t SurfaceFlinger::onTransact( return err; } - // --------------------------------------------------------------------------- -status_t SurfaceFlinger::turnElectronBeamOffImplLocked() +status_t SurfaceFlinger::renderScreenToTextureLocked(DisplayID dpy, + GLuint* textureName, GLfloat* uOut, GLfloat* vOut) { - 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; @@ -1576,167 +1573,344 @@ status_t SurfaceFlinger::turnElectronBeamOffImplLocked() 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); + 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); + 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); + 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); + // redraw the screen entirely... + glClearColor(0,0,0,1); + glClear(GL_COLOR_BUFFER_BIT); + const Vector< sp >& layers(mVisibleLayersSortedByZ); + const size_t count = layers.size(); + for (size_t i=0 ; i& layer(layers[i]); + layer->drawForSreenShot(); + } + + // back to main framebuffer + glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); + glDisable(GL_SCISSOR_TEST); + glDeleteFramebuffersOES(1, &name); + + *textureName = tname; + *uOut = u; + *vOut = v; + return NO_ERROR; +} + +// --------------------------------------------------------------------------- + +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(); + 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} }; + glEnable(GL_TEXTURE_2D); + 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); + 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; + 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); + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE); + for (int i=0 ; i >& layers(mVisibleLayersSortedByZ); - const size_t count = layers.size(); - for (size_t i=0 ; i& 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; - } - }; + // draw the red plane + vverts(vtx, vr); + glColorMask(1,0,0,1); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - 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; - } - }; + // draw the green plane + vverts(vtx, vg); + glColorMask(0,1,0,1); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - 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; - } - }; + // draw the blue plane + vverts(vtx, vb); + glColorMask(0,0,1,1); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - // 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=0 ; 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); + } + + 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); + + // 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); + glEnable(GL_SCISSOR_TEST); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDeleteTextures(1, &tname); + return NO_ERROR; +} + +// --------------------------------------------------------------------------- + +status_t SurfaceFlinger::turnElectronBeamOffImplLocked() +{ + DisplayHardware& hw(graphicPlane(0).editDisplayHardware()); + if (!hw.canDraw()) { + // we're already off + return NO_ERROR; + } + status_t result = electronBeamOffAnimationImplLocked(); if (result == NO_ERROR) { - DisplayHardware& hw(graphicPlane(dpy).editDisplayHardware()); hw.setCanDraw(false); } - return result; } @@ -1766,12 +1940,59 @@ status_t SurfaceFlinger::turnElectronBeamOff(int32_t mode) status_t res = postMessageSync(msg); if (res == NO_ERROR) { res = static_cast( 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 + mElectronBeamAnimation = true; } return res; } // --------------------------------------------------------------------------- +status_t SurfaceFlinger::turnElectronBeamOnImplLocked() +{ + DisplayHardware& hw(graphicPlane(0).editDisplayHardware()); + if (hw.canDraw()) { + // we're already on + return NO_ERROR; + } + status_t result = electronBeamOnAnimationImplLocked(); + if (result == NO_ERROR) { + hw.setCanDraw(true); + } + return result; +} + +status_t SurfaceFlinger::turnElectronBeamOn(int32_t mode) +{ + if (!GLExtensions::getInstance().haveFramebufferObject()) + return INVALID_OPERATION; + + class MessageTurnElectronBeamOn : public MessageBase { + SurfaceFlinger* flinger; + status_t result; + public: + MessageTurnElectronBeamOn(SurfaceFlinger* flinger) + : flinger(flinger), result(PERMISSION_DENIED) { + } + status_t getResult() const { + return result; + } + virtual bool handler() { + Mutex::Autolock _l(flinger->mStateLock); + result = flinger->turnElectronBeamOnImplLocked(); + return true; + } + }; + + postMessageAsync( new MessageTurnElectronBeamOn(this) ); + return NO_ERROR; +} + +// --------------------------------------------------------------------------- + status_t SurfaceFlinger::captureScreenImplLocked(DisplayID dpy, sp* heap, uint32_t* w, uint32_t* h, PixelFormat* f, diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index f85a22bed..d07a3ad0a 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -202,6 +202,7 @@ public: uint32_t reqWidth, uint32_t reqHeight); virtual status_t turnElectronBeamOff(int32_t mode); + virtual status_t turnElectronBeamOn(int32_t mode); void screenReleased(DisplayID dpy); void screenAcquired(DisplayID dpy); @@ -328,6 +329,11 @@ private: uint32_t reqWidth = 0, uint32_t reqHeight = 0); status_t turnElectronBeamOffImplLocked(); + status_t turnElectronBeamOnImplLocked(); + status_t electronBeamOffAnimationImplLocked(); + status_t electronBeamOnAnimationImplLocked(); + status_t renderScreenToTextureLocked(DisplayID dpy, + GLuint* textureName, GLfloat* uOut, GLfloat* vOut); friend class FreezeLock; sp getFreezeLock() const; @@ -389,6 +395,7 @@ private: bool mVisibleRegionsDirty; bool mDeferReleaseConsole; bool mFreezeDisplay; + bool mElectronBeamAnimation; int32_t mFreezeCount; nsecs_t mFreezeDisplayTime; Vector< sp > mVisibleLayersSortedByZ;