summaryrefslogtreecommitdiffstats
path: root/services/surfaceflinger
diff options
context:
space:
mode:
Diffstat (limited to 'services/surfaceflinger')
-rw-r--r--services/surfaceflinger/Android.mk16
-rw-r--r--services/surfaceflinger/DdmConnection.cpp4
-rw-r--r--services/surfaceflinger/DdmConnection.h3
-rw-r--r--services/surfaceflinger/DisplayHardware/HWComposer.cpp19
-rw-r--r--services/surfaceflinger/DisplayHardware/HWComposer.h1
-rw-r--r--services/surfaceflinger/EventThread.cpp43
-rw-r--r--services/surfaceflinger/Layer.cpp1
-rw-r--r--services/surfaceflinger/LayerBase.cpp13
-rw-r--r--services/surfaceflinger/LayerBase.h2
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp25
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h1
11 files changed, 112 insertions, 16 deletions
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index dd0dc16..07002cc 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -52,3 +52,19 @@ LOCAL_SHARED_LIBRARIES := \
LOCAL_MODULE:= libsurfaceflinger
include $(BUILD_SHARED_LIBRARY)
+
+###############################################################
+# uses jni which may not be available in PDK
+ifneq ($(wildcard libnativehelper/include),)
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES:= \
+ DdmConnection.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils \
+ libdl
+
+LOCAL_MODULE:= libsurfaceflinger_ddmconnection
+
+include $(BUILD_SHARED_LIBRARY)
+endif # libnativehelper
diff --git a/services/surfaceflinger/DdmConnection.cpp b/services/surfaceflinger/DdmConnection.cpp
index 433b38e..ece965c 100644
--- a/services/surfaceflinger/DdmConnection.cpp
+++ b/services/surfaceflinger/DdmConnection.cpp
@@ -23,6 +23,10 @@
namespace android {
+void DdmConnection_start(const char* name) {
+ ALOGI("DdmConnection_start");
+ DdmConnection::start(name);
+}
void DdmConnection::start(const char* name) {
JavaVM* vm;
diff --git a/services/surfaceflinger/DdmConnection.h b/services/surfaceflinger/DdmConnection.h
index 91b737c..b6b088b 100644
--- a/services/surfaceflinger/DdmConnection.h
+++ b/services/surfaceflinger/DdmConnection.h
@@ -19,6 +19,9 @@
namespace android {
+// wrapper for dlsym
+extern "C" void DdmConnection_start(const char* name);
+
class DdmConnection {
public:
static void start(const char* name);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 283d149..23290e3 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -573,9 +573,12 @@ public:
reinterpret_cast<Rect&>(getLayer()->sourceCrop) = crop;
}
virtual void setVisibleRegionScreen(const Region& reg) {
- getLayer()->visibleRegionScreen.rects =
- reinterpret_cast<hwc_rect_t const *>(
- reg.getArray(&getLayer()->visibleRegionScreen.numRects));
+ // Region::getSharedBuffer creates a reference to the underlying
+ // SharedBuffer of this Region, this reference is freed
+ // in onDisplayed()
+ hwc_region_t& visibleRegion = getLayer()->visibleRegionScreen;
+ SharedBuffer const* sb = reg.getSharedBuffer(&visibleRegion.numRects);
+ visibleRegion.rects = reinterpret_cast<hwc_rect_t const *>(sb->data());
}
virtual void setBuffer(const sp<GraphicBuffer>& buffer) {
if (buffer == 0 || buffer->handle == 0) {
@@ -586,6 +589,16 @@ public:
getLayer()->handle = buffer->handle;
}
}
+ virtual void onDisplayed() {
+ hwc_region_t& visibleRegion = getLayer()->visibleRegionScreen;
+ SharedBuffer const* sb = SharedBuffer::bufferFromData(visibleRegion.rects);
+ if (sb) {
+ sb->release();
+ // not technically needed but safer
+ visibleRegion.numRects = 0;
+ visibleRegion.rects = NULL;
+ }
+ }
};
/*
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 8852ab6..a49a023 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -130,6 +130,7 @@ public:
virtual void setVisibleRegionScreen(const Region& reg) = 0;
virtual void setBuffer(const sp<GraphicBuffer>& buffer) = 0;
virtual void setAcquireFenceFd(int fenceFd) = 0;
+ virtual void onDisplayed() = 0;
};
/*
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp
index dcda67e..ade9f75 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/EventThread.cpp
@@ -140,6 +140,8 @@ bool EventThread::threadLoop() {
return true;
}
+// This will return when (1) a vsync event has been received, and (2) there was
+// at least one connection interested in receiving it when we started waiting.
Vector< sp<EventThread::Connection> > EventThread::waitForEvent(
DisplayEventReceiver::Event* event)
{
@@ -193,31 +195,54 @@ Vector< sp<EventThread::Connection> > EventThread::waitForEvent(
// don't report it, and disable VSYNC events
disableVSyncLocked();
} else if (!timestamp && waitForVSync) {
+ // we have at least one client, so we want vsync enabled
+ // (TODO: this function is called right after we finish
+ // notifying clients of a vsync, so this call will be made
+ // at the vsync rate, e.g. 60fps. If we can accurately
+ // track the current state we could avoid making this call
+ // so often.)
enableVSyncLocked();
}
- // note: !timestamp implies signalConnections.isEmpty()
+ // note: !timestamp implies signalConnections.isEmpty(), because we
+ // don't populate signalConnections if there's no vsync pending
if (!timestamp) {
// wait for something to happen
- if (CC_UNLIKELY(mUseSoftwareVSync && waitForVSync)) {
- // h/w vsync cannot be used (screen is off), so we use
- // a timeout instead. it doesn't matter how imprecise this
- // is, we just need to make sure to serve the clients
- if (mCondition.waitRelative(mLock, ms2ns(16)) == TIMED_OUT) {
+ if (waitForVSync) {
+ // This is where we spend most of our time, waiting
+ // for vsync events and new client registrations.
+ //
+ // If the screen is off, we can't use h/w vsync, so we
+ // use a 16ms timeout instead. It doesn't need to be
+ // precise, we just need to keep feeding our clients.
+ //
+ // We don't want to stall if there's a driver bug, so we
+ // use a (long) timeout when waiting for h/w vsync, and
+ // generate fake events when necessary.
+ bool softwareSync = mUseSoftwareVSync;
+ nsecs_t timeout = softwareSync ? ms2ns(16) : ms2ns(1000);
+ if (mCondition.waitRelative(mLock, timeout) == TIMED_OUT) {
+ if (!softwareSync) {
+ ALOGW("Timed out waiting for hw vsync; faking it");
+ }
mVSyncTimestamp = systemTime(SYSTEM_TIME_MONOTONIC);
mVSyncCount++;
}
} else {
- // This is where we spend most of our time, waiting
- // for a vsync events and registered clients
+ // Nobody is interested in vsync, so we just want to sleep.
+ // h/w vsync should be disabled, so this will wait until we
+ // get a new connection, or an existing connection becomes
+ // interested in receiving vsync again.
mCondition.wait(mLock);
}
}
} while (signalConnections.isEmpty());
// here we're guaranteed to have a timestamp and some connections to signal
+ // (The connections might have dropped out of mDisplayEventConnections
+ // while we were asleep, but we'll still have strong references to them.)
- // dispatch vsync events to listeners...
+ // fill in vsync event info
event->header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
event->header.timestamp = timestamp;
event->vsync.count = vsyncCount;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index ea1bc54..f928805 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -72,6 +72,7 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client)
void Layer::onLayerDisplayed(const sp<const DisplayDevice>& hw,
HWComposer::HWCLayerInterface* layer) {
+ LayerBaseClient::onLayerDisplayed(hw, layer);
if (layer) {
mSurfaceTexture->setReleaseFence(layer->getAndResetReleaseFenceFd());
}
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index a2513a2..87dc572 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -288,12 +288,16 @@ void LayerBase::setGeometry(
// scaling is already applied in transformedBounds
layer.setFrame(transformedBounds);
layer.setCrop(transformedBounds.getBounds());
- layer.setVisibleRegionScreen(tr.transform(visibleRegion));
}
void LayerBase::setPerFrameData(const sp<const DisplayDevice>& hw,
HWComposer::HWCLayerInterface& layer) {
layer.setBuffer(0);
+ // we have to set the visible region on every frame because
+ // we currently free it during onLayerDisplayed(), which is called
+ // after HWComposer::commit() -- every frame.
+ const Transform& tr = hw->getTransform();
+ layer.setVisibleRegionScreen(tr.transform(visibleRegion));
}
void LayerBase::setAcquireFence(const sp<const DisplayDevice>& hw,
@@ -301,6 +305,13 @@ void LayerBase::setAcquireFence(const sp<const DisplayDevice>& hw,
layer.setAcquireFenceFd(-1);
}
+void LayerBase::onLayerDisplayed(const sp<const DisplayDevice>& hw,
+ HWComposer::HWCLayerInterface* layer) {
+ if (layer) {
+ layer->onDisplayed();
+ }
+}
+
void LayerBase::setFiltering(bool filtering)
{
mFiltering = filtering;
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index c18f397..4651517 100644
--- a/services/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
@@ -218,7 +218,7 @@ public:
/** called after page-flip
*/
virtual void onLayerDisplayed(const sp<const DisplayDevice>& hw,
- HWComposer::HWCLayerInterface* layer) { }
+ HWComposer::HWCLayerInterface* layer);
/** called before composition.
* returns true if the layer has pending updates.
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 7124b0c..ee653f3 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -20,6 +20,7 @@
#include <sys/types.h>
#include <errno.h>
#include <math.h>
+#include <dlfcn.h>
#include <EGL/egl.h>
#include <GLES/gl.h>
@@ -108,9 +109,11 @@ SurfaceFlinger::SurfaceFlinger()
property_get("debug.sf.ddms", value, "0");
mDebugDDMS = atoi(value);
if (mDebugDDMS) {
- DdmConnection::start(getServiceName());
+ if (!startDdmConnection()) {
+ // start failed, and DDMS debugging not enabled
+ mDebugDDMS = 0;
+ }
}
-
ALOGI_IF(mDebugRegion, "showupdates enabled");
ALOGI_IF(mDebugDDMS, "DDMS debugging enabled");
}
@@ -2061,6 +2064,24 @@ void SurfaceFlinger::dumpAllLocked(
hw->dump(result);
}
+bool SurfaceFlinger::startDdmConnection()
+{
+ void* libddmconnection_dso =
+ dlopen("libsurfaceflinger_ddmconnection.so", RTLD_NOW);
+ if (!libddmconnection_dso) {
+ return false;
+ }
+ void (*DdmConnection_start)(const char* name);
+ DdmConnection_start =
+ (typeof DdmConnection_start)dlsym(libddmconnection_dso, "DdmConnection_start");
+ if (!DdmConnection_start) {
+ dlclose(libddmconnection_dso);
+ return false;
+ }
+ (*DdmConnection_start)(getServiceName());
+ return true;
+}
+
status_t SurfaceFlinger::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 50fef00..9db6b2d 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -388,6 +388,7 @@ private:
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;
+ bool startDdmConnection();
/* ------------------------------------------------------------------------
* Attributes