fix another bug where screenshots could end-up all black
SF transactions were always handled on VSYNC which allowed the screenshot to sneak-in between closing the transaction and vsync (before it's latched), resulting in a screenshot with the previous state. we now always force transactions to happen immediately before screenhots. Bug: 7552304 Change-Id: I0afc86b7e8366173daff5b9988bbb4d2a0f43860
This commit is contained in:
parent
1df59c93fe
commit
9eb1f0558b
@ -61,6 +61,12 @@ void MessageQueue::Handler::dispatchInvalidate() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MessageQueue::Handler::dispatchTransaction() {
|
||||||
|
if ((android_atomic_or(eventMaskTransaction, &mEventMask) & eventMaskTransaction) == 0) {
|
||||||
|
mQueue.mLooper->sendMessage(this, Message(MessageQueue::TRANSACTION));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MessageQueue::Handler::handleMessage(const Message& message) {
|
void MessageQueue::Handler::handleMessage(const Message& message) {
|
||||||
switch (message.what) {
|
switch (message.what) {
|
||||||
case INVALIDATE:
|
case INVALIDATE:
|
||||||
@ -71,6 +77,10 @@ void MessageQueue::Handler::handleMessage(const Message& message) {
|
|||||||
android_atomic_and(~eventMaskRefresh, &mEventMask);
|
android_atomic_and(~eventMaskRefresh, &mEventMask);
|
||||||
mQueue.mFlinger->onMessageReceived(message.what);
|
mQueue.mFlinger->onMessageReceived(message.what);
|
||||||
break;
|
break;
|
||||||
|
case TRANSACTION:
|
||||||
|
android_atomic_and(~eventMaskTransaction, &mEventMask);
|
||||||
|
mQueue.mFlinger->onMessageReceived(message.what);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,6 +142,7 @@ status_t MessageQueue::postMessage(
|
|||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* when INVALIDATE_ON_VSYNC is set SF only processes
|
/* when INVALIDATE_ON_VSYNC is set SF only processes
|
||||||
* buffer updates on VSYNC and performs a refresh immediately
|
* buffer updates on VSYNC and performs a refresh immediately
|
||||||
* after.
|
* after.
|
||||||
@ -143,6 +154,10 @@ status_t MessageQueue::postMessage(
|
|||||||
*/
|
*/
|
||||||
#define INVALIDATE_ON_VSYNC 1
|
#define INVALIDATE_ON_VSYNC 1
|
||||||
|
|
||||||
|
void MessageQueue::invalidateTransactionNow() {
|
||||||
|
mHandler->dispatchTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
void MessageQueue::invalidate() {
|
void MessageQueue::invalidate() {
|
||||||
#if INVALIDATE_ON_VSYNC
|
#if INVALIDATE_ON_VSYNC
|
||||||
mEvents->requestNextVsync();
|
mEvents->requestNextVsync();
|
||||||
|
@ -62,8 +62,9 @@ private:
|
|||||||
class MessageQueue {
|
class MessageQueue {
|
||||||
class Handler : public MessageHandler {
|
class Handler : public MessageHandler {
|
||||||
enum {
|
enum {
|
||||||
eventMaskInvalidate = 0x1,
|
eventMaskInvalidate = 0x1,
|
||||||
eventMaskRefresh = 0x2
|
eventMaskRefresh = 0x2,
|
||||||
|
eventMaskTransaction = 0x4
|
||||||
};
|
};
|
||||||
MessageQueue& mQueue;
|
MessageQueue& mQueue;
|
||||||
int32_t mEventMask;
|
int32_t mEventMask;
|
||||||
@ -72,6 +73,7 @@ class MessageQueue {
|
|||||||
virtual void handleMessage(const Message& message);
|
virtual void handleMessage(const Message& message);
|
||||||
void dispatchRefresh();
|
void dispatchRefresh();
|
||||||
void dispatchInvalidate();
|
void dispatchInvalidate();
|
||||||
|
void dispatchTransaction();
|
||||||
};
|
};
|
||||||
|
|
||||||
friend class Handler;
|
friend class Handler;
|
||||||
@ -89,8 +91,9 @@ class MessageQueue {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
enum {
|
enum {
|
||||||
INVALIDATE = 0,
|
INVALIDATE = 0,
|
||||||
REFRESH = 1,
|
REFRESH = 1,
|
||||||
|
TRANSACTION = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
MessageQueue();
|
MessageQueue();
|
||||||
@ -100,8 +103,13 @@ public:
|
|||||||
|
|
||||||
void waitMessage();
|
void waitMessage();
|
||||||
status_t postMessage(const sp<MessageBase>& message, nsecs_t reltime=0);
|
status_t postMessage(const sp<MessageBase>& message, nsecs_t reltime=0);
|
||||||
|
|
||||||
|
// sends INVALIDATE message at next VSYNC
|
||||||
void invalidate();
|
void invalidate();
|
||||||
|
// sends REFRESH message at next VSYNC
|
||||||
void refresh();
|
void refresh();
|
||||||
|
// sends TRANSACTION message immediately
|
||||||
|
void invalidateTransactionNow();
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
@ -744,6 +744,9 @@ void SurfaceFlinger::eventControl(int disp, int event, int enabled) {
|
|||||||
void SurfaceFlinger::onMessageReceived(int32_t what) {
|
void SurfaceFlinger::onMessageReceived(int32_t what) {
|
||||||
ATRACE_CALL();
|
ATRACE_CALL();
|
||||||
switch (what) {
|
switch (what) {
|
||||||
|
case MessageQueue::TRANSACTION:
|
||||||
|
handleMessageTransaction();
|
||||||
|
break;
|
||||||
case MessageQueue::INVALIDATE:
|
case MessageQueue::INVALIDATE:
|
||||||
handleMessageTransaction();
|
handleMessageTransaction();
|
||||||
handleMessageInvalidate();
|
handleMessageInvalidate();
|
||||||
@ -2626,6 +2629,13 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// make sure to process transactions before screenshots -- a transaction
|
||||||
|
// might already be pending but scheduled for VSYNC; this guarantees we
|
||||||
|
// will handle it before the screenshot. When VSYNC finally arrives
|
||||||
|
// the scheduled transaction will be a no-op. If no transactions are
|
||||||
|
// scheduled at this time, this will end-up being a no-op as well.
|
||||||
|
mEventQueue.invalidateTransactionNow();
|
||||||
|
|
||||||
sp<MessageBase> msg = new MessageCaptureScreen(this,
|
sp<MessageBase> msg = new MessageCaptureScreen(this,
|
||||||
display, producer, reqWidth, reqHeight, minLayerZ, maxLayerZ,
|
display, producer, reqWidth, reqHeight, minLayerZ, maxLayerZ,
|
||||||
isCpuConsumer);
|
isCpuConsumer);
|
||||||
|
Loading…
Reference in New Issue
Block a user