mPendingStates.push_back(mCurrentState);
}
-void Layer::popPendingState() {
- auto oldFlags = mCurrentState.flags;
- mCurrentState = mPendingStates[0];
- mCurrentState.flags = (oldFlags & ~mCurrentState.mask) |
- (mCurrentState.flags & mCurrentState.mask);
+void Layer::popPendingState(State* stateToCommit) {
+ auto oldFlags = stateToCommit->flags;
+ *stateToCommit = mPendingStates[0];
+ stateToCommit->flags = (oldFlags & ~stateToCommit->mask) |
+ (stateToCommit->flags & stateToCommit->mask);
mPendingStates.removeAt(0);
}
-bool Layer::applyPendingStates() {
+bool Layer::applyPendingStates(State* stateToCommit) {
bool stateUpdateAvailable = false;
while (!mPendingStates.empty()) {
if (mPendingStates[0].handle != nullptr) {
// will be visually wrong, but it should keep us from getting
// into too much trouble.
ALOGE("[%s] No local sync point found", mName.string());
- popPendingState();
+ popPendingState(stateToCommit);
stateUpdateAvailable = true;
continue;
}
if (mRemoteSyncPoints.front()->frameIsAvailable()) {
// Apply the state update
- popPendingState();
+ popPendingState(stateToCommit);
stateUpdateAvailable = true;
// Signal our end of the sync point and then dispose of it
break;
}
} else {
- popPendingState();
+ popPendingState(stateToCommit);
stateUpdateAvailable = true;
}
}
ATRACE_CALL();
pushPendingState();
- if (!applyPendingStates()) {
+ Layer::State c = getCurrentState();
+ if (!applyPendingStates(&c)) {
return 0;
}
const Layer::State& s(getDrawingState());
- const Layer::State& c(getCurrentState());
const bool sizeChanged = (c.requested.w != s.requested.w) ||
(c.requested.h != s.requested.h);
// this is used by Layer, which special cases resizes.
if (flags & eDontUpdateGeometryState) {
} else {
- Layer::State& editCurrentState(getCurrentState());
- editCurrentState.active = c.requested;
+ c.active = c.requested;
}
if (s.active != c.active) {
}
// Commit the transaction
- commitTransaction();
+ commitTransaction(c);
return flags;
}
-void Layer::commitTransaction() {
- mDrawingState = mCurrentState;
+void Layer::commitTransaction(const State& stateToCommit) {
+ mDrawingState = stateToCommit;
}
uint32_t Layer::getTransactionFlags(uint32_t flags) {
}
}
+TEST_F(LayerUpdateTest, DeferredTransactionTest) {
+ sp<ScreenCapture> sc;
+ {
+ SCOPED_TRACE("before anything");
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel( 32, 32, 63, 63, 195);
+ sc->checkPixel( 96, 96, 195, 63, 63);
+ sc->checkPixel(160, 160, 63, 63, 195);
+ }
+
+ // set up two deferred transactions on different frames
+ SurfaceComposerClient::openGlobalTransaction();
+ ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(0.75));
+ mFGSurfaceControl->deferTransactionUntil(mSyncSurfaceControl->getHandle(),
+ mSyncSurfaceControl->getSurface()->getNextFrameNumber());
+ SurfaceComposerClient::closeGlobalTransaction(true);
+
+ SurfaceComposerClient::openGlobalTransaction();
+ ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(128,128));
+ mFGSurfaceControl->deferTransactionUntil(mSyncSurfaceControl->getHandle(),
+ mSyncSurfaceControl->getSurface()->getNextFrameNumber() + 1);
+ SurfaceComposerClient::closeGlobalTransaction(true);
+
+ {
+ SCOPED_TRACE("before any trigger");
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel( 32, 32, 63, 63, 195);
+ sc->checkPixel( 96, 96, 195, 63, 63);
+ sc->checkPixel(160, 160, 63, 63, 195);
+ }
+
+ // should trigger the first deferred transaction, but not the second one
+ fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
+ {
+ SCOPED_TRACE("after first trigger");
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel( 32, 32, 63, 63, 195);
+ sc->checkPixel( 96, 96, 162, 63, 96);
+ sc->checkPixel(160, 160, 63, 63, 195);
+ }
+
+ // should show up immediately since it's not deferred
+ SurfaceComposerClient::openGlobalTransaction();
+ ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(1.0));
+ SurfaceComposerClient::closeGlobalTransaction(true);
+
+ // trigger the second deferred transaction
+ fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
+ {
+ SCOPED_TRACE("after second trigger");
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel( 32, 32, 63, 63, 195);
+ sc->checkPixel( 96, 96, 63, 63, 195);
+ sc->checkPixel(160, 160, 195, 63, 63);
+ }
+}
+
}