Merge "separate transactions from updates"
This commit is contained in:
commit
064b68d1bc
@ -95,6 +95,8 @@ public:
|
||||
* should be destroyed and getEvents() shouldn't be called again.
|
||||
*/
|
||||
ssize_t getEvents(Event* events, size_t count);
|
||||
static ssize_t getEvents(const sp<BitTube>& dataChannel,
|
||||
Event* events, size_t count);
|
||||
|
||||
/*
|
||||
* setVsyncRate() sets the Event::VSync delivery rate. A value of
|
||||
|
@ -80,7 +80,13 @@ status_t DisplayEventReceiver::requestNextVsync() {
|
||||
|
||||
ssize_t DisplayEventReceiver::getEvents(DisplayEventReceiver::Event* events,
|
||||
size_t count) {
|
||||
ssize_t size = mDataChannel->read(events, sizeof(events[0])*count);
|
||||
return DisplayEventReceiver::getEvents(mDataChannel, events, count);
|
||||
}
|
||||
|
||||
ssize_t DisplayEventReceiver::getEvents(const sp<BitTube>& dataChannel,
|
||||
Event* events, size_t count)
|
||||
{
|
||||
ssize_t size = dataChannel->read(events, sizeof(events[0])*count);
|
||||
ALOGE_IF(size<0,
|
||||
"DisplayEventReceiver::getEvents error (%s)",
|
||||
strerror(-size));
|
||||
|
@ -32,7 +32,6 @@ ifeq ($(TARGET_BOARD_PLATFORM), omap3)
|
||||
endif
|
||||
ifeq ($(TARGET_BOARD_PLATFORM), omap4)
|
||||
LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY
|
||||
LOCAL_CFLAGS += -DUSE_TRIPLE_BUFFERING=1
|
||||
endif
|
||||
ifeq ($(TARGET_BOARD_PLATFORM), s5pc110)
|
||||
LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY -DNEVER_DEFAULT_TO_ASYNC_MODE
|
||||
|
@ -55,6 +55,7 @@ Layer::Layer(SurfaceFlinger* flinger,
|
||||
mCurrentTransform(0),
|
||||
mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
|
||||
mCurrentOpacity(true),
|
||||
mRefreshPending(0),
|
||||
mFrameLatencyNeeded(false),
|
||||
mFrameLatencyOffset(0),
|
||||
mFormat(PIXEL_FORMAT_NONE),
|
||||
@ -97,12 +98,7 @@ void Layer::onFirstRef()
|
||||
mSurfaceTexture = new SurfaceTextureLayer(mTextureName, this);
|
||||
mSurfaceTexture->setFrameAvailableListener(new FrameQueuedListener(this));
|
||||
mSurfaceTexture->setSynchronousMode(true);
|
||||
#ifdef USE_TRIPLE_BUFFERING
|
||||
#warning "using triple buffering"
|
||||
mSurfaceTexture->setBufferCountServer(3);
|
||||
#else
|
||||
mSurfaceTexture->setBufferCountServer(2);
|
||||
#endif
|
||||
}
|
||||
|
||||
Layer::~Layer()
|
||||
@ -113,7 +109,7 @@ Layer::~Layer()
|
||||
|
||||
void Layer::onFrameQueued() {
|
||||
android_atomic_inc(&mQueuedFrames);
|
||||
mFlinger->signalEvent();
|
||||
mFlinger->signalLayerUpdate();
|
||||
}
|
||||
|
||||
// called with SurfaceFlinger::mStateLock as soon as the layer is entered
|
||||
@ -407,16 +403,37 @@ bool Layer::isCropped() const {
|
||||
// pageflip handling...
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool Layer::onPreComposition()
|
||||
{
|
||||
// if there was more than one pending update, request a refresh
|
||||
if (mRefreshPending >= 2) {
|
||||
mRefreshPending = 0;
|
||||
return true;
|
||||
}
|
||||
mRefreshPending = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
void Layer::lockPageFlip(bool& recomputeVisibleRegions)
|
||||
{
|
||||
if (mQueuedFrames > 0) {
|
||||
|
||||
// if we've already called updateTexImage() without going through
|
||||
// a composition step, we have to skip this layer at this point
|
||||
// because we cannot call updateTeximage() without a corresponding
|
||||
// compositionComplete() call.
|
||||
// we'll trigger an update in onPreComposition().
|
||||
if (mRefreshPending++) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Capture the old state of the layer for comparisons later
|
||||
const bool oldOpacity = isOpaque();
|
||||
sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;
|
||||
|
||||
// signal another event if we have more frames pending
|
||||
if (android_atomic_dec(&mQueuedFrames) > 1) {
|
||||
mFlinger->signalEvent();
|
||||
mFlinger->signalLayerUpdate();
|
||||
}
|
||||
|
||||
if (mSurfaceTexture->updateTexImage() < NO_ERROR) {
|
||||
@ -519,6 +536,10 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)
|
||||
void Layer::unlockPageFlip(
|
||||
const Transform& planeTransform, Region& outDirtyRegion)
|
||||
{
|
||||
if (mRefreshPending >= 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
Region dirtyRegion(mPostedDirtyRegion);
|
||||
if (!dirtyRegion.isEmpty()) {
|
||||
mPostedDirtyRegion.clear();
|
||||
@ -552,9 +573,9 @@ void Layer::dump(String8& result, char* buffer, size_t SIZE) const
|
||||
snprintf(buffer, SIZE,
|
||||
" "
|
||||
"format=%2d, activeBuffer=[%4ux%4u:%4u,%3X],"
|
||||
" transform-hint=0x%02x, queued-frames=%d\n",
|
||||
" transform-hint=0x%02x, queued-frames=%d, mRefreshPending=%d\n",
|
||||
mFormat, w0, h0, s0,f0,
|
||||
getTransformHint(), mQueuedFrames);
|
||||
getTransformHint(), mQueuedFrames, mRefreshPending);
|
||||
|
||||
result.append(buffer);
|
||||
|
||||
|
@ -80,6 +80,7 @@ public:
|
||||
virtual wp<IBinder> getSurfaceTextureBinder() const;
|
||||
|
||||
virtual void onLayerDisplayed();
|
||||
virtual bool onPreComposition();
|
||||
|
||||
// only for debugging
|
||||
inline const sp<GraphicBuffer>& getActiveBuffer() const { return mActiveBuffer; }
|
||||
@ -115,14 +116,17 @@ private:
|
||||
uint32_t mCurrentTransform;
|
||||
uint32_t mCurrentScalingMode;
|
||||
bool mCurrentOpacity;
|
||||
size_t mRefreshPending;
|
||||
bool mFrameLatencyNeeded;
|
||||
int mFrameLatencyOffset;
|
||||
|
||||
struct Statistics {
|
||||
Statistics() : timestamp(0), set(0), vsync(0) { }
|
||||
nsecs_t timestamp; // buffer timestamp
|
||||
nsecs_t set; // buffer displayed timestamp
|
||||
nsecs_t vsync; // vsync immediately before set
|
||||
};
|
||||
|
||||
// protected by mLock
|
||||
Statistics mFrameStats[128];
|
||||
|
||||
|
@ -47,8 +47,7 @@ LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display)
|
||||
mOrientation(0),
|
||||
mPlaneOrientation(0),
|
||||
mTransactionFlags(0),
|
||||
mPremultipliedAlpha(true), mName("unnamed"), mDebug(false),
|
||||
mInvalidate(0)
|
||||
mPremultipliedAlpha(true), mName("unnamed"), mDebug(false)
|
||||
{
|
||||
const DisplayHardware& hw(flinger->graphicPlane(0).displayHardware());
|
||||
mFlags = hw.getFlags();
|
||||
@ -262,23 +261,11 @@ void LayerBase::validateVisibility(const Transform& planeTransform)
|
||||
mTransformedBounds = tr.makeBounds(w, h);
|
||||
}
|
||||
|
||||
void LayerBase::lockPageFlip(bool& recomputeVisibleRegions)
|
||||
{
|
||||
void LayerBase::lockPageFlip(bool& recomputeVisibleRegions) {
|
||||
}
|
||||
|
||||
void LayerBase::unlockPageFlip(
|
||||
const Transform& planeTransform, Region& outDirtyRegion)
|
||||
{
|
||||
if ((android_atomic_and(~1, &mInvalidate)&1) == 1) {
|
||||
outDirtyRegion.orSelf(visibleRegionScreen);
|
||||
}
|
||||
}
|
||||
|
||||
void LayerBase::invalidate()
|
||||
{
|
||||
if ((android_atomic_or(1, &mInvalidate)&1) == 0) {
|
||||
mFlinger->signalEvent();
|
||||
}
|
||||
const Transform& planeTransform, Region& outDirtyRegion) {
|
||||
}
|
||||
|
||||
void LayerBase::drawRegion(const Region& reg) const
|
||||
|
@ -103,8 +103,6 @@ public:
|
||||
Rect visibleBounds() const;
|
||||
void drawRegion(const Region& reg) const;
|
||||
|
||||
void invalidate();
|
||||
|
||||
virtual sp<LayerBaseClient> getLayerBaseClient() const { return 0; }
|
||||
virtual sp<Layer> getLayer() const { return 0; }
|
||||
|
||||
@ -204,9 +202,16 @@ public:
|
||||
|
||||
/** called with the state lock when the surface is removed from the
|
||||
* current list */
|
||||
virtual void onRemoved() { };
|
||||
virtual void onRemoved() { }
|
||||
|
||||
virtual void onLayerDisplayed() { };
|
||||
/** called after page-flip
|
||||
*/
|
||||
virtual void onLayerDisplayed() { }
|
||||
|
||||
/** called before composition.
|
||||
* returns true if the layer has pending updates.
|
||||
*/
|
||||
virtual bool onPreComposition() { return false; }
|
||||
|
||||
/** always call base class first */
|
||||
virtual void dump(String8& result, char* scratch, size_t size) const;
|
||||
@ -275,10 +280,6 @@ protected:
|
||||
mutable bool mDebug;
|
||||
|
||||
|
||||
// atomic
|
||||
volatile int32_t mInvalidate;
|
||||
|
||||
|
||||
public:
|
||||
// called from class SurfaceFlinger
|
||||
virtual ~LayerBase();
|
||||
|
@ -29,6 +29,7 @@
|
||||
|
||||
#include "MessageQueue.h"
|
||||
#include "EventThread.h"
|
||||
#include "SurfaceFlinger.h"
|
||||
|
||||
namespace android {
|
||||
|
||||
@ -48,14 +49,47 @@ void MessageBase::handleMessage(const Message&) {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
void MessageQueue::Handler::signalRefresh() {
|
||||
if ((android_atomic_or(eventMaskRefresh, &mEventMask) & eventMaskRefresh) == 0) {
|
||||
mQueue.mLooper->sendMessage(this, Message(MessageQueue::REFRESH));
|
||||
}
|
||||
}
|
||||
|
||||
void MessageQueue::Handler::signalInvalidate() {
|
||||
if ((android_atomic_or(eventMaskInvalidate, &mEventMask) & eventMaskInvalidate) == 0) {
|
||||
mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE));
|
||||
}
|
||||
}
|
||||
|
||||
void MessageQueue::Handler::handleMessage(const Message& message) {
|
||||
switch (message.what) {
|
||||
case INVALIDATE:
|
||||
android_atomic_and(~eventMaskInvalidate, &mEventMask);
|
||||
mQueue.mFlinger->onMessageReceived(message.what);
|
||||
break;
|
||||
case REFRESH:
|
||||
android_atomic_and(~eventMaskRefresh, &mEventMask);
|
||||
mQueue.mFlinger->onMessageReceived(message.what);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
MessageQueue::MessageQueue()
|
||||
: mLooper(new Looper(true)), mWorkPending(0)
|
||||
{
|
||||
}
|
||||
|
||||
MessageQueue::~MessageQueue() {
|
||||
}
|
||||
|
||||
void MessageQueue::init(const sp<SurfaceFlinger>& flinger)
|
||||
{
|
||||
mFlinger = flinger;
|
||||
mLooper = new Looper(true);
|
||||
mHandler = new Handler(*this);
|
||||
}
|
||||
|
||||
void MessageQueue::setEventThread(const sp<EventThread>& eventThread)
|
||||
{
|
||||
mEventThread = eventThread;
|
||||
@ -68,25 +102,16 @@ void MessageQueue::setEventThread(const sp<EventThread>& eventThread)
|
||||
void MessageQueue::waitMessage() {
|
||||
do {
|
||||
IPCThreadState::self()->flushCommands();
|
||||
|
||||
int32_t ret = mLooper->pollOnce(-1);
|
||||
switch (ret) {
|
||||
case ALOOPER_POLL_WAKE:
|
||||
case ALOOPER_POLL_CALLBACK:
|
||||
// callback and/or wake
|
||||
if (android_atomic_and(0, &mWorkPending)) {
|
||||
return;
|
||||
}
|
||||
continue;
|
||||
|
||||
case ALOOPER_POLL_ERROR:
|
||||
ALOGE("ALOOPER_POLL_ERROR");
|
||||
case ALOOPER_POLL_TIMEOUT:
|
||||
// timeout (should not happen)
|
||||
continue;
|
||||
|
||||
case ALOOPER_POLL_ERROR:
|
||||
ALOGE("ALOOPER_POLL_ERROR");
|
||||
continue;
|
||||
|
||||
default:
|
||||
// should not happen
|
||||
ALOGE("Looper::pollOnce() returned unknown status %d", ret);
|
||||
@ -107,15 +132,12 @@ status_t MessageQueue::postMessage(
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
void MessageQueue::scheduleWorkASAP() {
|
||||
if (android_atomic_or(1, &mWorkPending) == 0) {
|
||||
mLooper->wake();
|
||||
}
|
||||
void MessageQueue::invalidate() {
|
||||
mHandler->signalInvalidate();
|
||||
}
|
||||
|
||||
status_t MessageQueue::invalidate() {
|
||||
void MessageQueue::refresh() {
|
||||
mEvents->requestNextVsync();
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {
|
||||
@ -126,10 +148,10 @@ int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {
|
||||
int MessageQueue::eventReceiver(int fd, int events) {
|
||||
ssize_t n;
|
||||
DisplayEventReceiver::Event buffer[8];
|
||||
while ((n = getEvents(buffer, 8)) > 0) {
|
||||
while ((n = DisplayEventReceiver::getEvents(mEventTube, buffer, 8)) > 0) {
|
||||
for (int i=0 ; i<n ; i++) {
|
||||
if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
|
||||
scheduleWorkASAP();
|
||||
mHandler->signalRefresh();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -137,24 +159,6 @@ int MessageQueue::eventReceiver(int fd, int events) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
ssize_t MessageQueue::getEvents(
|
||||
DisplayEventReceiver::Event* events, size_t count)
|
||||
{
|
||||
ssize_t size = mEventTube->read(events, sizeof(events[0])*count);
|
||||
ALOGE_IF(size<0, "MessageQueue::getEvents error (%s)", strerror(-size));
|
||||
if (size >= 0) {
|
||||
// Note: if (size % sizeof(events[0])) != 0, we've got a
|
||||
// partial read. This can happen if the queue filed up (ie: if we
|
||||
// didn't pull from it fast enough).
|
||||
// We discard the partial event and rely on the sender to
|
||||
// re-send the event if appropriate (some events, like VSYNC
|
||||
// can be lost forever).
|
||||
// returns number of events read
|
||||
size /= sizeof(events[0]);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
}; // namespace android
|
||||
|
@ -33,6 +33,7 @@ namespace android {
|
||||
|
||||
class IDisplayEventConnection;
|
||||
class EventThread;
|
||||
class SurfaceFlinger;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@ -59,25 +60,48 @@ private:
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class MessageQueue {
|
||||
class Handler : public MessageHandler {
|
||||
enum {
|
||||
eventMaskInvalidate = 0x1,
|
||||
eventMaskRefresh = 0x2
|
||||
};
|
||||
MessageQueue& mQueue;
|
||||
int32_t mEventMask;
|
||||
public:
|
||||
Handler(MessageQueue& queue) : mQueue(queue), mEventMask(0) { }
|
||||
virtual void handleMessage(const Message& message);
|
||||
void signalRefresh();
|
||||
void signalInvalidate();
|
||||
};
|
||||
|
||||
friend class Handler;
|
||||
|
||||
sp<SurfaceFlinger> mFlinger;
|
||||
sp<Looper> mLooper;
|
||||
sp<EventThread> mEventThread;
|
||||
sp<IDisplayEventConnection> mEvents;
|
||||
sp<BitTube> mEventTube;
|
||||
int32_t mWorkPending;
|
||||
sp<Handler> mHandler;
|
||||
|
||||
|
||||
static int cb_eventReceiver(int fd, int events, void* data);
|
||||
int eventReceiver(int fd, int events);
|
||||
ssize_t getEvents(DisplayEventReceiver::Event* events, size_t count);
|
||||
void scheduleWorkASAP();
|
||||
|
||||
public:
|
||||
enum {
|
||||
INVALIDATE = 0,
|
||||
REFRESH = 1,
|
||||
};
|
||||
|
||||
MessageQueue();
|
||||
~MessageQueue();
|
||||
void init(const sp<SurfaceFlinger>& flinger);
|
||||
void setEventThread(const sp<EventThread>& events);
|
||||
|
||||
void waitMessage();
|
||||
status_t postMessage(const sp<MessageBase>& message, nsecs_t reltime=0);
|
||||
status_t invalidate();
|
||||
void invalidate();
|
||||
void refresh();
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
@ -125,11 +125,34 @@ void SurfaceFlinger::init()
|
||||
ALOGI_IF(mDebugDDMS, "DDMS debugging enabled");
|
||||
}
|
||||
|
||||
void SurfaceFlinger::onFirstRef()
|
||||
{
|
||||
mEventQueue.init(this);
|
||||
|
||||
run("SurfaceFlinger", PRIORITY_URGENT_DISPLAY);
|
||||
|
||||
// Wait for the main thread to be done with its initialization
|
||||
mReadyToRunBarrier.wait();
|
||||
}
|
||||
|
||||
|
||||
SurfaceFlinger::~SurfaceFlinger()
|
||||
{
|
||||
glDeleteTextures(1, &mWormholeTexName);
|
||||
}
|
||||
|
||||
void SurfaceFlinger::binderDied(const wp<IBinder>& who)
|
||||
{
|
||||
// the window manager died on us. prepare its eulogy.
|
||||
|
||||
// reset screen orientation
|
||||
Vector<ComposerState> state;
|
||||
setTransactionState(state, eOrientationDefault, 0);
|
||||
|
||||
// restart the boot-animation
|
||||
property_set("ctl.start", "bootanim");
|
||||
}
|
||||
|
||||
sp<IMemoryHeap> SurfaceFlinger::getCblk() const
|
||||
{
|
||||
return mServerHeap;
|
||||
@ -183,26 +206,6 @@ void SurfaceFlinger::bootFinished()
|
||||
property_set("ctl.stop", "bootanim");
|
||||
}
|
||||
|
||||
void SurfaceFlinger::binderDied(const wp<IBinder>& who)
|
||||
{
|
||||
// the window manager died on us. prepare its eulogy.
|
||||
|
||||
// reset screen orientation
|
||||
Vector<ComposerState> state;
|
||||
setTransactionState(state, eOrientationDefault, 0);
|
||||
|
||||
// restart the boot-animation
|
||||
property_set("ctl.start", "bootanim");
|
||||
}
|
||||
|
||||
void SurfaceFlinger::onFirstRef()
|
||||
{
|
||||
run("SurfaceFlinger", PRIORITY_URGENT_DISPLAY);
|
||||
|
||||
// Wait for the main thread to be done with its initialization
|
||||
mReadyToRunBarrier.wait();
|
||||
}
|
||||
|
||||
static inline uint16_t pack565(int r, int g, int b) {
|
||||
return (r<<11)|(g<<5)|b;
|
||||
}
|
||||
@ -310,34 +313,6 @@ status_t SurfaceFlinger::readyToRun()
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
#if 0
|
||||
#pragma mark -
|
||||
#pragma mark Events Handler
|
||||
#endif
|
||||
|
||||
void SurfaceFlinger::waitForEvent() {
|
||||
mEventQueue.waitMessage();
|
||||
}
|
||||
|
||||
void SurfaceFlinger::signalEvent() {
|
||||
mEventQueue.invalidate();
|
||||
}
|
||||
|
||||
status_t SurfaceFlinger::postMessageAsync(const sp<MessageBase>& msg,
|
||||
nsecs_t reltime, uint32_t flags) {
|
||||
return mEventQueue.postMessage(msg, reltime);
|
||||
}
|
||||
|
||||
status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg,
|
||||
nsecs_t reltime, uint32_t flags) {
|
||||
status_t res = mEventQueue.postMessage(msg, reltime);
|
||||
if (res == NO_ERROR) {
|
||||
msg->wait();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool SurfaceFlinger::authenticateSurfaceTexture(
|
||||
@ -388,54 +363,93 @@ sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection() {
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
#if 0
|
||||
#pragma mark -
|
||||
#pragma mark Main loop
|
||||
#endif
|
||||
|
||||
void SurfaceFlinger::waitForEvent() {
|
||||
mEventQueue.waitMessage();
|
||||
}
|
||||
|
||||
void SurfaceFlinger::signalTransaction() {
|
||||
mEventQueue.invalidate();
|
||||
}
|
||||
|
||||
void SurfaceFlinger::signalLayerUpdate() {
|
||||
mEventQueue.invalidate();
|
||||
}
|
||||
|
||||
void SurfaceFlinger::signalRefresh() {
|
||||
mEventQueue.refresh();
|
||||
}
|
||||
|
||||
status_t SurfaceFlinger::postMessageAsync(const sp<MessageBase>& msg,
|
||||
nsecs_t reltime, uint32_t flags) {
|
||||
return mEventQueue.postMessage(msg, reltime);
|
||||
}
|
||||
|
||||
status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg,
|
||||
nsecs_t reltime, uint32_t flags) {
|
||||
status_t res = mEventQueue.postMessage(msg, reltime);
|
||||
if (res == NO_ERROR) {
|
||||
msg->wait();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool SurfaceFlinger::threadLoop()
|
||||
{
|
||||
waitForEvent();
|
||||
|
||||
// check for transactions
|
||||
if (CC_UNLIKELY(mConsoleSignals)) {
|
||||
handleConsoleEvents();
|
||||
}
|
||||
|
||||
// if we're in a global transaction, don't do anything.
|
||||
const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
|
||||
uint32_t transactionFlags = peekTransactionFlags(mask);
|
||||
if (CC_UNLIKELY(transactionFlags)) {
|
||||
handleTransaction(transactionFlags);
|
||||
}
|
||||
|
||||
// post surfaces (if needed)
|
||||
handlePageFlip();
|
||||
|
||||
if (mDirtyRegion.isEmpty()) {
|
||||
// nothing new to do.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (CC_UNLIKELY(mHwWorkListDirty)) {
|
||||
// build the h/w work list
|
||||
handleWorkList();
|
||||
}
|
||||
|
||||
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
||||
if (CC_LIKELY(hw.canDraw())) {
|
||||
// repaint the framebuffer (if needed)
|
||||
handleRepaint();
|
||||
// inform the h/w that we're done compositing
|
||||
hw.compositionComplete();
|
||||
postFramebuffer();
|
||||
} else {
|
||||
// pretend we did the post
|
||||
hw.compositionComplete();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void SurfaceFlinger::onMessageReceived(int32_t what)
|
||||
{
|
||||
switch (what) {
|
||||
case MessageQueue::INVALIDATE: {
|
||||
// check for transactions
|
||||
if (CC_UNLIKELY(mConsoleSignals)) {
|
||||
handleConsoleEvents();
|
||||
}
|
||||
|
||||
// if we're in a global transaction, don't do anything.
|
||||
const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
|
||||
uint32_t transactionFlags = peekTransactionFlags(mask);
|
||||
if (CC_UNLIKELY(transactionFlags)) {
|
||||
handleTransaction(transactionFlags);
|
||||
}
|
||||
|
||||
// post surfaces (if needed)
|
||||
handlePageFlip();
|
||||
|
||||
if (!mDirtyRegion.isEmpty()) {
|
||||
signalRefresh();
|
||||
}
|
||||
} break;
|
||||
|
||||
case MessageQueue::REFRESH: {
|
||||
if (!mDirtyRegion.isEmpty()) {
|
||||
// NOTE: it is mandatory to call hw.compositionComplete()
|
||||
// after handleRefresh()
|
||||
handleRefresh();
|
||||
|
||||
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
||||
if (CC_UNLIKELY(mHwWorkListDirty)) {
|
||||
// build the h/w work list
|
||||
handleWorkList();
|
||||
}
|
||||
if (CC_LIKELY(hw.canDraw())) {
|
||||
// repaint the framebuffer (if needed)
|
||||
handleRepaint();
|
||||
// inform the h/w that we're done compositing
|
||||
hw.compositionComplete();
|
||||
postFramebuffer();
|
||||
} else {
|
||||
// pretend we did the post
|
||||
hw.compositionComplete();
|
||||
}
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void SurfaceFlinger::postFramebuffer()
|
||||
{
|
||||
// this should never happen. we do the flip anyways so we don't
|
||||
@ -717,13 +731,13 @@ void SurfaceFlinger::commitTransaction()
|
||||
|
||||
void SurfaceFlinger::handlePageFlip()
|
||||
{
|
||||
bool visibleRegions = mVisibleRegionsDirty;
|
||||
const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
|
||||
visibleRegions |= lockPageFlip(currentLayers);
|
||||
const DisplayHardware& hw = graphicPlane(0).displayHardware();
|
||||
const Region screenRegion(hw.bounds());
|
||||
|
||||
const DisplayHardware& hw = graphicPlane(0).displayHardware();
|
||||
const Region screenRegion(hw.bounds());
|
||||
if (visibleRegions) {
|
||||
const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
|
||||
const bool visibleRegions = lockPageFlip(currentLayers);
|
||||
|
||||
if (visibleRegions || mVisibleRegionsDirty) {
|
||||
Region opaqueRegion;
|
||||
computeVisibleRegions(currentLayers, mDirtyRegion, opaqueRegion);
|
||||
|
||||
@ -770,7 +784,7 @@ void SurfaceFlinger::unlockPageFlip(const LayerVector& currentLayers)
|
||||
{
|
||||
const GraphicPlane& plane(graphicPlane(0));
|
||||
const Transform& planeTransform(plane.transform());
|
||||
size_t count = currentLayers.size();
|
||||
const size_t count = currentLayers.size();
|
||||
sp<LayerBase> const* layers = currentLayers.array();
|
||||
for (size_t i=0 ; i<count ; i++) {
|
||||
const sp<LayerBase>& layer(layers[i]);
|
||||
@ -778,6 +792,23 @@ void SurfaceFlinger::unlockPageFlip(const LayerVector& currentLayers)
|
||||
}
|
||||
}
|
||||
|
||||
void SurfaceFlinger::handleRefresh()
|
||||
{
|
||||
bool needInvalidate = false;
|
||||
const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
|
||||
const size_t count = currentLayers.size();
|
||||
for (size_t i=0 ; i<count ; i++) {
|
||||
const sp<LayerBase>& layer(currentLayers[i]);
|
||||
if (layer->onPreComposition()) {
|
||||
needInvalidate = true;
|
||||
}
|
||||
}
|
||||
if (needInvalidate) {
|
||||
signalLayerUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SurfaceFlinger::handleWorkList()
|
||||
{
|
||||
mHwWorkListDirty = false;
|
||||
@ -1175,7 +1206,7 @@ uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags)
|
||||
{
|
||||
uint32_t old = android_atomic_or(flags, &mTransactionFlags);
|
||||
if ((old & flags)==0) { // wake the server up
|
||||
signalEvent();
|
||||
signalTransaction();
|
||||
}
|
||||
return old;
|
||||
}
|
||||
@ -1426,14 +1457,14 @@ void SurfaceFlinger::screenReleased(int dpy)
|
||||
{
|
||||
// this may be called by a signal handler, we can't do too much in here
|
||||
android_atomic_or(eConsoleReleased, &mConsoleSignals);
|
||||
signalEvent();
|
||||
signalTransaction();
|
||||
}
|
||||
|
||||
void SurfaceFlinger::screenAcquired(int dpy)
|
||||
{
|
||||
// this may be called by a signal handler, we can't do too much in here
|
||||
android_atomic_or(eConsoleAcquired, &mConsoleSignals);
|
||||
signalEvent();
|
||||
signalTransaction();
|
||||
}
|
||||
|
||||
status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
|
||||
@ -1769,7 +1800,7 @@ void SurfaceFlinger::repaintEverything() {
|
||||
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
||||
const Rect bounds(hw.getBounds());
|
||||
setInvalidateRegion(Region(bounds));
|
||||
signalEvent();
|
||||
signalTransaction();
|
||||
}
|
||||
|
||||
void SurfaceFlinger::setInvalidateRegion(const Region& reg) {
|
||||
@ -2245,7 +2276,7 @@ status_t SurfaceFlinger::turnElectronBeamOnImplLocked(int32_t mode)
|
||||
|
||||
// make sure to redraw the whole screen when the animation is done
|
||||
mDirtyRegion.set(hw.bounds());
|
||||
signalEvent();
|
||||
signalTransaction();
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
@ -190,6 +190,8 @@ public:
|
||||
status_t renderScreenToTextureLocked(DisplayID dpy,
|
||||
GLuint* textureName, GLfloat* uOut, GLfloat* vOut);
|
||||
|
||||
void onMessageReceived(int32_t what);
|
||||
|
||||
status_t postMessageAsync(const sp<MessageBase>& msg,
|
||||
nsecs_t reltime=0, uint32_t flags = 0);
|
||||
|
||||
@ -283,7 +285,10 @@ private:
|
||||
public: // hack to work around gcc 4.0.3 bug
|
||||
const GraphicPlane& graphicPlane(int dpy) const;
|
||||
GraphicPlane& graphicPlane(int dpy);
|
||||
void signalEvent();
|
||||
|
||||
void signalTransaction();
|
||||
void signalLayerUpdate();
|
||||
void signalRefresh();
|
||||
void repaintEverything();
|
||||
|
||||
private:
|
||||
@ -300,6 +305,7 @@ private:
|
||||
void handlePageFlip();
|
||||
bool lockPageFlip(const LayerVector& currentLayers);
|
||||
void unlockPageFlip(const LayerVector& currentLayers);
|
||||
void handleRefresh();
|
||||
void handleWorkList();
|
||||
void handleRepaint();
|
||||
void postFramebuffer();
|
||||
|
Loading…
Reference in New Issue
Block a user