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

Commit 8bfdda9a authored by Mathias Agopian's avatar Mathias Agopian
Browse files

fix transition from full overlays to fb

we need to clear the whole framebuffer in that situation because
we can't trust the content of the FB when partial (fb preserving)
updates are used.

Bug: 5318492

Change-Id: I3f0e01b0fb665a34e44d88ad9f0f54a5d990060b
parent 56eb3fc6
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -84,9 +84,10 @@ public:
    
    
    status_t compositionComplete() const;
    status_t compositionComplete() const;
    
    
    Rect bounds() const {
    Rect getBounds() const {
        return Rect(mWidth, mHeight);
        return Rect(mWidth, mHeight);
    }
    }
    inline Rect bounds() const { return getBounds(); }


    // only for debugging
    // only for debugging
    int getCurrentBufferIndex() const;
    int getCurrentBufferIndex() const;
+32 −0
Original line number Original line Diff line number Diff line
@@ -40,6 +40,7 @@ namespace android {
HWComposer::HWComposer(const sp<SurfaceFlinger>& flinger)
HWComposer::HWComposer(const sp<SurfaceFlinger>& flinger)
    : mFlinger(flinger),
    : mFlinger(flinger),
      mModule(0), mHwc(0), mList(0), mCapacity(0),
      mModule(0), mHwc(0), mList(0), mCapacity(0),
      mNumOVLayers(0), mNumFBLayers(0),
      mDpy(EGL_NO_DISPLAY), mSur(EGL_NO_SURFACE)
      mDpy(EGL_NO_DISPLAY), mSur(EGL_NO_SURFACE)
{
{
    int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &mModule);
    int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &mModule);
@@ -98,9 +99,40 @@ status_t HWComposer::createWorkList(size_t numLayers) {


status_t HWComposer::prepare() const {
status_t HWComposer::prepare() const {
    int err = mHwc->prepare(mHwc, mList);
    int err = mHwc->prepare(mHwc, mList);
    if (err == NO_ERROR) {
        size_t numOVLayers = 0;
        size_t numFBLayers = 0;
        size_t count = mList->numHwLayers;
        for (size_t i=0 ; i<count ; i++) {
            hwc_layer& l(mList->hwLayers[i]);
            if (l.flags & HWC_SKIP_LAYER) {
                l.compositionType = HWC_FRAMEBUFFER;
            }
            switch (l.compositionType) {
                case HWC_OVERLAY:
                    numOVLayers++;
                    break;
                case HWC_FRAMEBUFFER:
                    numFBLayers++;
                    break;
            }
        }
        mNumOVLayers = numOVLayers;
        mNumFBLayers = numFBLayers;
    }
    return (status_t)err;
    return (status_t)err;
}
}


size_t HWComposer::getLayerCount(int type) const {
    switch (type) {
        case HWC_OVERLAY:
            return mNumOVLayers;
        case HWC_FRAMEBUFFER:
            return mNumFBLayers;
    }
    return 0;
}

status_t HWComposer::commit() const {
status_t HWComposer::commit() const {
    int err = mHwc->set(mHwc, mDpy, mSur, mList);
    int err = mHwc->set(mHwc, mDpy, mSur, mList);
    if (mList) {
    if (mList) {
+5 −0
Original line number Original line Diff line number Diff line
@@ -64,6 +64,9 @@ public:
    size_t getNumLayers() const;
    size_t getNumLayers() const;
    hwc_layer_t* getLayers() const;
    hwc_layer_t* getLayers() const;


    // updated in preapre()
    size_t getLayerCount(int type) const;

    // for debugging
    // for debugging
    void dump(String8& out, char* scratch, size_t SIZE,
    void dump(String8& out, char* scratch, size_t SIZE,
            const Vector< sp<LayerBase> >& visibleLayersSortedByZ) const;
            const Vector< sp<LayerBase> >& visibleLayersSortedByZ) const;
@@ -81,6 +84,8 @@ private:
    hwc_composer_device_t*  mHwc;
    hwc_composer_device_t*  mHwc;
    hwc_layer_list_t*       mList;
    hwc_layer_list_t*       mList;
    size_t                  mCapacity;
    size_t                  mCapacity;
    mutable size_t          mNumOVLayers;
    mutable size_t          mNumFBLayers;
    hwc_display_t           mDpy;
    hwc_display_t           mDpy;
    hwc_surface_t           mSur;
    hwc_surface_t           mSur;
    cb_context              mCBContext;
    cb_context              mCBContext;
+50 −46
Original line number Original line Diff line number Diff line
@@ -876,24 +876,21 @@ void SurfaceFlinger::handleRepaint()
        }
        }
    }
    }


    Region expandDirty = setupHardwareComposer(mDirtyRegion);
    setupHardwareComposer(mDirtyRegion);
    mDirtyRegion.orSelf(expandDirty);
    mSwapRegion.orSelf(mDirtyRegion);
    composeSurfaces(mDirtyRegion);
    composeSurfaces(mDirtyRegion);


    // clear the dirty regions
    // update the swap region and clear the dirty region
    mSwapRegion.orSelf(mDirtyRegion);
    mDirtyRegion.clear();
    mDirtyRegion.clear();
}
}


Region SurfaceFlinger::setupHardwareComposer(const Region& dirty)
void SurfaceFlinger::setupHardwareComposer(Region& dirtyInOut)
{
{
    Region dirtyOut(dirty);

    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    HWComposer& hwc(hw.getHwComposer());
    HWComposer& hwc(hw.getHwComposer());
    hwc_layer_t* const cur(hwc.getLayers());
    hwc_layer_t* const cur(hwc.getLayers());
    if (!cur) {
    if (!cur) {
        return dirtyOut;
        return;
    }
    }


    const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
    const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
@@ -916,12 +913,11 @@ Region SurfaceFlinger::setupHardwareComposer(const Region& dirty)
        const sp<LayerBase>& layer(layers[i]);
        const sp<LayerBase>& layer(layers[i]);
        layer->setPerFrameData(&cur[i]);
        layer->setPerFrameData(&cur[i]);
    }
    }
    const size_t fbLayerCount = hwc.getLayerCount(HWC_FRAMEBUFFER);
    status_t err = hwc.prepare();
    status_t err = hwc.prepare();
    LOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
    LOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));


    if (err == NO_ERROR) {
    if (err == NO_ERROR) {
        Region transparent;
        for (size_t i=0 ; i<count ; i++) {
        // what's happening here is tricky.
        // what's happening here is tricky.
        // we want to clear all the layers with the CLEAR_FB flags
        // we want to clear all the layers with the CLEAR_FB flags
        // that are opaque.
        // that are opaque.
@@ -932,37 +928,47 @@ Region SurfaceFlinger::setupHardwareComposer(const Region& dirty)
        //   NOTE: on non backbuffer preserving GPU, the dirty region
        //   NOTE: on non backbuffer preserving GPU, the dirty region
        //   has already been expanded as needed, so the code is correct
        //   has already been expanded as needed, so the code is correct
        //   there too.
        //   there too.
        //
        // However, the content of the framebuffer cannot be trusted when
        // However, the content of the framebuffer cannot be trusted when
        // we switch to/from FB/OVERLAY, in which case we need to
        // we switch to/from FB/OVERLAY, in which case we need to
        // expand the dirty region to those areas too.
        // expand the dirty region to those areas too.
        //
        //
        // Note also that there is a special case when switching from
        // "no layers in FB" to "some layers in FB", where we need to redraw
        // the entire FB, since some areas might contain uninitialized
        // data.
        //
        // Also we want to make sure to not clear areas that belong to
        // Also we want to make sure to not clear areas that belong to
        // layers above that won't redraw (we would just erasing them),
        // layers above that won't redraw (we would just erasing them),
        // that is, we can't erase anything outside the dirty region.
        // that is, we can't erase anything outside the dirty region.


        Region transparent;

        if (!fbLayerCount && hwc.getLayerCount(HWC_FRAMEBUFFER)) {
            transparent.set(hw.getBounds());
            dirtyInOut = transparent;
        } else {
            for (size_t i=0 ; i<count ; i++) {
                const sp<LayerBase>& layer(layers[i]);
                const sp<LayerBase>& layer(layers[i]);
                if ((cur[i].hints & HWC_HINT_CLEAR_FB) && layer->isOpaque()) {
                if ((cur[i].hints & HWC_HINT_CLEAR_FB) && layer->isOpaque()) {
                    transparent.orSelf(layer->visibleRegionScreen);
                    transparent.orSelf(layer->visibleRegionScreen);
                }
                }

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

                if (isOverlay != layer->isOverlay()) {
                if (isOverlay != layer->isOverlay()) {
                    // we transitioned to/from overlay, so add this layer
                    // we transitioned to/from overlay, so add this layer
                    // to the dirty region so the framebuffer can be either
                    // to the dirty region so the framebuffer can be either
                    // cleared or redrawn.
                    // cleared or redrawn.
                dirtyOut.orSelf(layer->visibleRegionScreen);
                    dirtyInOut.orSelf(layer->visibleRegionScreen);
                }
                }
                layer->setOverlay(isOverlay);
                layer->setOverlay(isOverlay);
            }
            }

            // don't erase stuff outside the dirty region
            transparent.andSelf(dirtyInOut);
        }


        /*
        /*
         *  clear the area of the FB that need to be transparent
         *  clear the area of the FB that need to be transparent
         */
         */
        // don't erase stuff outside the dirty region
        transparent.andSelf(dirtyOut);
        if (!transparent.isEmpty()) {
        if (!transparent.isEmpty()) {
            glClearColor(0,0,0,0);
            glClearColor(0,0,0,0);
            Region::const_iterator it = transparent.begin();
            Region::const_iterator it = transparent.begin();
@@ -976,7 +982,6 @@ Region SurfaceFlinger::setupHardwareComposer(const Region& dirty)
            }
            }
        }
        }
    }
    }
    return dirtyOut;
}
}


void SurfaceFlinger::composeSurfaces(const Region& dirty)
void SurfaceFlinger::composeSurfaces(const Region& dirty)
@@ -997,8 +1002,7 @@ void SurfaceFlinger::composeSurfaces(const Region& dirty)
    const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
    const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
    size_t count = layers.size();
    size_t count = layers.size();
    for (size_t i=0 ; i<count ; i++) {
    for (size_t i=0 ; i<count ; i++) {
        if (cur && (cur[i].compositionType != HWC_FRAMEBUFFER) &&
        if (cur && (cur[i].compositionType != HWC_FRAMEBUFFER)) {
                !(cur[i].flags & HWC_SKIP_LAYER)) {
            continue;
            continue;
        }
        }
        const sp<LayerBase>& layer(layers[i]);
        const sp<LayerBase>& layer(layers[i]);
+1 −1
Original line number Original line Diff line number Diff line
@@ -277,7 +277,7 @@ private:
            void        handleWorkList();
            void        handleWorkList();
            void        handleRepaint();
            void        handleRepaint();
            void        postFramebuffer();
            void        postFramebuffer();
            Region      setupHardwareComposer(const Region& dirty);
            void        setupHardwareComposer(Region& dirtyInOut);
            void        composeSurfaces(const Region& dirty);
            void        composeSurfaces(const Region& dirty);
            void        repaintEverything();
            void        repaintEverything();