SF now synchronizes to VSYNC
Change-Id: Ic5e4f2ea9927ce133eef9499c03161325e9d02c5
This commit is contained in:
parent
54d89516ef
commit
8aedd4737d
|
@ -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 \
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue