SF now synchronizes to VSYNC

Change-Id: Ic5e4f2ea9927ce133eef9499c03161325e9d02c5
This commit is contained in:
Mathias Agopian 2012-01-24 16:39:14 -08:00
parent 54d89516ef
commit 8aedd4737d
8 changed files with 120 additions and 14 deletions

View File

@ -23,18 +23,22 @@ LOCAL_SRC_FILES:= \
LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\"
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
ifeq ($(TARGET_HAS_WAITFORVSYNC), true)
LOCAL_CFLAGS += -DHAS_WAITFORVSYNC
endif
ifeq ($(TARGET_BOARD_PLATFORM), omap3)
LOCAL_CFLAGS += -DNO_RGBX_8888
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
LOCAL_CFLAGS += -DREFRESH_RATE=56
endif
LOCAL_SHARED_LIBRARIES := \
libcutils \
libhardware \

View File

@ -36,6 +36,7 @@ namespace android {
EventThread::EventThread(const sp<SurfaceFlinger>& flinger)
: mFlinger(flinger),
mHw(flinger->graphicPlane(0).displayHardware()),
mLastVSyncTimestamp(0),
mDeliveredEvents(0)
{
}
@ -44,6 +45,20 @@ void EventThread::onFirstRef() {
run("EventThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
}
sp<DisplayEventConnection> EventThread::createEventConnection() const {
return new DisplayEventConnection(const_cast<EventThread*>(this));
}
nsecs_t EventThread::getLastVSyncTimestamp() const {
Mutex::Autolock _l(mLock);
return mLastVSyncTimestamp;
}
nsecs_t EventThread::getVSyncPeriod() const {
return mHw.getRefreshPeriod();
}
status_t EventThread::registerDisplayEventConnection(
const sp<DisplayEventConnection>& connection) {
Mutex::Autolock _l(mLock);
@ -80,8 +95,11 @@ void EventThread::setVsyncRate(uint32_t count,
Mutex::Autolock _l(mLock);
ConnectionInfo* info = getConnectionInfoLocked(connection);
if (info) {
info->count = (count == 0) ? -1 : count;
mCondition.signal();
const int32_t new_count = (count == 0) ? -1 : count;
if (info->count != new_count) {
info->count = new_count;
mCondition.signal();
}
}
}
}
@ -90,10 +108,8 @@ void EventThread::requestNextVsync(
const wp<DisplayEventConnection>& connection) {
Mutex::Autolock _l(mLock);
ConnectionInfo* info = getConnectionInfoLocked(connection);
if (info) {
if (info->count < 0) {
info->count = 0;
}
if (info && info->count < 0) {
info->count = 0;
mCondition.signal();
}
}
@ -132,6 +148,7 @@ bool EventThread::threadLoop() {
timestamp = mHw.waitForRefresh();
mLock.lock();
mDeliveredEvents++;
mLastVSyncTimestamp = timestamp;
// now see if we still need to report this VSYNC event
bool reportVsync = false;

View File

@ -36,6 +36,7 @@ namespace android {
class SurfaceFlinger;
class DisplayHardware;
class DisplayEventConnection;
// ---------------------------------------------------------------------------
@ -45,6 +46,8 @@ class EventThread : public Thread {
public:
EventThread(const sp<SurfaceFlinger>& flinger);
sp<DisplayEventConnection> createEventConnection() const;
status_t registerDisplayEventConnection(
const sp<DisplayEventConnection>& connection);
@ -56,6 +59,10 @@ public:
void requestNextVsync(const wp<DisplayEventConnection>& connection);
nsecs_t getLastVSyncTimestamp() const;
nsecs_t getVSyncPeriod() const;
void dump(String8& result, char* buffer, size_t SIZE) const;
private:
@ -88,6 +95,7 @@ private:
// protected by mLock
KeyedVector< wp<DisplayEventConnection>, ConnectionInfo > mDisplayEventConnections;
nsecs_t mLastVSyncTimestamp;
// main thread only
size_t mDeliveredEvents;

View File

@ -97,7 +97,12 @@ 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()

View File

@ -18,12 +18,17 @@
#include <errno.h>
#include <sys/types.h>
#include <binder/IPCThreadState.h>
#include <utils/threads.h>
#include <utils/Timers.h>
#include <utils/Log.h>
#include <binder/IPCThreadState.h>
#include <gui/IDisplayEventConnection.h>
#include <gui/BitTube.h>
#include "MessageQueue.h"
#include "EventThread.h"
namespace android {
@ -51,6 +56,15 @@ MessageQueue::MessageQueue()
MessageQueue::~MessageQueue() {
}
void MessageQueue::setEventThread(const sp<EventThread>& eventThread)
{
mEventThread = eventThread;
mEvents = eventThread->createEventConnection();
mEventTube = mEvents->getDataChannel();
mLooper->addFd(mEventTube->getFd(), 0, ALOOPER_EVENT_INPUT,
MessageQueue::cb_eventReceiver, this);
}
void MessageQueue::waitMessage() {
do {
IPCThreadState::self()->flushCommands();
@ -93,13 +107,54 @@ status_t MessageQueue::postMessage(
return NO_ERROR;
}
status_t MessageQueue::invalidate() {
void MessageQueue::scheduleWorkASAP() {
if (android_atomic_or(1, &mWorkPending) == 0) {
mLooper->wake();
}
}
}
status_t MessageQueue::invalidate() {
mEvents->requestNextVsync();
return NO_ERROR;
}
int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {
MessageQueue* queue = reinterpret_cast<MessageQueue *>(data);
return queue->eventReceiver(fd, events);
}
int MessageQueue::eventReceiver(int fd, int events) {
ssize_t n;
DisplayEventReceiver::Event buffer[8];
while ((n = getEvents(buffer, 8)) > 0) {
for (int i=0 ; i<n ; i++) {
if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
scheduleWorkASAP();
break;
}
}
}
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

View File

@ -25,10 +25,15 @@
#include <utils/Timers.h>
#include <utils/Looper.h>
#include <gui/DisplayEventReceiver.h>
#include "Barrier.h"
namespace android {
class IDisplayEventConnection;
class EventThread;
// ---------------------------------------------------------------------------
class MessageBase : public MessageHandler
@ -55,11 +60,20 @@ private:
class MessageQueue {
sp<Looper> mLooper;
volatile int32_t mWorkPending;
sp<EventThread> mEventThread;
sp<IDisplayEventConnection> mEvents;
sp<BitTube> mEventTube;
int32_t mWorkPending;
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:
MessageQueue();
~MessageQueue();
void setEventThread(const sp<EventThread>& events);
void waitMessage();
status_t postMessage(const sp<MessageBase>& message, nsecs_t reltime=0);

View File

@ -296,6 +296,7 @@ status_t SurfaceFlinger::readyToRun()
// start the EventThread
mEventThread = new EventThread(this);
mEventQueue.setEventThread(mEventThread);
/*
* We're now ready to accept clients...
@ -383,8 +384,7 @@ bool SurfaceFlinger::authenticateSurfaceTexture(
// ----------------------------------------------------------------------------
sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection() {
sp<DisplayEventConnection> result(new DisplayEventConnection(mEventThread));
return result;
return mEventThread->createEventConnection();
}
// ----------------------------------------------------------------------------
@ -432,7 +432,6 @@ bool SurfaceFlinger::threadLoop()
} else {
// pretend we did the post
hw.compositionComplete();
hw.waitForRefresh();
}
return true;
}

View File

@ -94,6 +94,10 @@ status_t SurfaceTextureLayer::connect(int api,
*outTransform = orientation;
}
switch(api) {
case NATIVE_WINDOW_API_CPU:
// SurfaceTextureClient supports only 2 buffers for CPU connections
this->setBufferCountServer(2);
break;
case NATIVE_WINDOW_API_MEDIA:
case NATIVE_WINDOW_API_CAMERA:
// Camera preview and videos are rate-limited on the producer