summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/surfaceflinger/Android.mk7
-rw-r--r--services/surfaceflinger/DisplayHardware/DisplayHardware.cpp15
-rw-r--r--services/surfaceflinger/DisplayHardware/DisplayHardware.h5
-rw-r--r--services/surfaceflinger/EventThread.cpp41
-rw-r--r--services/surfaceflinger/EventThread.h8
-rw-r--r--services/surfaceflinger/Layer.cpp46
-rw-r--r--services/surfaceflinger/Layer.h18
-rw-r--r--services/surfaceflinger/LayerBase.cpp11
-rw-r--r--services/surfaceflinger/LayerBase.h6
-rw-r--r--services/surfaceflinger/MessageQueue.cpp61
-rw-r--r--services/surfaceflinger/MessageQueue.h16
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp314
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h8
-rw-r--r--services/surfaceflinger/SurfaceTextureLayer.cpp4
-rw-r--r--services/surfaceflinger/tests/vsync/vsync.cpp2
15 files changed, 408 insertions, 154 deletions
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 95d651a..fc211e5 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -23,18 +23,21 @@ 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 \
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index 438a6da..986aec5 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -350,15 +350,28 @@ uint32_t DisplayHardware::getPageFlipCount() const {
}
// this needs to be thread safe
-nsecs_t DisplayHardware::waitForVSync() const {
+nsecs_t DisplayHardware::waitForRefresh() const {
nsecs_t timestamp;
if (mVSync.wait(&timestamp) < 0) {
// vsync not supported!
usleep( getDelayToNextVSyncUs(&timestamp) );
}
+ mLastHwVSync = timestamp; // FIXME: Not thread safe
return timestamp;
}
+nsecs_t DisplayHardware::getRefreshTimestamp() const {
+ // this returns the last refresh timestamp.
+ // if the last one is not available, we estimate it based on
+ // the refresh period and whatever closest timestamp we have.
+ nsecs_t now = systemTime();
+ return now - ((now - mLastHwVSync) % mRefreshPeriod);
+}
+
+nsecs_t DisplayHardware::getRefreshPeriod() const {
+ return mRefreshPeriod;
+}
+
int32_t DisplayHardware::getDelayToNextVSyncUs(nsecs_t* timestamp) const {
Mutex::Autolock _l(mFakeVSyncMutex);
const nsecs_t period = mRefreshPeriod;
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.h b/services/surfaceflinger/DisplayHardware/DisplayHardware.h
index 77da272..02be4dc 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardware.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.h
@@ -76,7 +76,9 @@ public:
uint32_t getMaxViewportDims() const;
// waits for the next vsync and returns the timestamp of when it happened
- nsecs_t waitForVSync() const;
+ nsecs_t waitForRefresh() const;
+ nsecs_t getRefreshPeriod() const;
+ nsecs_t getRefreshTimestamp() const;
uint32_t getPageFlipCount() const;
EGLDisplay getEGLDisplay() const { return mDisplay; }
@@ -119,6 +121,7 @@ private:
mutable Mutex mFakeVSyncMutex;
mutable nsecs_t mNextFakeVSync;
nsecs_t mRefreshPeriod;
+ mutable nsecs_t mLastHwVSync;
HWComposer* mHwc;
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp
index 80ab519..af0da0b 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/EventThread.cpp
@@ -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();
}
}
@@ -129,14 +145,15 @@ bool EventThread::threadLoop() {
// at least one listener requested VSYNC
mLock.unlock();
- timestamp = mHw.waitForVSync();
+ timestamp = mHw.waitForRefresh();
mLock.lock();
mDeliveredEvents++;
+ mLastVSyncTimestamp = timestamp;
// now see if we still need to report this VSYNC event
- bool reportVsync = false;
- size_t count = mDisplayEventConnections.size();
+ const size_t count = mDisplayEventConnections.size();
for (size_t i=0 ; i<count ; i++) {
+ bool reportVsync = false;
const ConnectionInfo& info(
mDisplayEventConnections.valueAt(i));
if (info.count >= 1) {
@@ -157,11 +174,7 @@ bool EventThread::threadLoop() {
displayEventConnections.add(mDisplayEventConnections.keyAt(i));
}
}
-
- if (reportVsync) {
- break;
- }
- } while (true);
+ } while (!displayEventConnections.size());
// dispatch vsync events to listeners...
vsync.header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
diff --git a/services/surfaceflinger/EventThread.h b/services/surfaceflinger/EventThread.h
index 35bd299..3a3071e 100644
--- a/services/surfaceflinger/EventThread.h
+++ b/services/surfaceflinger/EventThread.h
@@ -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;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index d4c4b1f..9c04d59 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -38,6 +38,7 @@
#include "Layer.h"
#include "SurfaceFlinger.h"
#include "SurfaceTextureLayer.h"
+#include <math.h>
#define DEBUG_RESIZE 0
@@ -54,6 +55,8 @@ Layer::Layer(SurfaceFlinger* flinger,
mCurrentTransform(0),
mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
mCurrentOpacity(true),
+ mFrameLatencyNeeded(false),
+ mFrameLatencyOffset(0),
mFormat(PIXEL_FORMAT_NONE),
mGLExtensions(GLExtensions::getInstance()),
mOpaqueLayer(true),
@@ -65,6 +68,17 @@ Layer::Layer(SurfaceFlinger* flinger,
glGenTextures(1, &mTextureName);
}
+void Layer::onLayerDisplayed() {
+ if (mFrameLatencyNeeded) {
+ const DisplayHardware& hw(graphicPlane(0).displayHardware());
+ mFrameStats[mFrameLatencyOffset].timestamp = mSurfaceTexture->getTimestamp();
+ mFrameStats[mFrameLatencyOffset].set = systemTime();
+ mFrameStats[mFrameLatencyOffset].vsync = hw.getRefreshTimestamp();
+ mFrameLatencyOffset = (mFrameLatencyOffset + 1) % 128;
+ mFrameLatencyNeeded = false;
+ }
+}
+
void Layer::onFirstRef()
{
LayerBaseClient::onFirstRef();
@@ -83,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()
@@ -408,6 +427,7 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)
// update the active buffer
mActiveBuffer = mSurfaceTexture->getCurrentBuffer();
+ mFrameLatencyNeeded = true;
const Rect crop(mSurfaceTexture->getCurrentCrop());
const uint32_t transform(mSurfaceTexture->getCurrentTransform());
@@ -543,6 +563,32 @@ void Layer::dump(String8& result, char* buffer, size_t SIZE) const
}
}
+void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const
+{
+ LayerBaseClient::dumpStats(result, buffer, SIZE);
+ const size_t o = mFrameLatencyOffset;
+ const DisplayHardware& hw(graphicPlane(0).displayHardware());
+ const nsecs_t period = hw.getRefreshPeriod();
+ result.appendFormat("%lld\n", period);
+ for (size_t i=0 ; i<128 ; i++) {
+ const size_t index = (o+i) % 128;
+ const nsecs_t time_app = mFrameStats[index].timestamp;
+ const nsecs_t time_set = mFrameStats[index].set;
+ const nsecs_t time_vsync = mFrameStats[index].vsync;
+ result.appendFormat("%lld\t%lld\t%lld\n",
+ time_app,
+ time_vsync,
+ time_set);
+ }
+ result.append("\n");
+}
+
+void Layer::clearStats()
+{
+ LayerBaseClient::clearStats();
+ memset(mFrameStats, 0, sizeof(mFrameStats));
+}
+
uint32_t Layer::getEffectiveUsage(uint32_t usage) const
{
// TODO: should we do something special if mSecure is set?
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 2b9471b..2dd4da1 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -34,6 +34,7 @@
#include "LayerBase.h"
#include "SurfaceTextureLayer.h"
#include "Transform.h"
+#include <utils/Timers.h>
namespace android {
@@ -78,12 +79,16 @@ public:
// LayerBaseClient interface
virtual wp<IBinder> getSurfaceTextureBinder() const;
+ virtual void onLayerDisplayed();
+
// only for debugging
inline const sp<GraphicBuffer>& getActiveBuffer() const { return mActiveBuffer; }
protected:
virtual void onFirstRef();
virtual void dump(String8& result, char* scratch, size_t size) const;
+ virtual void dumpStats(String8& result, char* buffer, size_t SIZE) const;
+ virtual void clearStats();
private:
friend class SurfaceTextureLayer;
@@ -110,6 +115,16 @@ private:
uint32_t mCurrentTransform;
uint32_t mCurrentScalingMode;
bool mCurrentOpacity;
+ 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];
// constants
PixelFormat mFormat;
@@ -121,9 +136,6 @@ private:
bool mSecure; // no screenshots
bool mProtectedByApp; // application requires protected path to external sink
Region mPostedDirtyRegion;
-
- // binder thread, transaction thread
- mutable Mutex mLock;
};
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index 37879f1..d32fcdd 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -471,6 +471,9 @@ void LayerBase::drawWithOpenGL(const Region& clip) const
void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const
{
const Layer::State& s(drawingState());
+ s.transparentRegion.dump(result, "transparentRegion");
+ transparentRegionScreen.dump(result, "transparentRegionScreen");
+ visibleRegionScreen.dump(result, "visibleRegionScreen");
snprintf(buffer, SIZE,
"+ %s %p (%s)\n"
" "
@@ -486,11 +489,15 @@ void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const
result.append(buffer);
}
-void LayerBase::shortDump(String8& result, char* scratch, size_t size) const
-{
+void LayerBase::shortDump(String8& result, char* scratch, size_t size) const {
LayerBase::dump(result, scratch, size);
}
+void LayerBase::dumpStats(String8& result, char* scratch, size_t SIZE) const {
+}
+
+void LayerBase::clearStats() {
+}
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index 7f62145..6b62c9d 100644
--- a/services/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
@@ -205,10 +205,14 @@ public:
/** called with the state lock when the surface is removed from the
* current list */
virtual void onRemoved() { };
-
+
+ virtual void onLayerDisplayed() { };
+
/** always call base class first */
virtual void dump(String8& result, char* scratch, size_t size) const;
virtual void shortDump(String8& result, char* scratch, size_t size) const;
+ virtual void dumpStats(String8& result, char* buffer, size_t SIZE) const;
+ virtual void clearStats();
enum { // flags for doTransaction()
diff --git a/services/surfaceflinger/MessageQueue.cpp b/services/surfaceflinger/MessageQueue.cpp
index cbd530c..70711e7 100644
--- a/services/surfaceflinger/MessageQueue.cpp
+++ b/services/surfaceflinger/MessageQueue.cpp
@@ -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
diff --git a/services/surfaceflinger/MessageQueue.h b/services/surfaceflinger/MessageQueue.h
index 2317d81..5ea197d 100644
--- a/services/surfaceflinger/MessageQueue.h
+++ b/services/surfaceflinger/MessageQueue.h
@@ -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);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index af47402..ff70ec3 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -188,7 +188,8 @@ void SurfaceFlinger::binderDied(const wp<IBinder>& who)
// the window manager died on us. prepare its eulogy.
// reset screen orientation
- setOrientation(0, eOrientationDefault, 0);
+ Vector<ComposerState> state;
+ setTransactionState(state, eOrientationDefault, 0);
// restart the boot-animation
property_set("ctl.start", "bootanim");
@@ -295,6 +296,7 @@ status_t SurfaceFlinger::readyToRun()
// start the EventThread
mEventThread = new EventThread(this);
+ mEventQueue.setEventThread(mEventThread);
/*
* We're now ready to accept clients...
@@ -382,8 +384,7 @@ bool SurfaceFlinger::authenticateSurfaceTexture(
// ----------------------------------------------------------------------------
sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection() {
- sp<DisplayEventConnection> result(new DisplayEventConnection(mEventThread));
- return result;
+ return mEventThread->createEventConnection();
}
// ----------------------------------------------------------------------------
@@ -431,7 +432,6 @@ bool SurfaceFlinger::threadLoop()
} else {
// pretend we did the post
hw.compositionComplete();
- hw.waitForVSync();
}
return true;
}
@@ -445,6 +445,12 @@ void SurfaceFlinger::postFramebuffer()
const nsecs_t now = systemTime();
mDebugInSwapBuffers = now;
hw.flip(mSwapRegion);
+
+ size_t numLayers = mVisibleLayersSortedByZ.size();
+ for (size_t i = 0; i < numLayers; i++) {
+ mVisibleLayersSortedByZ[i]->onLayerDisplayed();
+ }
+
mLastSwapBufferTime = systemTime() - now;
mDebugInSwapBuffers = 0;
mSwapRegion.clear();
@@ -1219,26 +1225,6 @@ void SurfaceFlinger::setTransactionState(const Vector<ComposerState>& state,
}
}
-int SurfaceFlinger::setOrientation(DisplayID dpy,
- int orientation, uint32_t flags)
-{
- if (CC_UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
- return BAD_VALUE;
-
- Mutex::Autolock _l(mStateLock);
- if (mCurrentState.orientation != orientation) {
- if (uint32_t(orientation)<=eOrientation270 || orientation==42) {
- mCurrentState.orientationFlags = flags;
- mCurrentState.orientation = orientation;
- setTransactionFlags(eTransactionNeeded);
- mTransactionCV.wait(mStateLock);
- } else {
- orientation = BAD_VALUE;
- }
- }
- return orientation;
-}
-
sp<ISurface> SurfaceFlinger::createSurface(
ISurfaceComposerClient::surface_data_t* params,
const String8& name,
@@ -1463,14 +1449,6 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
IPCThreadState::self()->getCallingUid());
result.append(buffer);
} else {
-
- // figure out if we're stuck somewhere
- const nsecs_t now = systemTime();
- const nsecs_t inSwapBuffers(mDebugInSwapBuffers);
- const nsecs_t inTransaction(mDebugInTransaction);
- nsecs_t inSwapBuffersDuration = (inSwapBuffers) ? now-inSwapBuffers : 0;
- nsecs_t inTransactionDuration = (inTransaction) ? now-inTransaction : 0;
-
// Try to get the main lock, but don't insist if we can't
// (this would indicate SF is stuck, but we want to be able to
// print something in dumpsys).
@@ -1486,117 +1464,203 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
result.append(buffer);
}
- /*
- * Dump the visible layer list
- */
- const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
- const size_t count = currentLayers.size();
- snprintf(buffer, SIZE, "Visible layers (count = %d)\n", count);
- result.append(buffer);
- for (size_t i=0 ; i<count ; i++) {
- const sp<LayerBase>& layer(currentLayers[i]);
- layer->dump(result, buffer, SIZE);
- const Layer::State& s(layer->drawingState());
- s.transparentRegion.dump(result, "transparentRegion");
- layer->transparentRegionScreen.dump(result, "transparentRegionScreen");
- layer->visibleRegionScreen.dump(result, "visibleRegionScreen");
- }
+ bool dumpAll = true;
+ size_t index = 0;
+ size_t numArgs = args.size();
+ if (numArgs) {
+ dumpAll = false;
- /*
- * Dump the layers in the purgatory
- */
-
- const size_t purgatorySize = mLayerPurgatory.size();
- snprintf(buffer, SIZE, "Purgatory state (%d entries)\n", purgatorySize);
- result.append(buffer);
- for (size_t i=0 ; i<purgatorySize ; i++) {
- const sp<LayerBase>& layer(mLayerPurgatory.itemAt(i));
- layer->shortDump(result, buffer, SIZE);
- }
+ if ((index < numArgs) &&
+ (args[index] == String16("--list"))) {
+ index++;
+ listLayersLocked(args, index, result, buffer, SIZE);
+ }
- /*
- * Dump SurfaceFlinger global state
- */
+ if ((index < numArgs) &&
+ (args[index] == String16("--latency"))) {
+ index++;
+ dumpStatsLocked(args, index, result, buffer, SIZE);
+ }
- snprintf(buffer, SIZE, "SurfaceFlinger global state:\n");
- result.append(buffer);
+ if ((index < numArgs) &&
+ (args[index] == String16("--latency-clear"))) {
+ index++;
+ clearStatsLocked(args, index, result, buffer, SIZE);
+ }
+ }
- const GLExtensions& extensions(GLExtensions::getInstance());
- snprintf(buffer, SIZE, "GLES: %s, %s, %s\n",
- extensions.getVendor(),
- extensions.getRenderer(),
- extensions.getVersion());
- result.append(buffer);
+ if (dumpAll) {
+ dumpAllLocked(result, buffer, SIZE);
+ }
- snprintf(buffer, SIZE, "EGL : %s\n",
- eglQueryString(graphicPlane(0).getEGLDisplay(),
- EGL_VERSION_HW_ANDROID));
- result.append(buffer);
+ if (locked) {
+ mStateLock.unlock();
+ }
+ }
+ write(fd, result.string(), result.size());
+ return NO_ERROR;
+}
- snprintf(buffer, SIZE, "EXTS: %s\n", extensions.getExtension());
+void SurfaceFlinger::listLayersLocked(const Vector<String16>& args, size_t& index,
+ String8& result, char* buffer, size_t SIZE) const
+{
+ const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
+ const size_t count = currentLayers.size();
+ for (size_t i=0 ; i<count ; i++) {
+ const sp<LayerBase>& layer(currentLayers[i]);
+ snprintf(buffer, SIZE, "%s\n", layer->getName().string());
result.append(buffer);
+ }
+}
- mWormholeRegion.dump(result, "WormholeRegion");
- const DisplayHardware& hw(graphicPlane(0).displayHardware());
- snprintf(buffer, SIZE,
- " orientation=%d, canDraw=%d\n",
- mCurrentState.orientation, hw.canDraw());
- result.append(buffer);
- snprintf(buffer, SIZE,
- " last eglSwapBuffers() time: %f us\n"
- " last transaction time : %f us\n"
- " refresh-rate : %f fps\n"
- " x-dpi : %f\n"
- " y-dpi : %f\n",
- mLastSwapBufferTime/1000.0,
- mLastTransactionTime/1000.0,
- hw.getRefreshRate(),
- hw.getDpiX(),
- hw.getDpiY());
- result.append(buffer);
+void SurfaceFlinger::dumpStatsLocked(const Vector<String16>& args, size_t& index,
+ String8& result, char* buffer, size_t SIZE) const
+{
+ String8 name;
+ if (index < args.size()) {
+ name = String8(args[index]);
+ index++;
+ }
- if (inSwapBuffersDuration || !locked) {
- snprintf(buffer, SIZE, " eglSwapBuffers time: %f us\n",
- inSwapBuffersDuration/1000.0);
+ const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
+ const size_t count = currentLayers.size();
+ for (size_t i=0 ; i<count ; i++) {
+ const sp<LayerBase>& layer(currentLayers[i]);
+ if (name.isEmpty()) {
+ snprintf(buffer, SIZE, "%s\n", layer->getName().string());
result.append(buffer);
}
+ if (name.isEmpty() || (name == layer->getName())) {
+ layer->dumpStats(result, buffer, SIZE);
+ }
+ }
+}
- if (inTransactionDuration || !locked) {
- snprintf(buffer, SIZE, " transaction time: %f us\n",
- inTransactionDuration/1000.0);
- result.append(buffer);
+void SurfaceFlinger::clearStatsLocked(const Vector<String16>& args, size_t& index,
+ String8& result, char* buffer, size_t SIZE) const
+{
+ String8 name;
+ if (index < args.size()) {
+ name = String8(args[index]);
+ index++;
+ }
+
+ const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
+ const size_t count = currentLayers.size();
+ for (size_t i=0 ; i<count ; i++) {
+ const sp<LayerBase>& layer(currentLayers[i]);
+ if (name.isEmpty() || (name == layer->getName())) {
+ layer->clearStats();
}
+ }
+}
- /*
- * VSYNC state
- */
- mEventThread->dump(result, buffer, SIZE);
+void SurfaceFlinger::dumpAllLocked(
+ String8& result, char* buffer, size_t SIZE) const
+{
+ // figure out if we're stuck somewhere
+ const nsecs_t now = systemTime();
+ const nsecs_t inSwapBuffers(mDebugInSwapBuffers);
+ const nsecs_t inTransaction(mDebugInTransaction);
+ nsecs_t inSwapBuffersDuration = (inSwapBuffers) ? now-inSwapBuffers : 0;
+ nsecs_t inTransactionDuration = (inTransaction) ? now-inTransaction : 0;
- /*
- * Dump HWComposer state
- */
- HWComposer& hwc(hw.getHwComposer());
- snprintf(buffer, SIZE, "h/w composer state:\n");
- result.append(buffer);
- snprintf(buffer, SIZE, " h/w composer %s and %s\n",
- hwc.initCheck()==NO_ERROR ? "present" : "not present",
- (mDebugDisableHWC || mDebugRegion) ? "disabled" : "enabled");
- result.append(buffer);
- hwc.dump(result, buffer, SIZE, mVisibleLayersSortedByZ);
+ /*
+ * Dump the visible layer list
+ */
+ const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
+ const size_t count = currentLayers.size();
+ snprintf(buffer, SIZE, "Visible layers (count = %d)\n", count);
+ result.append(buffer);
+ for (size_t i=0 ; i<count ; i++) {
+ const sp<LayerBase>& layer(currentLayers[i]);
+ layer->dump(result, buffer, SIZE);
+ }
- /*
- * Dump gralloc state
- */
- const GraphicBufferAllocator& alloc(GraphicBufferAllocator::get());
- alloc.dump(result);
- hw.dump(result);
+ /*
+ * Dump the layers in the purgatory
+ */
- if (locked) {
- mStateLock.unlock();
- }
+ const size_t purgatorySize = mLayerPurgatory.size();
+ snprintf(buffer, SIZE, "Purgatory state (%d entries)\n", purgatorySize);
+ result.append(buffer);
+ for (size_t i=0 ; i<purgatorySize ; i++) {
+ const sp<LayerBase>& layer(mLayerPurgatory.itemAt(i));
+ layer->shortDump(result, buffer, SIZE);
}
- write(fd, result.string(), result.size());
- return NO_ERROR;
+
+ /*
+ * Dump SurfaceFlinger global state
+ */
+
+ snprintf(buffer, SIZE, "SurfaceFlinger global state:\n");
+ result.append(buffer);
+
+ const GLExtensions& extensions(GLExtensions::getInstance());
+ snprintf(buffer, SIZE, "GLES: %s, %s, %s\n",
+ extensions.getVendor(),
+ extensions.getRenderer(),
+ extensions.getVersion());
+ result.append(buffer);
+
+ snprintf(buffer, SIZE, "EGL : %s\n",
+ eglQueryString(graphicPlane(0).getEGLDisplay(),
+ EGL_VERSION_HW_ANDROID));
+ result.append(buffer);
+
+ snprintf(buffer, SIZE, "EXTS: %s\n", extensions.getExtension());
+ result.append(buffer);
+
+ mWormholeRegion.dump(result, "WormholeRegion");
+ const DisplayHardware& hw(graphicPlane(0).displayHardware());
+ snprintf(buffer, SIZE,
+ " orientation=%d, canDraw=%d\n",
+ mCurrentState.orientation, hw.canDraw());
+ result.append(buffer);
+ snprintf(buffer, SIZE,
+ " last eglSwapBuffers() time: %f us\n"
+ " last transaction time : %f us\n"
+ " refresh-rate : %f fps\n"
+ " x-dpi : %f\n"
+ " y-dpi : %f\n",
+ mLastSwapBufferTime/1000.0,
+ mLastTransactionTime/1000.0,
+ hw.getRefreshRate(),
+ hw.getDpiX(),
+ hw.getDpiY());
+ result.append(buffer);
+
+ snprintf(buffer, SIZE, " eglSwapBuffers time: %f us\n",
+ inSwapBuffersDuration/1000.0);
+ result.append(buffer);
+
+ snprintf(buffer, SIZE, " transaction time: %f us\n",
+ inTransactionDuration/1000.0);
+ result.append(buffer);
+
+ /*
+ * VSYNC state
+ */
+ mEventThread->dump(result, buffer, SIZE);
+
+ /*
+ * Dump HWComposer state
+ */
+ HWComposer& hwc(hw.getHwComposer());
+ snprintf(buffer, SIZE, "h/w composer state:\n");
+ result.append(buffer);
+ snprintf(buffer, SIZE, " h/w composer %s and %s\n",
+ hwc.initCheck()==NO_ERROR ? "present" : "not present",
+ (mDebugDisableHWC || mDebugRegion) ? "disabled" : "enabled");
+ result.append(buffer);
+ hwc.dump(result, buffer, SIZE, mVisibleLayersSortedByZ);
+
+ /*
+ * Dump gralloc state
+ */
+ const GraphicBufferAllocator& alloc(GraphicBufferAllocator::get());
+ alloc.dump(result);
+ hw.dump(result);
}
status_t SurfaceFlinger::onTransact(
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 7f6c90c..c24a9de 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -170,7 +170,6 @@ public:
virtual void bootFinished();
virtual void setTransactionState(const Vector<ComposerState>& state,
int orientation, uint32_t flags);
- virtual int setOrientation(DisplayID dpy, int orientation, uint32_t flags);
virtual bool authenticateSurfaceTexture(const sp<ISurfaceTexture>& surface) const;
virtual sp<IDisplayEventConnection> createDisplayEventConnection();
@@ -337,6 +336,13 @@ private:
void debugFlashRegions();
void drawWormhole() const;
+ void listLayersLocked(const Vector<String16>& args, size_t& index,
+ String8& result, char* buffer, size_t SIZE) const;
+ void dumpStatsLocked(const Vector<String16>& args, size_t& index,
+ String8& result, char* buffer, size_t SIZE) const;
+ void clearStatsLocked(const Vector<String16>& args, size_t& index,
+ String8& result, char* buffer, size_t SIZE) const;
+ void dumpAllLocked(String8& result, char* buffer, size_t SIZE) const;
mutable MessageQueue mEventQueue;
diff --git a/services/surfaceflinger/SurfaceTextureLayer.cpp b/services/surfaceflinger/SurfaceTextureLayer.cpp
index 259b937..49e8e63 100644
--- a/services/surfaceflinger/SurfaceTextureLayer.cpp
+++ b/services/surfaceflinger/SurfaceTextureLayer.cpp
@@ -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
diff --git a/services/surfaceflinger/tests/vsync/vsync.cpp b/services/surfaceflinger/tests/vsync/vsync.cpp
index 4f79080..b0d54c4 100644
--- a/services/surfaceflinger/tests/vsync/vsync.cpp
+++ b/services/surfaceflinger/tests/vsync/vsync.cpp
@@ -55,6 +55,8 @@ int main(int argc, char** argv)
loop->addFd(myDisplayEvent.getFd(), 0, ALOOPER_EVENT_INPUT, receiver,
&myDisplayEvent);
+ myDisplayEvent.setVsyncRate(1);
+
do {
//printf("about to poll...\n");
int32_t ret = loop->pollOnce(-1);