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

Commit 74180cb2 authored by Sravan Kumar D.V.N's avatar Sravan Kumar D.V.N Committed by Linux Build Service Account
Browse files

sf: Enable GPU Tiled DR optimization for overlap and mixed mode use cases

Extend the GPU Tiled DR optimization to Overlapping layers use cases
and mixed mode composition

Change-Id: Iaba496be21d5c4ceeedfe3405cf26b36677cd14b
parent 2b1beba7
Loading
Loading
Loading
Loading
+74 −18
Original line number Diff line number Diff line
@@ -202,6 +202,11 @@ HWComposer::HWComposer(
        // we don't have VSYNC support, we need to fake it
        mVSyncThread = new VSyncThread(*this);
    }
#ifdef QCOM_BSP
    // Threshold Area to enable GPU Tiled Rect.
    property_get("debug.hwc.gpuTiledThreshold", value, "1.9");
    mDynThreshold = atof(value);
#endif
}

HWComposer::~HWComposer() {
@@ -705,6 +710,12 @@ status_t HWComposer::prepare() {
#endif

            if (disp.list) {
#ifdef QCOM_BSP
               //GPUTILERECT
               prev_comp_map[i] = current_comp_map[i];
               current_comp_map[i].reset();
               current_comp_map[i].count = disp.list->numHwLayers-1;
#endif
                for (size_t j=0 ; j<disp.list->numHwLayers ; j++) {
                    hwc_layer_1_t& l = disp.list->hwLayers[j];

@@ -732,6 +743,12 @@ status_t HWComposer::prepare() {
                    if (l.compositionType == HWC_CURSOR_OVERLAY) {
                        disp.hasOvComp = true;
                    }
#ifdef QCOM_BSP
                    //GPUTILERECT
                    if(l.compositionType != HWC_FRAMEBUFFER_TARGET) {
                        current_comp_map[i].compType[j] = l.compositionType;
                    }
#endif
                }
                if (disp.list->numHwLayers == (disp.framebufferTarget ? 1 : 0)) {
                    disp.hasFbComp = true;
@@ -745,10 +762,10 @@ status_t HWComposer::prepare() {
}

#ifdef QCOM_BSP
bool HWComposer::hasHwcOrBlitComposition(int32_t id) const {
bool HWComposer::hasBlitComposition(int32_t id) const {
    if (!mHwc || uint32_t(id) > 31 || !mAllocatedDisplayIDs.hasBit(id))
        return false;
    return mDisplayData[id].hasOvComp || mDisplayData[id].hasBlitComp;
    return mDisplayData[id].hasBlitComp;
}
#endif
bool HWComposer::hasHwcComposition(int32_t id) const {
@@ -1374,6 +1391,37 @@ bool HWComposer::areVisibleRegionsOverlapping(int32_t id ) {
    return false;
}

bool HWComposer::canHandleOverlapArea(int32_t id, Rect unionDr) {
    DisplayData& disp(mDisplayData[id]);
    float layerAreaSum = 0;
    float drArea = ((unionDr.right-unionDr.left)* (unionDr.bottom-unionDr.top));
    hwc_layer_1_t& fbLayer = disp.list->hwLayers[disp.list->numHwLayers-1];
    hwc_rect_t fbDisplayFrame  = fbLayer.displayFrame;
    float fbLayerArea = ((fbDisplayFrame.right - fbDisplayFrame.left)*
              (fbDisplayFrame.bottom - fbDisplayFrame.top));

    //Compute sum of the Areas of FB layers intersecting with Union Dirty Rect
    for (size_t i=0; i<disp.list->numHwLayers-1; i++) {
        hwc_layer_1_t& layer = disp.list->hwLayers[i];
        if(layer.compositionType != HWC_FRAMEBUFFER)
           continue;

        hwc_rect_t displayFrame  = layer.displayFrame;
        Rect df(displayFrame.left, displayFrame.top,
              displayFrame.right, displayFrame.bottom);
        Rect df_dirty;
        df_dirty.clear();
        if(df.intersect(unionDr, &df_dirty))
            layerAreaSum += ((df_dirty.right - df_dirty.left)*
                  (df_dirty.bottom - df_dirty.top));
    }
    ALOGD_IF(GPUTILERECT_DEBUG,"GPUTileRect: overlap/FB : %f",
           (layerAreaSum/fbLayerArea));
    // Return false, if the sum of layer Areas intersecting with union Dr is
    // more than the threshold as we are not getting better performance.
    return (mDynThreshold > (layerAreaSum/fbLayerArea));
}

bool HWComposer::needsScaling(int32_t id) {
    if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
        return false;
@@ -1413,8 +1461,10 @@ void HWComposer::computeUnionDirtyRect(int32_t id, Rect& unionDirtyRect) {
    // Find UnionDr of all layers
    for (size_t i=0; i<count; i++) {
        hwc_layer_1_t& l = disp.list->hwLayers[i];
        Rect dr(0,0,0,0);
        if(currentLayers[i]->hasNewFrame()) {
        Rect dr;
        dr.clear();
        if((l.compositionType == HWC_FRAMEBUFFER) &&
              currentLayers[i]->hasNewFrame()) {
            dr = Rect(l.dirtyRect.left, l.dirtyRect.top, l.dirtyRect.right,
                  l.dirtyRect.bottom);
            hwc_rect_t dst = l.displayFrame;
@@ -1434,7 +1484,12 @@ void HWComposer::computeUnionDirtyRect(int32_t id, Rect& unionDirtyRect) {
    }
    unionDirtyRect = unionDirtyRegion.getBounds();
}

bool HWComposer::isCompositionMapChanged(int32_t id) {
    if (prev_comp_map[id] == current_comp_map[id]) {
        return false;
    }
    return true;
}
bool HWComposer::isGeometryChanged(int32_t id) {
    if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
        return false;
@@ -1453,18 +1508,11 @@ bool HWComposer::canUseTiledDR(int32_t id, Rect& unionDr ){
    if (isGeometryChanged(id)) {
        ALOGD_IF(GPUTILERECT_DEBUG, "GPUTileRect : geometrychanged, disable");
        status = false;
    } else if ( hasHwcOrBlitComposition(id)) {
     /* Currently enabled only for full GPU Comp
      * TODO : enable for mixed mode also */
    } else if ( hasBlitComposition(id)) {
        ALOGD_IF(GPUTILERECT_DEBUG, "GPUTileRect: Blit comp, disable");
        status = false;
    } else if (areVisibleRegionsOverlapping(id)) {
      /* With DirtyRect optimiaton, On certain targets we are  seeing slightly
       * lower FPS in use cases where visible regions overlap in Full GPU Comp.
       * Hence this optimizatin has been disabled for usecases where visible
       * regions overlap. TODO : Analyse & handle overlap usecases. */
       ALOGD_IF(GPUTILERECT_DEBUG, "GPUTileRect: Visible \
             regions overlap, disable");
    } else if ( isCompositionMapChanged(id)) {
        ALOGD_IF(GPUTILERECT_DEBUG, "GPUTileRect: comp map changed, disable");
        status = false;
    } else if (needsScaling(id)) {
       /* Do Not use TiledDR optimization, if layers need scaling */
@@ -1472,8 +1520,16 @@ bool HWComposer::canUseTiledDR(int32_t id, Rect& unionDr ){
       status = false;
    } else {
        computeUnionDirtyRect(id, unionDr);
        if(unionDr.isEmpty())
        {
        if(areVisibleRegionsOverlapping(id) &&
              !canHandleOverlapArea(id, unionDr)){
           /* With DR optimizaton, On certain targets we are seeing slightly
            * lower FPS in use cases where visible regions overlap &
            * the total dirty area of layers is greater than a threshold value.
            * Hence this optimization has been disabled for such use cases */
            ALOGD_IF(GPUTILERECT_DEBUG, "GPUTileRect: Visible \
                 regions overlap & Total Dirty Area > Threashold, disable");
            status = false;
        } else if(unionDr.isEmpty()) {
            ALOGD_IF(GPUTILERECT_DEBUG,"GPUTileRect: UnionDr is emtpy, \
                  No need to PRESERVE");
            status = false;
+42 −2
Original line number Diff line number Diff line
@@ -32,6 +32,8 @@
#include <utils/Timers.h>
#include <utils/Vector.h>

#define MAX_LAYER_COUNT 32

extern "C" int clock_nanosleep(clockid_t clock_id, int flags,
                           const struct timespec *request,
                           struct timespec *remain);
@@ -118,8 +120,8 @@ public:
    bool hasGlesComposition(int32_t id) const;

#ifdef QCOM_BSP
    // does this display have layers handled by overlays/blit
    bool hasHwcOrBlitComposition(int32_t id) const;
    // does this display have layers handled by BLIT HW
    bool hasBlitComposition(int32_t id) const;

    //GPUTiledRect : function to find out if DR can be used in GPU Comp.
    bool canUseTiledDR(int32_t id, Rect& dr);
@@ -388,12 +390,50 @@ private:
    // thread-safe
    mutable Mutex mEventControlLock;

    //GPUTileRect : CompMap, class to track the composition type of layers
    struct CompMap {
        int32_t count;
        int32_t compType[MAX_LAYER_COUNT];
        CompMap () {
            reset();
        }
        void reset () {
            count=0;
            for(size_t i= 0; i <MAX_LAYER_COUNT; i++) {
                compType[i] = -1;
            }
        }
        CompMap& operator=(const CompMap &rhs) {
            if(this != &rhs) {
                reset();
                count = rhs.count;
                for(int32_t i=0; i<count; i++) {
                    compType[i] = rhs.compType[i];
                }
            }
            return *this;
        }
        bool operator== (CompMap &rhs) {
            if( count != rhs.count)
                return false;
            for(int32_t i=0; i<count; i++) {
                if(compType[i] != rhs.compType[i])
                    return false;
            }
            return true;
        }
    };

#ifdef QCOM_BSP
    //GPUTileRect Optimization Functions.
    CompMap prev_comp_map[MAX_HWC_DISPLAYS], current_comp_map[MAX_HWC_DISPLAYS];
    bool isCompositionMapChanged(int32_t id);
    bool isGeometryChanged(int32_t id);
    void computeUnionDirtyRect(int32_t id, Rect& unionDirtyRect);
    bool areVisibleRegionsOverlapping(int32_t id );
    bool needsScaling(int32_t id);
    float mDynThreshold;
    bool canHandleOverlapArea(int32_t id, Rect unionDr);
#endif
};

+18 −5
Original line number Diff line number Diff line
@@ -2085,6 +2085,7 @@ bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const

    Region clearRegion;
    bool hasGlesComposition = hwc.hasGlesComposition(id);
    const bool hasHwcComposition = hwc.hasHwcComposition(id);
    if (hasGlesComposition) {
        if (!hw->makeCurrent(mEGLDisplay, mEGLContext)) {
            ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s",
@@ -2097,13 +2098,13 @@ bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const
        }

        // Never touch the framebuffer if we don't have any framebuffer layers
        const bool hasHwcComposition = hwc.hasHwcComposition(id);
        if (hasHwcComposition) {
            // when using overlays, we assume a fully transparent framebuffer
            // NOTE: we could reduce how much we need to clear, for instance
            // remove where there are opaque FB layers. however, on some
            // GPUs doing a "clean slate" clear might be more efficient.
            // We'll revisit later if needed.
            if(!(mGpuTileRenderEnable && (mDisplays.size()==1)))
                engine.clearWithColor(0, 0, 0, 0);
        } else {
            // we start with the whole screen area
@@ -2195,11 +2196,23 @@ bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const
                hw->eglSwapPreserved(false);
            }
            // DrawWormHole/Any Draw has to be within startTile & EndTile
            if (hasHwcComposition) {
                if(mCanUseGpuTileRender && !mUnionDirtyRect.isEmpty()) {
                    const Rect& scissor(mUnionDirtyRect);
                    engine.setScissor(scissor.left, hw->getHeight()- scissor.bottom,
                    scissor.getWidth(), scissor.getHeight());
                    engine.clearWithColor(0, 0, 0, 0);
                    engine.disableScissor();
                } else {
                    engine.clearWithColor(0, 0, 0, 0);
                }
            } else {
                if (cur->getCompositionType() != HWC_BLIT &&
                      !clearRegion.isEmpty()){
                    drawWormhole(hw, clearRegion);
                }
            }
        }
#endif

        for (size_t i=0 ; i<count && cur!=end ; ++i, ++cur) {