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
This commit is contained in:
parent
9bdaa60b80
commit
2d5e230292
@ -46,6 +46,7 @@ public:
|
||||
// flags for setTransactionState()
|
||||
enum {
|
||||
eSynchronous = 0x01,
|
||||
eAnimation = 0x02,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -105,6 +105,9 @@ public:
|
||||
//! 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);
|
||||
|
@ -115,12 +115,15 @@ class Composer : public Singleton<Composer>
|
||||
SortedVector<ComposerState> mComposerStates;
|
||||
SortedVector<DisplayState > mDisplayStates;
|
||||
uint32_t mForceSynchronous;
|
||||
bool mAnimation;
|
||||
|
||||
Composer() : Singleton<Composer>(),
|
||||
mForceSynchronous(0)
|
||||
mForceSynchronous(0),
|
||||
mAnimation(false)
|
||||
{ }
|
||||
|
||||
void closeGlobalTransactionImpl(bool synchronous);
|
||||
void setAnimationTransactionImpl();
|
||||
|
||||
layer_state_t* getLayerStateLocked(
|
||||
const sp<SurfaceComposerClient>& 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<SurfaceComposerClient>& 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) {
|
||||
|
@ -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<count ; i++) {
|
||||
const DisplayState& s(displays[i]);
|
||||
@ -1685,15 +1702,18 @@ void SurfaceFlinger::setTransactionState(
|
||||
// if this is a synchronous transaction, wait for it to take effect
|
||||
// before returning.
|
||||
if (flags & eSynchronous) {
|
||||
mTransationPending = true;
|
||||
mTransactionPending = true;
|
||||
}
|
||||
while (mTransationPending) {
|
||||
if (flags & eAnimation) {
|
||||
mAnimTransactionPending = true;
|
||||
}
|
||||
while (mTransactionPending) {
|
||||
status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
|
||||
if (CC_UNLIKELY(err != NO_ERROR)) {
|
||||
// just in case something goes wrong in SF, return to the
|
||||
// called after a few seconds.
|
||||
ALOGW_IF(err == TIMED_OUT, "closeGlobalTransaction timed out!");
|
||||
mTransationPending = false;
|
||||
ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out!");
|
||||
mTransactionPending = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -398,7 +398,8 @@ private:
|
||||
volatile int32_t mTransactionFlags;
|
||||
Condition mTransactionCV;
|
||||
SortedVector<sp<LayerBase> > mLayerPurgatory;
|
||||
bool mTransationPending;
|
||||
bool mTransactionPending;
|
||||
bool mAnimTransactionPending;
|
||||
Vector<sp<LayerBase> > mLayersPendingRemoval;
|
||||
|
||||
// protected by mStateLock (but we could use another lock)
|
||||
|
Loading…
Reference in New Issue
Block a user