diff options
-rw-r--r-- | include/utils/KeyedVector.h | 16 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayDevice.cpp | 57 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayDevice.h | 20 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 113 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 29 |
5 files changed, 172 insertions, 63 deletions
diff --git a/include/utils/KeyedVector.h b/include/utils/KeyedVector.h index 20575ee..47c2c56 100644 --- a/include/utils/KeyedVector.h +++ b/include/utils/KeyedVector.h @@ -56,7 +56,10 @@ public: inline size_t capacity() const { return mVector.capacity(); } //! setst the capacity. capacity can never be reduced less than size() inline ssize_t setCapacity(size_t size) { return mVector.setCapacity(size); } - + + // returns true if the arguments is known to be identical to this vector + inline bool isIdenticalTo(const KeyedVector& rhs) const; + /*! * accessors */ @@ -64,6 +67,7 @@ public: const VALUE& valueAt(size_t index) const; const KEY& keyAt(size_t index) const; ssize_t indexOfKey(const KEY& key) const; + const VALUE& operator[] (size_t index) const; /*! * modifying the array @@ -123,6 +127,11 @@ KeyedVector<KEY,VALUE>::KeyedVector() } template<typename KEY, typename VALUE> inline +bool KeyedVector<KEY,VALUE>::isIdenticalTo(const KeyedVector<KEY,VALUE>& rhs) const { + return mVector.array() == rhs.mVector.array(); +} + +template<typename KEY, typename VALUE> inline ssize_t KeyedVector<KEY,VALUE>::indexOfKey(const KEY& key) const { return mVector.indexOf( key_value_pair_t<KEY,VALUE>(key) ); } @@ -140,6 +149,11 @@ const VALUE& KeyedVector<KEY,VALUE>::valueAt(size_t index) const { } template<typename KEY, typename VALUE> inline +const VALUE& KeyedVector<KEY,VALUE>::operator[] (size_t index) const { + return valueAt(index); +} + +template<typename KEY, typename VALUE> inline const KEY& KeyedVector<KEY,VALUE>::keyAt(size_t index) const { return mVector.itemAt(index).key; } diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index b09b77c..a33b94b 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -97,33 +97,55 @@ void checkEGLErrors(const char* token) * */ +DisplayDevice::DisplayDevice() + : mId(0), + mDisplay(EGL_NO_DISPLAY), + mSurface(EGL_NO_SURFACE), + mContext(EGL_NO_CONTEXT) +{ +} + DisplayDevice::DisplayDevice( const sp<SurfaceFlinger>& flinger, int display, const sp<SurfaceTextureClient>& surface, EGLConfig config) - : mFlinger(flinger), - mDisplayId(display), - mNativeWindow(surface), - mDisplay(EGL_NO_DISPLAY), - mSurface(EGL_NO_SURFACE), - mContext(EGL_NO_CONTEXT), - mDpiX(), mDpiY(), - mRefreshRate(), - mDensity(), - mDisplayWidth(), mDisplayHeight(), mFormat(), - mFlags(), - mPageFlipCount(), - mRefreshPeriod(), - mSecureLayerVisible(false), - mScreenAcquired(false), - mOrientation(), - mLayerStack(0) + : mFlinger(flinger), + mId(display), + mNativeWindow(surface), + mDisplay(EGL_NO_DISPLAY), + mSurface(EGL_NO_SURFACE), + mContext(EGL_NO_CONTEXT), + mDpiX(), mDpiY(), + mRefreshRate(), + mDensity(), + mDisplayWidth(), mDisplayHeight(), mFormat(), + mFlags(), + mPageFlipCount(), + mRefreshPeriod(), + mSecureLayerVisible(false), + mScreenAcquired(false), + mOrientation(), + mLayerStack(0) { init(config); } DisplayDevice::~DisplayDevice() { + // DO NOT call terminate() from here, because we create + // temporaries of this class (on the stack typically), and we don't + // want to destroy the EGLSurface in that case +} + +void DisplayDevice::terminate() { + if (mSurface != EGL_NO_SURFACE) { + eglDestroySurface(mDisplay, mSurface); + mSurface = EGL_NO_SURFACE; + } +} + +bool DisplayDevice::isValid() const { + return mFlinger != NULL; } float DisplayDevice::getDpiX() const { @@ -389,5 +411,6 @@ status_t DisplayDevice::setOrientation(int orientation) { h = tmp; } mOrientation = orientation; + dirtyRegion.set(bounds()); return NO_ERROR; } diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index e1c2d11..96590a0 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -49,10 +49,17 @@ public: Region undefinedRegion; enum { + DISPLAY_ID_MAIN = 0, + DISPLAY_ID_HDMI = 1 + }; + + enum { PARTIAL_UPDATES = 0x00020000, // video driver feature SWAP_RECTANGLE = 0x00080000, }; + DisplayDevice(); + DisplayDevice( const sp<SurfaceFlinger>& flinger, int dpy, @@ -61,6 +68,14 @@ public: ~DisplayDevice(); + // must be called when this object is no longer needed. this will + // render the associated EGLSurface invalid. + void terminate(); + + // whether this is a valid object. An invalid DisplayDevice is returned + // when an non existing id is requested + bool isValid() const; + // Flip the front and back buffers if the back buffer is "dirty". Might // be instantaneous, might involve copying the frame buffer around. void flip(const Region& dirty) const; @@ -110,6 +125,9 @@ public: uint32_t getPageFlipCount() const; void dump(String8& res) const; + inline bool operator < (const DisplayDevice& rhs) const { + return mId < rhs.mId; + } private: void init(EGLConfig config); @@ -118,7 +136,7 @@ private: * Constants, set during initialization */ sp<SurfaceFlinger> mFlinger; - int mDisplayId; + int32_t mId; // ANativeWindow this display is rendering into sp<SurfaceTextureClient> mNativeWindow; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 7fb825a..f25eb5f 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -370,11 +370,12 @@ status_t SurfaceFlinger::readyToRun() mEGLContext = createGLContext(mEGLDisplay, mEGLConfig); // initialize our main display hardware - DisplayDevice* const hw = new DisplayDevice(this, 0, anw, mEGLConfig); - mDisplayDevices[0] = hw; + mCurrentState.displays.add(DisplayDevice::DISPLAY_ID_MAIN, DisplayDeviceState()); + DisplayDevice hw(this, DisplayDevice::DISPLAY_ID_MAIN, anw, mEGLConfig); + mDisplays.add(DisplayDevice::DISPLAY_ID_MAIN, hw); // initialize OpenGL ES - EGLSurface surface = hw->getEGLSurface(); + EGLSurface surface = hw.getEGLSurface(); initializeGL(mEGLDisplay, surface); // start the EventThread @@ -384,7 +385,10 @@ status_t SurfaceFlinger::readyToRun() // initialize the H/W composer mHwc = new HWComposer(this, *static_cast<HWComposer::EventHandler *>(this), - hw->getRefreshPeriod()); + hw.getRefreshPeriod()); + + // initialize our drawing state + mDrawingState = mCurrentState; // We're now ready to accept clients... mReadyToRunBarrier.open(); @@ -585,9 +589,8 @@ void SurfaceFlinger::handleMessageRefresh() { */ const LayerVector& currentLayers(mDrawingState.layersSortedByZ); - for (int dpy=0 ; dpy<1 ; dpy++) { // TODO: iterate through all displays - DisplayDevice& hw(const_cast<DisplayDevice&>(getDisplayDevice(dpy))); - + for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) { + DisplayDevice& hw(mDisplays.editValueAt(dpy)); Region opaqueRegion; Region dirtyRegion; computeVisibleRegions(currentLayers, @@ -615,8 +618,8 @@ void SurfaceFlinger::handleMessageRefresh() { // build the h/w work list const bool workListsDirty = mHwWorkListDirty; mHwWorkListDirty = false; - for (int dpy=0 ; dpy<1 ; dpy++) { // TODO: iterate through all displays - DisplayDevice& hw(const_cast<DisplayDevice&>(getDisplayDevice(dpy))); + for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) { + const DisplayDevice& hw(mDisplays[dpy]); const Vector< sp<LayerBase> >& currentLayers(hw.getVisibleLayersSortedByZ()); const size_t count = currentLayers.size(); @@ -646,8 +649,8 @@ void SurfaceFlinger::handleMessageRefresh() { } const bool repaintEverything = android_atomic_and(0, &mRepaintEverything); - for (int dpy=0 ; dpy<1 ; dpy++) { // TODO: iterate through all displays - DisplayDevice& hw(const_cast<DisplayDevice&>(getDisplayDevice(dpy))); + for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) { + DisplayDevice& hw(mDisplays.editValueAt(dpy)); // transform the dirty region into this screen's coordinate space const Transform& planeTransform(hw.getTransform()); @@ -693,7 +696,7 @@ void SurfaceFlinger::handleMessageRefresh() { glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - DisplayDevice& hw(const_cast<DisplayDevice&>(getDisplayDevice(0))); + DisplayDevice& hw(const_cast<DisplayDevice&>(getDefaultDisplayDevice())); const Vector< sp<LayerBase> >& layers( hw.getVisibleLayersSortedByZ() ); const size_t count = layers.size(); for (size_t i=0 ; i<count ; ++i) { @@ -725,8 +728,8 @@ void SurfaceFlinger::postFramebuffer() HWComposer& hwc(getHwComposer()); - for (int dpy=0 ; dpy<1 ; dpy++) { // TODO: iterate through all displays - DisplayDevice& hw(const_cast<DisplayDevice&>(getDisplayDevice(dpy))); + for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) { + DisplayDevice& hw(mDisplays.editValueAt(dpy)); if (hwc.initCheck() == NO_ERROR) { const Vector< sp<LayerBase> >& currentLayers(hw.getVisibleLayersSortedByZ()); const size_t count = currentLayers.size(); @@ -746,8 +749,8 @@ void SurfaceFlinger::postFramebuffer() hwc.commit(mEGLDisplay, getDefaultDisplayDevice().getEGLSurface()); } - for (int dpy=0 ; dpy<1 ; dpy++) { // TODO: iterate through all displays - DisplayDevice& hw(const_cast<DisplayDevice&>(getDisplayDevice(dpy))); + for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) { + const DisplayDevice& hw(mDisplays[dpy]); const Vector< sp<LayerBase> >& currentLayers(hw.getVisibleLayersSortedByZ()); const size_t count = currentLayers.size(); if (hwc.initCheck() == NO_ERROR) { @@ -822,16 +825,52 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) */ if (transactionFlags & eTransactionNeeded) { - if (mCurrentState.orientation != mDrawingState.orientation) { - // the orientation has changed, recompute all visible regions - // and invalidate everything. - - const int dpy = 0; // FIXME: should be a parameter - DisplayDevice& hw(const_cast<DisplayDevice&>(getDisplayDevice(dpy))); - hw.setOrientation(mCurrentState.orientation); - hw.dirtyRegion.set(hw.bounds()); - + // here we take advantage of Vector's copy-on-write semantics to + // improve performance by skipping the transaction entirely when + // know that the lists are identical + const KeyedVector<int32_t, DisplayDeviceState>& curr(mCurrentState.displays); + const KeyedVector<int32_t, DisplayDeviceState>& draw(mDrawingState.displays); + if (!curr.isIdenticalTo(draw)) { mVisibleRegionsDirty = true; + const size_t cc = curr.size(); + const size_t dc = draw.size(); + + // find the displays that were removed + // (ie: in drawing state but not in current state) + // also handle displays that changed + // (ie: displays that are in both lists) + for (size_t i=0 ; i<dc ; i++) { + if (curr.indexOfKey(draw[i].id) < 0) { + // in drawing state but not in current state + if (draw[i].id != DisplayDevice::DISPLAY_ID_MAIN) { + mDisplays.editValueFor(draw[i].id).terminate(); + mDisplays.removeItem(draw[i].id); + } else { + ALOGW("trying to remove the main display"); + } + } else { + // this display is in both lists. see if something changed. + const DisplayDeviceState& state(curr[i]); + if (state.layerStack != draw[i].layerStack) { + DisplayDevice& disp(mDisplays.editValueFor(state.id)); + //disp.setLayerStack(state.layerStack); + } + if (curr[i].orientation != draw[i].orientation) { + DisplayDevice& disp(mDisplays.editValueFor(state.id)); + disp.setOrientation(state.orientation); + } + } + } + + // find displays that were added + // (ie: in current state but not in drawing state) + for (size_t i=0 ; i<cc ; i++) { + if (mDrawingState.displays.indexOfKey(curr[i].id) < 0) { + // FIXME: we need to pass the surface here + DisplayDevice disp(this, curr[i].id, 0, mEGLConfig); + mDisplays.add(curr[i].id, disp); + } + } } if (currentLayers.size() > mDrawingState.layersSortedByZ.size()) { @@ -1011,10 +1050,12 @@ void SurfaceFlinger::computeVisibleRegions( void SurfaceFlinger::invalidateLayerStack(uint32_t layerStack, const Region& dirty) { - // FIXME: update the dirty region of all displays - // presenting this layer's layer stack. - DisplayDevice& hw(const_cast<DisplayDevice&>(getDisplayDevice(0))); - hw.dirtyRegion.orSelf(dirty); + for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) { + DisplayDevice& hw(mDisplays.editValueAt(dpy)); + if (hw.getLayerStack() == layerStack) { + hw.dirtyRegion.orSelf(dirty); + } + } } void SurfaceFlinger::handlePageFlip() @@ -1324,9 +1365,10 @@ void SurfaceFlinger::setTransactionState( } uint32_t transactionFlags = 0; - if (mCurrentState.orientation != orientation) { + // FIXME: don't hardcode display id here + if (mCurrentState.displays.valueFor(0).orientation != orientation) { if (uint32_t(orientation)<=eOrientation270 || orientation==42) { - mCurrentState.orientation = orientation; + mCurrentState.displays.editValueFor(0).orientation = orientation; transactionFlags |= eTransactionNeeded; } else if (orientation != eOrientationUnchanged) { ALOGW("setTransactionState: ignoring unrecognized orientation: %d", @@ -1416,7 +1458,7 @@ sp<Layer> SurfaceFlinger::createNormalLayer( PixelFormat& format) { // initialize the surfaces - switch (format) { // TODO: take h/w into account + switch (format) { case PIXEL_FORMAT_TRANSPARENT: case PIXEL_FORMAT_TRANSLUCENT: format = PIXEL_FORMAT_RGBA_8888; @@ -1804,7 +1846,7 @@ void SurfaceFlinger::dumpAllLocked( hw.undefinedRegion.dump(result, "undefinedRegion"); snprintf(buffer, SIZE, " orientation=%d, canDraw=%d\n", - mCurrentState.orientation, hw.canDraw()); + hw.getOrientation(), hw.canDraw()); result.append(buffer); snprintf(buffer, SIZE, " last eglSwapBuffers() time: %f us\n" @@ -2727,9 +2769,8 @@ int SurfaceFlinger::LayerVector::do_compare(const void* lhs, // --------------------------------------------------------------------------- -SurfaceFlinger::State::State() - : orientation(ISurfaceComposer::eOrientationDefault), - orientationFlags(0) { +SurfaceFlinger::DisplayDeviceState::DisplayDeviceState() + : id(DisplayDevice::DISPLAY_ID_MAIN), layerStack(0), orientation(0) { } // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 6091e33..15d5a37 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -47,6 +47,7 @@ #include "Barrier.h" #include "MessageQueue.h" +#include "DisplayDevice.h" #include "DisplayHardware/HWComposer.h" @@ -56,7 +57,6 @@ namespace android { class Client; class DisplayEventConnection; -class DisplayDevice; class EventThread; class Layer; class LayerBase; @@ -119,7 +119,7 @@ public: // returns the default Display const DisplayDevice& getDefaultDisplayDevice() const { - return getDisplayDevice(0); + return getDisplayDevice(DisplayDevice::DISPLAY_ID_MAIN); } // utility function to delete a texture on the main thread @@ -156,11 +156,21 @@ private: virtual int do_compare(const void* lhs, const void* rhs) const; }; + struct DisplayDeviceState { + DisplayDeviceState(); + int32_t id; + uint32_t layerStack; + Rect viewport; + Rect frame; + uint8_t orientation; + inline bool operator < (const DisplayDeviceState& rhs) const { + return id < rhs.id; + } + }; + struct State { - State(); LayerVector layersSortedByZ; - uint8_t orientation; - uint8_t orientationFlags; + KeyedVector<int32_t, DisplayDeviceState> displays; }; /* ------------------------------------------------------------------------ @@ -175,9 +185,9 @@ private: */ virtual sp<ISurfaceComposerClient> createConnection(); virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc(); - virtual void bootFinished(); virtual void setTransactionState(const Vector<ComposerState>& state, const Vector<DisplayState>& displays, uint32_t flags); + virtual void bootFinished(); virtual bool authenticateSurfaceTexture( const sp<ISurfaceTexture>& surface) const; virtual sp<IDisplayEventConnection> createDisplayEventConnection(); @@ -317,7 +327,10 @@ private: * Display and layer stack management */ const DisplayDevice& getDisplayDevice(DisplayID dpy) const { - return *mDisplayDevices[dpy]; + return mDisplays.valueFor(dpy); + } + DisplayDevice& getDisplayDevice(DisplayID dpy) { + return mDisplays.editValueFor(dpy); } // mark a region of a layer stack dirty. this updates the dirty @@ -370,7 +383,6 @@ private: Vector<sp<LayerBase> > mLayersPendingRemoval; // protected by mStateLock (but we could use another lock) - DisplayDevice* mDisplayDevices[1]; bool mLayersRemoved; // access must be protected by mInvalidateLock @@ -393,6 +405,7 @@ private: bool mVisibleRegionsDirty; bool mHwWorkListDirty; int32_t mElectronBeamAnimationMode; + DefaultKeyedVector<int32_t, DisplayDevice> mDisplays; // don't use a lock for these, we don't care int mDebugRegion; |