From 529efdf60f2015e591dd9cd62e8802c583a8917a Mon Sep 17 00:00:00 2001 From: Jamie Gennis Date: Mon, 15 Oct 2012 18:24:43 -0700 Subject: [PATCH 1/3] SurfaceFlinger: add animation transactions This change adds a transaction flag for WindowManager to indicate that a transaction is being used to animate windows around the screen. SurfaceFlinger will not allow more than one of these transactions to be outstanding at a time to prevent the animation "frames" from being dropped. Bug: 7353840 Change-Id: I6488a6e0e1ed13d27356d2203c9dc766dc6b1759 --- include/gui/ISurfaceComposer.h | 1 + include/gui/SurfaceComposerClient.h | 5 +++- libs/gui/SurfaceComposerClient.cpp | 23 +++++++++++++++- services/surfaceflinger/SurfaceFlinger.cpp | 32 ++++++++++++++++++---- services/surfaceflinger/SurfaceFlinger.h | 3 +- 5 files changed, 55 insertions(+), 9 deletions(-) diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h index 5d2d8d705..002aafc52 100644 --- a/include/gui/ISurfaceComposer.h +++ b/include/gui/ISurfaceComposer.h @@ -46,6 +46,7 @@ public: // flags for setTransactionState() enum { eSynchronous = 0x01, + eAnimation = 0x02, }; enum { diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h index 581ec8d47..21d16a947 100644 --- a/include/gui/SurfaceComposerClient.h +++ b/include/gui/SurfaceComposerClient.h @@ -101,10 +101,13 @@ public: //! Open a composer transaction on all active SurfaceComposerClients. static void openGlobalTransaction(); - + //! Close a composer transaction on all active SurfaceComposerClients. static void closeGlobalTransaction(bool synchronous = false); + //! Flag the currently open transaction as an animation transaction. + static void setAnimationTransaction(); + status_t hide(SurfaceID id); status_t show(SurfaceID id); status_t setFlags(SurfaceID id, uint32_t flags, uint32_t mask); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 3efd086bd..8586ed218 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -115,12 +115,15 @@ class Composer : public Singleton SortedVector mComposerStates; SortedVector mDisplayStates; uint32_t mForceSynchronous; + bool mAnimation; Composer() : Singleton(), - mForceSynchronous(0) + mForceSynchronous(0), + mAnimation(false) { } void closeGlobalTransactionImpl(bool synchronous); + void setAnimationTransactionImpl(); layer_state_t* getLayerStateLocked( const sp& client, SurfaceID id); @@ -159,6 +162,10 @@ public: const Rect& layerStackRect, const Rect& displayRect); + static void setAnimationTransaction() { + Composer::getInstance().setAnimationTransactionImpl(); + } + static void closeGlobalTransaction(bool synchronous) { Composer::getInstance().closeGlobalTransactionImpl(synchronous); } @@ -194,12 +201,22 @@ void Composer::closeGlobalTransactionImpl(bool synchronous) { if (synchronous || mForceSynchronous) { flags |= ISurfaceComposer::eSynchronous; } + if (mAnimation) { + flags |= ISurfaceComposer::eAnimation; + } + mForceSynchronous = false; + mAnimation = false; } sm->setTransactionState(transaction, displayTransaction, flags); } +void Composer::setAnimationTransactionImpl() { + Mutex::Autolock _l(mLock); + mAnimation = true; +} + layer_state_t* Composer::getLayerStateLocked( const sp& client, SurfaceID id) { @@ -471,6 +488,10 @@ void SurfaceComposerClient::closeGlobalTransaction(bool synchronous) { Composer::closeGlobalTransaction(synchronous); } +void SurfaceComposerClient::setAnimationTransaction() { + Composer::setAnimationTransaction(); +} + // ---------------------------------------------------------------------------- status_t SurfaceComposerClient::setCrop(SurfaceID id, const Rect& crop) { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 492d1cf10..e21e2bfc3 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -86,7 +86,8 @@ const String16 sDump("android.permission.DUMP"); SurfaceFlinger::SurfaceFlinger() : BnSurfaceComposer(), Thread(false), mTransactionFlags(0), - mTransationPending(false), + mTransactionPending(false), + mAnimTransactionPending(false), mLayersRemoved(false), mRepaintEverything(0), mBootTime(systemTime()), @@ -1264,7 +1265,8 @@ void SurfaceFlinger::commitTransaction() } mDrawingState = mCurrentState; - mTransationPending = false; + mTransactionPending = false; + mAnimTransactionPending = false; mTransactionCV.broadcast(); } @@ -1665,6 +1667,21 @@ void SurfaceFlinger::setTransactionState( Mutex::Autolock _l(mStateLock); uint32_t transactionFlags = 0; + if (flags & eAnimation) { + // For window updates that are part of an animation we must wait for + // previous animation "frames" to be handled. + while (mAnimTransactionPending) { + status_t err = mTransactionCV.waitRelative(mStateLock, 500 * 1000); + if (CC_UNLIKELY(err != NO_ERROR)) { + // just in case something goes wrong in SF, return to the + // caller after a few hundred microseconds. + ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out!"); + mAnimTransactionPending = false; + break; + } + } + } + size_t count = displays.size(); for (size_t i=0 ; i > mLayerPurgatory; - bool mTransationPending; + bool mTransactionPending; + bool mAnimTransactionPending; Vector > mLayersPendingRemoval; // protected by mStateLock (but we could use another lock) From 4ea5d656db0f5fcc4ae6c792ec83e157a2c1bae8 Mon Sep 17 00:00:00 2001 From: Jesse Hall Date: Mon, 15 Oct 2012 12:38:33 -0700 Subject: [PATCH 2/3] Always set vertex alpha when drawing screenshot layers The screenshot is a GL_RGB texture, and the GL_REPLACE texture env mode uses vertex alpha for GL_RGB textures instead of alpha=1.0. Bug: 7340077 Change-Id: I6fbb907023e48f9c422b15a33da79757d6726840 --- services/surfaceflinger/LayerScreenshot.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/surfaceflinger/LayerScreenshot.cpp b/services/surfaceflinger/LayerScreenshot.cpp index 1aa8c099d..0fd744fdd 100644 --- a/services/surfaceflinger/LayerScreenshot.cpp +++ b/services/surfaceflinger/LayerScreenshot.cpp @@ -122,13 +122,14 @@ void LayerScreenshot::onDraw(const sp& hw, const Region& cl } else { glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - glColor4f(alpha, alpha, alpha, alpha); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } LayerMesh mesh; computeGeometry(hw, &mesh); + glColor4f(alpha, alpha, alpha, alpha); + glDisable(GL_TEXTURE_EXTERNAL_OES); glEnable(GL_TEXTURE_2D); From 1b10e25356fed2d9d3480485638e737332be6ef7 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Wed, 24 Oct 2012 16:29:17 -0700 Subject: [PATCH 3/3] partially implement external display clipping we perform external display clipping only on the GL side (ie: not done on the h/w composer side, which is harder and would be too risky). in practice this means that WFD will be clipped properly, while HDMI *may* or may not depending on how hwc is used. Bug: 7149437 Change-Id: I92d4d04220db72b6ffb134c7fa7a93af569723a5 --- services/surfaceflinger/SurfaceFlinger.cpp | 25 ++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 26e9c6054..7ee6e5ead 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1500,6 +1500,28 @@ void SurfaceFlinger::doComposeSurfaces(const sp& hw, const drawWormhole(hw, region); } } + + if (hw->getDisplayType() >= DisplayDevice::DISPLAY_EXTERNAL) { + // TODO: just to be on the safe side, we don't set the + // scissor on the main display. It should never be needed + // anyways (though in theory it could since the API allows it). + const Rect& bounds(hw->getBounds()); + const Transform& tr(hw->getTransform()); + const Rect scissor(tr.transform(hw->getViewport())); + if (scissor != bounds) { + // scissor doesn't match the screen's dimensions, so we + // need to clear everything outside of it and enable + // the GL scissor so we don't draw anything where we shouldn't + const GLint height = hw->getHeight(); + glScissor(scissor.left, height - scissor.bottom, + scissor.getWidth(), scissor.getHeight()); + // clear everything unscissored + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); + // enable scissor for this frame + glEnable(GL_SCISSOR_TEST); + } + } } /* @@ -1552,6 +1574,9 @@ void SurfaceFlinger::doComposeSurfaces(const sp& hw, const } } } + + // disable scissor at the end of the frame + glDisable(GL_SCISSOR_TEST); } void SurfaceFlinger::drawWormhole(const sp& hw,