diff options
Diffstat (limited to 'services')
-rw-r--r-- | services/surfaceflinger/Android.mk | 16 | ||||
-rw-r--r-- | services/surfaceflinger/DdmConnection.cpp | 4 | ||||
-rw-r--r-- | services/surfaceflinger/DdmConnection.h | 3 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayHardware/HWComposer.cpp | 19 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayHardware/HWComposer.h | 1 | ||||
-rw-r--r-- | services/surfaceflinger/EventThread.cpp | 43 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.cpp | 1 | ||||
-rw-r--r-- | services/surfaceflinger/LayerBase.cpp | 13 | ||||
-rw-r--r-- | services/surfaceflinger/LayerBase.h | 2 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 25 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 1 |
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 |