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

Commit 84300958 authored by Mathias Agopian's avatar Mathias Agopian
Browse files

make transform hint multi-display aware

if a layer is not mirrored, we now use its display
as the source for the transfrom hint calculation
instead of always using the default (main) display.

this change does two thing:
1) we make updateTransformHint take a DisplayDevice
   as a parameter instead of hard-coding the
   main display.

2) each time we do a transaction that could change
   the hint, we go through all layers and
   figure out which display should be used for their
   transform hint.

Bug: 7599344
Change-Id: I9b04a95e6c372dd770bacf81d8ef6f8e31b87b83
parent 764c197c
Loading
Loading
Loading
Loading
+5 −7
Original line number Diff line number Diff line
@@ -110,7 +110,8 @@ void Layer::onFirstRef()
    mSurfaceTexture->setDefaultMaxBufferCount(3);
#endif

    updateTransformHint();
    const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
    updateTransformHint(hw);
}

Layer::~Layer()
@@ -767,15 +768,12 @@ uint32_t Layer::getEffectiveUsage(uint32_t usage) const
    return usage;
}

void Layer::updateTransformHint() const {
void Layer::updateTransformHint(const sp<const DisplayDevice>& hw) const {
    uint32_t orientation = 0;
    if (!mFlinger->mDebugDisableTransformHint) {
        // The transform hint is used to improve performance on the main
        // display -- we can only have a single transform hint, it cannot
        // The transform hint is used to improve performance, but we can
        // only have a single transform hint, it cannot
        // apply to all displays.
        // This is why we use the default display here. This is not an
        // oversight.
        sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
        const Transform& planeTransform(hw->getTransform());
        orientation = planeTransform.getOrientation();
        if (orientation & Transform::ROT_INVALID) {
+2 −2
Original line number Diff line number Diff line
@@ -91,8 +91,8 @@ public:
    inline const sp<GraphicBuffer>& getActiveBuffer() const { return mActiveBuffer; }

    // Updates the transform hint in our SurfaceTexture to match
    // the current orientation of the default display device.
    virtual void updateTransformHint() const;
    // the current orientation of the display device.
    virtual void updateTransformHint(const sp<const DisplayDevice>& hw) const;

protected:
    virtual void onFirstRef();
+1 −1
Original line number Diff line number Diff line
@@ -246,7 +246,7 @@ public:
     * Updates the SurfaceTexture's transform hint, for layers that have
     * a SurfaceTexture.
     */
    virtual void updateTransformHint() const { }
    virtual void updateTransformHint(const sp<const DisplayDevice>& hw) const { }

    /** always call base class first */
    virtual void dump(String8& result, char* scratch, size_t size) const;
+56 −13
Original line number Diff line number Diff line
@@ -1069,7 +1069,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)

    if (transactionFlags & eTraversalNeeded) {
        for (size_t i=0 ; i<count ; i++) {
            const sp<LayerBase>& layer = currentLayers[i];
            const sp<LayerBase>& layer(currentLayers[i]);
            uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
            if (!trFlags) continue;

@@ -1142,18 +1142,6 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
                            disp->setProjection(state.orientation,
                                    state.viewport, state.frame);
                        }

                        // Walk through all the layers in currentLayers,
                        // and update their transform hint.
                        //
                        // TODO: we could be much more clever about which
                        // layers we touch and how often we do these updates
                        // (e.g. only touch the layers associated with this
                        // display, and only on a rotation).
                        for (size_t i = 0; i < count; i++) {
                            const sp<LayerBase>& layerBase = currentLayers[i];
                            layerBase->updateTransformHint();
                        }
                    }
                }
            }
@@ -1208,6 +1196,61 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
        }
    }

    if (transactionFlags & (eTraversalNeeded|eDisplayTransactionNeeded)) {
        // The transform hint might have changed for some layers
        // (either because a display has changed, or because a layer
        // as changed).
        //
        // Walk through all the layers in currentLayers,
        // and update their transform hint.
        //
        // If a layer is visible only on a single display, then that
        // display is used to calculate the hint, otherwise we use the
        // default display.
        //
        // NOTE: we do this here, rather than in rebuildLayerStacks() so that
        // the hint is set before we acquire a buffer from the surface texture.
        //
        // NOTE: layer transactions have taken place already, so we use their
        // drawing state. However, SurfaceFlinger's own transaction has not
        // happened yet, so we must use the current state layer list
        // (soon to become the drawing state list).
        //
        sp<const DisplayDevice> disp;
        uint32_t currentlayerStack = 0;
        for (size_t i=0; i<count; i++) {
            // NOTE: we rely on the fact that layers are sorted by
            // layerStack first (so we don't have to traverse the list
            // of displays for every layer).
            const sp<LayerBase>& layerBase(currentLayers[i]);
            uint32_t layerStack = layerBase->drawingState().layerStack;
            if (i==0 || currentlayerStack != layerStack) {
                currentlayerStack = layerStack;
                // figure out if this layerstack is mirrored
                // (more than one display) if so, pick the default display,
                // if not, pick the only display it's on.
                disp.clear();
                for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
                    sp<const DisplayDevice> hw(mDisplays[dpy]);
                    if (hw->getLayerStack() == currentlayerStack) {
                        if (disp == NULL) {
                            disp = hw;
                        } else {
                            disp = getDefaultDisplayDevice();
                            break;
                        }
                    }
                }
            }
            if (disp != NULL) {
                // presumably this means this layer is using a layerStack
                // that is not visible on any display
                layerBase->updateTransformHint(disp);
            }
        }
    }


    /*
     * Perform our own transaction if needed
     */