diff options
author | 2011-11-17 17:49:17 -0800 | |
---|---|---|
committer | 2011-11-29 11:44:05 -0800 | |
commit | f3918c5bd4bc9f02f74da42995564150ca2dd382 (patch) | |
tree | 9f8a1bb871b9b5a7571a6a9cbc65d539ac947b92 | |
parent | bb9ba8bae551305acba4f60577b0f461a9421bc5 (diff) |
Add support for sending VSYNC events to the framework
use gui/DisplayEvent to receive the events. Events are
dispatched through a unix pipe, so the API is compatible
with utils/Looper. see gui/DisplayEvent.h for more info.
Bug: 1475048
Change-Id: If4126023fc9c067e56087ec7d16a8fd542ce1794
-rw-r--r-- | include/surfaceflinger/ISurfaceComposer.h | 10 | ||||
-rw-r--r-- | libs/gui/Android.mk | 2 | ||||
-rw-r--r-- | libs/gui/ISurfaceComposer.cpp | 32 | ||||
-rw-r--r-- | services/surfaceflinger/Android.mk | 27 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayHardware/DisplayHardware.cpp | 34 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayHardware/DisplayHardware.h | 12 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 56 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 8 |
8 files changed, 153 insertions, 28 deletions
diff --git a/include/surfaceflinger/ISurfaceComposer.h b/include/surfaceflinger/ISurfaceComposer.h index 5eb09c79666a..58fd89d3b62c 100644 --- a/include/surfaceflinger/ISurfaceComposer.h +++ b/include/surfaceflinger/ISurfaceComposer.h @@ -33,8 +33,9 @@ namespace android { // ---------------------------------------------------------------------------- -class IMemoryHeap; class ComposerState; +class IDisplayEventConnection; +class IMemoryHeap; class ISurfaceComposer : public IInterface { @@ -124,13 +125,19 @@ public: uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ) = 0; + /* triggers screen off animation */ virtual status_t turnElectronBeamOff(int32_t mode) = 0; + + /* triggers screen on animation */ virtual status_t turnElectronBeamOn(int32_t mode) = 0; /* verify that an ISurfaceTexture was created by SurfaceFlinger. */ virtual bool authenticateSurfaceTexture( const sp<ISurfaceTexture>& surface) const = 0; + + /* return an IDisplayEventConnection */ + virtual sp<IDisplayEventConnection> createDisplayEventConnection() = 0; }; // ---------------------------------------------------------------------------- @@ -151,6 +158,7 @@ public: TURN_ELECTRON_BEAM_OFF, TURN_ELECTRON_BEAM_ON, AUTHENTICATE_SURFACE, + CREATE_DISPLAY_EVENT_CONNECTION, }; virtual status_t onTransact( uint32_t code, diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk index b7e3ee32c62f..b8be67d446ce 100644 --- a/libs/gui/Android.mk +++ b/libs/gui/Android.mk @@ -3,6 +3,8 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ BitTube.cpp \ + DisplayEventReceiver.cpp \ + IDisplayEventConnection.cpp \ ISensorEventConnection.cpp \ ISensorServer.cpp \ ISurfaceTexture.cpp \ diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 86bc62aa2806..db3282781ab3 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -29,6 +29,9 @@ #include <surfaceflinger/ISurfaceComposer.h> +#include <gui/BitTube.h> +#include <gui/IDisplayEventConnection.h> + #include <ui/DisplayInfo.h> #include <gui/ISurfaceTexture.h> @@ -44,6 +47,8 @@ namespace android { +class IDisplayEventConnection; + class BpSurfaceComposer : public BpInterface<ISurfaceComposer> { public: @@ -174,6 +179,27 @@ public: } return result != 0; } + + virtual sp<IDisplayEventConnection> createDisplayEventConnection() + { + Parcel data, reply; + sp<IDisplayEventConnection> result; + int err = data.writeInterfaceToken( + ISurfaceComposer::getInterfaceDescriptor()); + if (err != NO_ERROR) { + return result; + } + err = remote()->transact( + BnSurfaceComposer::CREATE_DISPLAY_EVENT_CONNECTION, + data, &reply); + if (err != NO_ERROR) { + LOGE("ISurfaceComposer::createDisplayEventConnection: error performing " + "transaction: %s (%d)", strerror(-err), -err); + return result; + } + result = interface_cast<IDisplayEventConnection>(reply.readStrongBinder()); + return result; + } }; IMPLEMENT_META_INTERFACE(SurfaceComposer, "android.ui.ISurfaceComposer"); @@ -254,6 +280,12 @@ status_t BnSurfaceComposer::onTransact( int32_t result = authenticateSurfaceTexture(surfaceTexture) ? 1 : 0; reply->writeInt32(result); } break; + case CREATE_DISPLAY_EVENT_CONNECTION: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + sp<IDisplayEventConnection> connection(createDisplayEventConnection()); + reply->writeStrongBinder(connection->asBinder()); + return NO_ERROR; + } break; default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index 61a8358332eb..17bf375a1d7d 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -2,19 +2,22 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ - Layer.cpp \ - LayerBase.cpp \ - LayerDim.cpp \ - LayerScreenshot.cpp \ - DdmConnection.cpp \ - DisplayHardware/DisplayHardware.cpp \ + EventThread.cpp \ + Layer.cpp \ + LayerBase.cpp \ + LayerDim.cpp \ + LayerScreenshot.cpp \ + DdmConnection.cpp \ + DisplayHardware/DisplayHardware.cpp \ DisplayHardware/DisplayHardwareBase.cpp \ - DisplayHardware/HWComposer.cpp \ - GLExtensions.cpp \ - MessageQueue.cpp \ - SurfaceFlinger.cpp \ - SurfaceTextureLayer.cpp \ - Transform.cpp \ + DisplayHardware/HWComposer.cpp \ + DisplayHardware/VSyncBarrier.cpp \ + DisplayEventConnection.cpp \ + GLExtensions.cpp \ + MessageQueue.cpp \ + SurfaceFlinger.cpp \ + SurfaceTextureLayer.cpp \ + Transform.cpp \ LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\" diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp index f94d32149b0f..3bbc75e6f8a6 100644 --- a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp +++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp @@ -140,6 +140,7 @@ void DisplayHardware::init(uint32_t dpy) mDpiX = mNativeWindow->xdpi; mDpiY = mNativeWindow->ydpi; mRefreshRate = fbDev->fps; + mNextFakeVSync = 0; /* FIXME: this is a temporary HACK until we are able to report the refresh rate @@ -152,6 +153,8 @@ void DisplayHardware::init(uint32_t dpy) #warning "refresh rate set via makefile to REFRESH_RATE" #endif + mRefreshPeriod = nsecs_t(1e9 / mRefreshRate); + EGLint w, h, dummy; EGLint numConfigs=0; EGLSurface surface; @@ -346,6 +349,37 @@ uint32_t DisplayHardware::getPageFlipCount() const { return mPageFlipCount; } +// this needs to be thread safe +nsecs_t DisplayHardware::waitForVSync() const { + nsecs_t timestamp; + if (mVSync.wait(×tamp) < 0) { + // vsync not supported! + usleep( getDelayToNextVSyncUs(×tamp) ); + } + return timestamp; +} + +int32_t DisplayHardware::getDelayToNextVSyncUs(nsecs_t* timestamp) const { + Mutex::Autolock _l(mFakeVSyncMutex); + const nsecs_t period = mRefreshPeriod; + const nsecs_t now = systemTime(CLOCK_MONOTONIC); + nsecs_t next_vsync = mNextFakeVSync; + nsecs_t sleep = next_vsync - now; + if (sleep < 0) { + // we missed, find where the next vsync should be + sleep = (period - ((now - next_vsync) % period)); + next_vsync = now + sleep; + } + mNextFakeVSync = next_vsync + period; + timestamp[0] = next_vsync; + + // round to next microsecond + int32_t sleep_us = (sleep + 999LL) / 1000LL; + + // guaranteed to be > 0 + return sleep_us; +} + status_t DisplayHardware::compositionComplete() const { return mNativeWindow->compositionComplete(); } diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.h b/services/surfaceflinger/DisplayHardware/DisplayHardware.h index f02c95414fae..45d4b45ad934 100644 --- a/services/surfaceflinger/DisplayHardware/DisplayHardware.h +++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.h @@ -32,6 +32,7 @@ #include "GLExtensions.h" #include "DisplayHardware/DisplayHardwareBase.h" +#include "DisplayHardware/VSyncBarrier.h" namespace android { @@ -74,6 +75,9 @@ public: uint32_t getMaxTextureSize() const; uint32_t getMaxViewportDims() const; + // waits for the next vsync and returns the timestamp of when it happened + nsecs_t waitForVSync() const; + uint32_t getPageFlipCount() const; EGLDisplay getEGLDisplay() const { return mDisplay; } @@ -95,6 +99,7 @@ public: private: void init(uint32_t displayIndex) __attribute__((noinline)); void fini() __attribute__((noinline)); + int32_t getDelayToNextVSyncUs(nsecs_t* timestamp) const; sp<SurfaceFlinger> mFlinger; EGLDisplay mDisplay; @@ -112,7 +117,12 @@ private: mutable uint32_t mPageFlipCount; GLint mMaxViewportDims[2]; GLint mMaxTextureSize; - + VSyncBarrier mVSync; + + mutable Mutex mFakeVSyncMutex; + mutable nsecs_t mNextFakeVSync; + nsecs_t mRefreshPeriod; + HWComposer* mHwc; sp<FramebufferNativeWindow> mNativeWindow; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 39f0f401b4f9..d5a8d083e8c2 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -34,6 +34,8 @@ #include <binder/MemoryHeapBase.h> #include <binder/PermissionCache.h> +#include <gui/IDisplayEventConnection.h> + #include <utils/String8.h> #include <utils/String16.h> #include <utils/StopWatch.h> @@ -46,6 +48,8 @@ #include <GLES/gl.h> #include "clz.h" +#include "DisplayEventConnection.h" +#include "EventThread.h" #include "GLExtensions.h" #include "DdmConnection.h" #include "Layer.h" @@ -293,12 +297,16 @@ status_t SurfaceFlinger::readyToRun() // put the origin in the left-bottom corner glOrthof(0, w, 0, h, 0, 1); // l=0, r=w ; b=0, t=h - mReadyToRunBarrier.open(); + + // start the EventThread + mEventThread = new EventThread(this); /* * We're now ready to accept clients... */ + mReadyToRunBarrier.open(); + // start boot animation property_set("ctl.start", "bootanim"); @@ -319,6 +327,22 @@ void SurfaceFlinger::signalEvent() { mEventQueue.invalidate(); } +status_t SurfaceFlinger::postMessageAsync(const sp<MessageBase>& msg, + nsecs_t reltime, uint32_t flags) { + return mEventQueue.postMessage(msg, reltime); +} + +status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg, + nsecs_t reltime, uint32_t flags) { + status_t res = mEventQueue.postMessage(msg, reltime); + if (res == NO_ERROR) { + msg->wait(); + } + return res; +} + +// ---------------------------------------------------------------------------- + bool SurfaceFlinger::authenticateSurfaceTexture( const sp<ISurfaceTexture>& surfaceTexture) const { Mutex::Autolock _l(mStateLock); @@ -360,20 +384,17 @@ bool SurfaceFlinger::authenticateSurfaceTexture( return false; } -status_t SurfaceFlinger::postMessageAsync(const sp<MessageBase>& msg, - nsecs_t reltime, uint32_t flags) -{ - return mEventQueue.postMessage(msg, reltime, flags); +// ---------------------------------------------------------------------------- + +sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection() { + sp<DisplayEventConnection> result(new DisplayEventConnection(this)); + mEventThread->registerDisplayEventConnection(result); + return result; } -status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg, - nsecs_t reltime, uint32_t flags) -{ - status_t res = mEventQueue.postMessage(msg, reltime, flags); - if (res == NO_ERROR) { - msg->wait(); - } - return res; +void SurfaceFlinger::cleanupDisplayEventConnection( + const wp<DisplayEventConnection>& connection) { + mEventThread->unregisterDisplayEventConnection(connection); } // ---------------------------------------------------------------------------- @@ -432,7 +453,7 @@ bool SurfaceFlinger::threadLoop() } else { // pretend we did the post hw.compositionComplete(); - usleep(16667); // 60 fps period + hw.waitForVSync(); } return true; } @@ -1572,9 +1593,16 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) } /* + * 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"); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 17028dbb64fa..1039f471e5a3 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -46,6 +46,8 @@ namespace android { class Client; class DisplayHardware; +class DisplayEventConnection; +class EventThread; class Layer; class LayerDim; class LayerScreenshot; @@ -171,6 +173,7 @@ public: 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(); virtual status_t captureScreen(DisplayID dpy, sp<IMemoryHeap>* heap, @@ -222,6 +225,7 @@ private: private: friend class Client; + friend class DisplayEventConnection; friend class LayerBase; friend class LayerBaseClient; friend class Layer; @@ -331,6 +335,9 @@ private: status_t electronBeamOffAnimationImplLocked(); status_t electronBeamOnAnimationImplLocked(); + void cleanupDisplayEventConnection( + const wp<DisplayEventConnection>& connection); + void debugFlashRegions(); void debugShowFPS() const; void drawWormhole() const; @@ -361,6 +368,7 @@ private: GLuint mWormholeTexName; GLuint mProtectedTexName; nsecs_t mBootTime; + sp<EventThread> mEventThread; // Can only accessed from the main thread, these members // don't need synchronization |