Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 92a979a9 authored by Mathias Agopian's avatar Mathias Agopian
Browse files

We now have a real list of displays.

displays can be dynamically added or removed, and the
list is part of the SF's transaction.

Change-Id: I4186ea39f1317c0e7c044f869004017738968fab
parent fcb239d3
Loading
Loading
Loading
Loading
+15 −1
Original line number Diff line number Diff line
@@ -57,6 +57,9 @@ public:
    //! 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
@@ -122,6 +126,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) );
@@ -139,6 +148,11 @@ const VALUE& KeyedVector<KEY,VALUE>::valueAt(size_t index) const {
    return mVector.itemAt(index).value;
}

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;
+40 −17
Original line number Diff line number Diff line
@@ -97,13 +97,21 @@ 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),
      mId(display),
      mNativeWindow(surface),
      mDisplay(EGL_NO_DISPLAY),
      mSurface(EGL_NO_SURFACE),
@@ -124,6 +132,20 @@ DisplayDevice::DisplayDevice(
}

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;
}
+19 −1
Original line number Diff line number Diff line
@@ -48,11 +48,18 @@ public:
    // region in screen space
    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;
+77 −36
Original line number Diff line number Diff line
@@ -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,11 +1050,13 @@ 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)));
    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) {
}

// ---------------------------------------------------------------------------
+21 −8
Original line number Diff line number Diff line
@@ -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;