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

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

Fix an issue is SF that caused drawing artifacts when hwc changed mode

we were not redrawing and/or clearing the FB properly when
hwc moved a layer from/to FB to/from OVERLAY.

In these cases we needed to expand the dirty region to include
the layer that changed mode.

Also split composeSurfaces() which was becoming quite large.

Change-Id: Id6fa1acfc4ff694037fddf7efd037a4405732073
parent 93ec1147
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -344,6 +344,14 @@ void LayerBase::setPerFrameData(hwc_layer_t* hwcl) {
    hwcl->handle = NULL;
}

void LayerBase::setOverlay(bool inOverlay) {
    mInOverlay = inOverlay;
}

bool LayerBase::isOverlay() const {
    return mInOverlay;
}

void LayerBase::setFiltering(bool filtering)
{
    mFiltering = filtering;
+8 −1
Original line number Diff line number Diff line
@@ -109,8 +109,10 @@ public:
    virtual const char* getTypeId() const { return "LayerBase"; }

    virtual void setGeometry(hwc_layer_t* hwcl);

    virtual void setPerFrameData(hwc_layer_t* hwcl);
            void setOverlay(bool inOverlay);
            bool isOverlay() const;


    /**
     * draw - performs some global clipping optimizations
@@ -242,6 +244,11 @@ private:
                // Whether filtering is needed b/c of the drawingstate
                bool            mNeedsFiltering;

                // this layer is currently handled by the hwc. this is
                // updated at composition time, always frmo the composition
                // thread.
                bool            mInOverlay;

protected:
                // cached during validateVisibility()
                int32_t         mOrientation;
+68 −59
Original line number Diff line number Diff line
@@ -817,20 +817,6 @@ void SurfaceFlinger::handleWorkList()
    mHwWorkListDirty = false;
    HWComposer& hwc(graphicPlane(0).displayHardware().getHwComposer());
    if (hwc.initCheck() == NO_ERROR) {

        const DisplayHardware& hw(graphicPlane(0).displayHardware());
        uint32_t flags = hw.getFlags();
        if ((flags & DisplayHardware::SWAP_RECTANGLE) ||
            (flags & DisplayHardware::BUFFER_PRESERVED))
        {
            // we need to redraw everything (the whole screen)
            // NOTE: we could be more subtle here and redraw only
            // the area which will end-up in an overlay. But since this
            // shouldn't happen often, we invalidate everything.
            mDirtyRegion.set(hw.bounds());
            mInvalidRegion = mDirtyRegion;
        }

        const Vector< sp<LayerBase> >& currentLayers(mVisibleLayersSortedByZ);
        const size_t count = currentLayers.size();
        hwc.createWorkList(count);
@@ -891,29 +877,26 @@ void SurfaceFlinger::handleRepaint()
    }

    // compose all surfaces
    setupHardwareComposer(&mDirtyRegion);
    composeSurfaces(mDirtyRegion);

    // clear the dirty regions
    mDirtyRegion.clear();
}

void SurfaceFlinger::composeSurfaces(const Region& dirty)
void SurfaceFlinger::setupHardwareComposer(Region* dirtyInOut)
{
    if (UNLIKELY(!mWormholeRegion.isEmpty())) {
        // should never happen unless the window manager has a bug
        // draw something...
        drawWormhole();
    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    HWComposer& hwc(hw.getHwComposer());
    hwc_layer_t* const cur(hwc.getLayers());
    if (!cur) {
        return;
    }

    status_t err = NO_ERROR;
    const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
    size_t count = layers.size();

    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    HWComposer& hwc(hw.getHwComposer());
    hwc_layer_t* const cur(hwc.getLayers());

    LOGE_IF(cur && hwc.getNumLayers() != count,
    LOGE_IF(hwc.getNumLayers() != count,
            "HAL number of layers (%d) doesn't match surfaceflinger (%d)",
            hwc.getNumLayers(), count);

@@ -927,28 +910,45 @@ void SurfaceFlinger::composeSurfaces(const Region& dirty)
     *  and build the transparent region of the FB
     */
    Region transparent;
    if (cur) {
    for (size_t i=0 ; i<count ; i++) {
        const sp<LayerBase>& layer(layers[i]);
        layer->setPerFrameData(&cur[i]);
    }
        err = hwc.prepare();
    status_t err = hwc.prepare();
    LOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));

    if (err == NO_ERROR) {
        Region transparentDirty(*dirtyInOut);
        for (size_t i=0 ; i<count ; i++) {
                if (cur[i].hints & HWC_HINT_CLEAR_FB) {
            // Calculate the new transparent region and dirty region
            // - the transparent region needs to always include the layers
            // that moved from FB to OVERLAY, regardless of the dirty region
            // - the dirty region needs to be expanded to include layers
            // that moved from OVERLAY to FB.

            const sp<LayerBase>& layer(layers[i]);
                    if (layer->isOpaque()) {
            if ((cur[i].hints & HWC_HINT_CLEAR_FB) && layer->isOpaque()) {
                transparent.orSelf(layer->visibleRegionScreen);
            }

            bool isOverlay = (cur[i].compositionType != HWC_FRAMEBUFFER) &&
                !(cur[i].flags & HWC_SKIP_LAYER);

            if (!isOverlay && layer->isOverlay()) {
                dirtyInOut->orSelf(layer->visibleRegionScreen);
            }

            if (isOverlay && !layer->isOverlay()) {
                transparentDirty.orSelf(layer->visibleRegionScreen);
            }

            layer->setOverlay(isOverlay);
        }

        /*
         *  clear the area of the FB that need to be transparent
         */
            transparent.andSelf(dirty);
        transparent.andSelf(transparentDirty);
        if (!transparent.isEmpty()) {
            glClearColor(0,0,0,0);
            Region::const_iterator it = transparent.begin();
@@ -964,19 +964,28 @@ void SurfaceFlinger::composeSurfaces(const Region& dirty)
    }
}

void SurfaceFlinger::composeSurfaces(const Region& dirty)
{
    if (UNLIKELY(!mWormholeRegion.isEmpty())) {
        // should never happen unless the window manager has a bug
        // draw something...
        drawWormhole();
    }

    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    HWComposer& hwc(hw.getHwComposer());
    hwc_layer_t* const cur(hwc.getLayers());

    /*
     * and then, render the layers targeted at the framebuffer
     */
    const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
    size_t count = layers.size();
    for (size_t i=0 ; i<count ; i++) {
        if (cur) {
            if ((cur[i].compositionType != HWC_FRAMEBUFFER) &&
        if (cur && (cur[i].compositionType != HWC_FRAMEBUFFER) &&
                !(cur[i].flags & HWC_SKIP_LAYER)) {
                // skip layers handled by the HAL
            continue;
        }
        }

        const sp<LayerBase>& layer(layers[i]);
        const Region clip(dirty.intersect(layer->visibleRegionScreen));
        if (!clip.isEmpty()) {
+1 −0
Original line number Diff line number Diff line
@@ -277,6 +277,7 @@ private:
            void        handleWorkList();
            void        handleRepaint();
            void        postFramebuffer();
            void        setupHardwareComposer(Region* dirtyInOut);
            void        composeSurfaces(const Region& dirty);
            void        repaintEverything();