Merge "hwc/overlay: Prevent pipes from switching mixers"
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index 04a1716..7ba2ddc 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -21,13 +21,14 @@
 #define DEBUG_FBUPDATE 0
 #include <cutils/properties.h>
 #include <gralloc_priv.h>
+#include <overlay.h>
 #include <overlayRotator.h>
 #include "hwc_fbupdate.h"
 #include "mdp_version.h"
 #include "external.h"
 
 using namespace qdutils;
-
+using namespace overlay;
 using overlay::Rotator;
 
 namespace qhwc {
@@ -89,7 +90,7 @@
             //For 8x26 external always use DMA pipe
             type = ovutils::OV_MDP_PIPE_DMA;
         }
-        ovutils::eDest dest = ov.nextPipe(type, mDpy);
+        ovutils::eDest dest = ov.nextPipe(type, mDpy, Overlay::MIXER_DEFAULT);
         if(dest == ovutils::OV_INVALID) { //None available
             ALOGE("%s: No pipes available to configure fb for dpy %d",
                 __FUNCTION__, mDpy);
@@ -244,14 +245,16 @@
                           ovutils::getMdpFormat(hnd->format), hnd->size);
 
         //Request left pipe
-        ovutils::eDest destL = ov.nextPipe(ovutils::OV_MDP_PIPE_ANY, mDpy);
+        ovutils::eDest destL = ov.nextPipe(ovutils::OV_MDP_PIPE_ANY, mDpy,
+                Overlay::MIXER_LEFT);
         if(destL == ovutils::OV_INVALID) { //None available
             ALOGE("%s: No pipes available to configure fb for dpy %d's left"
                     " mixer", __FUNCTION__, mDpy);
             return false;
         }
         //Request right pipe
-        ovutils::eDest destR = ov.nextPipe(ovutils::OV_MDP_PIPE_ANY, mDpy);
+        ovutils::eDest destR = ov.nextPipe(ovutils::OV_MDP_PIPE_ANY, mDpy,
+                Overlay::MIXER_RIGHT);
         if(destR == ovutils::OV_INVALID) { //None available
             ALOGE("%s: No pipes available to configure fb for dpy %d's right"
                     " mixer", __FUNCTION__, mDpy);
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 0f34cd4..462cc6d 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -338,19 +338,20 @@
     return true;
 }
 
-ovutils::eDest MDPComp::getMdpPipe(hwc_context_t *ctx, ePipeType type) {
+ovutils::eDest MDPComp::getMdpPipe(hwc_context_t *ctx, ePipeType type,
+        int mixer) {
     overlay::Overlay& ov = *ctx->mOverlay;
     ovutils::eDest mdp_pipe = ovutils::OV_INVALID;
 
     switch(type) {
     case MDPCOMP_OV_DMA:
-        mdp_pipe = ov.nextPipe(ovutils::OV_MDP_PIPE_DMA, mDpy);
+        mdp_pipe = ov.nextPipe(ovutils::OV_MDP_PIPE_DMA, mDpy, mixer);
         if(mdp_pipe != ovutils::OV_INVALID) {
             return mdp_pipe;
         }
     case MDPCOMP_OV_ANY:
     case MDPCOMP_OV_RGB:
-        mdp_pipe = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, mDpy);
+        mdp_pipe = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, mDpy, mixer);
         if(mdp_pipe != ovutils::OV_INVALID) {
             return mdp_pipe;
         }
@@ -360,7 +361,7 @@
             break;
         }
     case  MDPCOMP_OV_VG:
-        return ov.nextPipe(ovutils::OV_MDP_PIPE_VG, mDpy);
+        return ov.nextPipe(ovutils::OV_MDP_PIPE_VG, mDpy, mixer);
     default:
         ALOGE("%s: Invalid pipe type",__FUNCTION__);
         return ovutils::OV_INVALID;
@@ -475,12 +476,7 @@
         return false;
     }
 
-    int numPipesNeeded = pipesNeeded(ctx, list);
-    int availPipes = getAvailablePipes(ctx);
-
-    if(numPipesNeeded > availPipes) {
-        ALOGD_IF(isDebug(), "%s: Insufficient MDP pipes, needed %d, avail %d",
-                __FUNCTION__, numPipesNeeded, availPipes);
+    if(!arePipesAvailable(ctx, list)) {
         return false;
     }
 
@@ -508,12 +504,7 @@
         return false;
     }
 
-    int numPipesNeeded = pipesNeeded(ctx, list);
-    int availPipes = getAvailablePipes(ctx);
-
-    if(numPipesNeeded > availPipes) {
-        ALOGD_IF(isDebug(), "%s: Insufficient MDP pipes, needed %d, avail %d",
-                __FUNCTION__, numPipesNeeded, availPipes);
+    if(!arePipesAvailable(ctx, list)) {
         return false;
     }
 
@@ -540,11 +531,7 @@
         return false;
     }
 
-    int numPipesNeeded = pipesNeeded(ctx, list);
-    int availPipes = getAvailablePipes(ctx);
-    if(numPipesNeeded > availPipes) {
-        ALOGD_IF(isDebug(), "%s: Insufficient MDP pipes, needed %d, avail %d",
-                __FUNCTION__, numPipesNeeded, availPipes);
+    if(!arePipesAvailable(ctx, list)) {
         return false;
     }
 
@@ -646,23 +633,6 @@
     ALOGD_IF(isDebug(),"%s: cached count: %d",__FUNCTION__, numCacheableLayers);
 }
 
-int MDPComp::getAvailablePipes(hwc_context_t* ctx) {
-    int numDMAPipes = qdutils::MDPVersion::getInstance().getDMAPipes();
-    overlay::Overlay& ov = *ctx->mOverlay;
-
-    int numAvailable = ov.availablePipes(mDpy);
-
-    //Reserve DMA for rotator
-    if(Overlay::getDMAMode() == Overlay::DMA_BLOCK_MODE)
-        numAvailable -= numDMAPipes;
-
-    //Reserve pipe(s)for FB
-    if(mCurrentFrame.fbCount)
-        numAvailable -= pipesForFB();
-
-    return numAvailable;
-}
-
 void MDPComp::updateYUV(hwc_context_t* ctx, hwc_display_contents_1_t* list) {
 
     int nYuvCount = ctx->listStats[mDpy].yuvCount;
@@ -875,9 +845,23 @@
                            &PipeLayerPair.rot);
 }
 
-int MDPCompLowRes::pipesNeeded(hwc_context_t *ctx,
-                               hwc_display_contents_1_t* list) {
-    return mCurrentFrame.mdpCount;
+bool MDPCompLowRes::arePipesAvailable(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
+    overlay::Overlay& ov = *ctx->mOverlay;
+    int numPipesNeeded = mCurrentFrame.mdpCount;
+    int availPipes = ov.availablePipes(mDpy, Overlay::MIXER_DEFAULT);
+
+    //Reserve pipe for FB
+    if(mCurrentFrame.fbCount)
+        availPipes -= 1;
+
+    if(numPipesNeeded > availPipes) {
+        ALOGD_IF(isDebug(), "%s: Insufficient pipes, dpy %d needed %d, avail %d",
+                __FUNCTION__, mDpy, numPipesNeeded, availPipes);
+        return false;
+    }
+
+    return true;
 }
 
 bool MDPCompLowRes::allocLayerPipes(hwc_context_t *ctx,
@@ -903,7 +887,7 @@
             type = MDPCOMP_OV_DMA;
         }
 
-        pipe_info.index = getMdpPipe(ctx, type);
+        pipe_info.index = getMdpPipe(ctx, type, Overlay::MIXER_DEFAULT);
         if(pipe_info.index == ovutils::OV_INVALID) {
             ALOGD_IF(isDebug(), "%s: Unable to get pipe type = %d",
                 __FUNCTION__, (int) type);
@@ -992,7 +976,8 @@
 //=============MDPCompHighRes===================================================
 
 int MDPCompHighRes::pipesNeeded(hwc_context_t *ctx,
-        hwc_display_contents_1_t* list) {
+        hwc_display_contents_1_t* list,
+        int mixer) {
     int pipesNeeded = 0;
     const int xres = ctx->dpyAttr[mDpy].xres;
     //Default even split for all displays with high res
@@ -1007,18 +992,38 @@
         if(!mCurrentFrame.isFBComposed[i]) {
             hwc_layer_1_t* layer = &list->hwLayers[i];
             hwc_rect_t dst = layer->displayFrame;
-            if(dst.left > lSplit) {
+            if(mixer == Overlay::MIXER_LEFT && dst.left < lSplit) {
                 pipesNeeded++;
-            } else if(dst.right <= lSplit) {
+            } else if(mixer == Overlay::MIXER_RIGHT && dst.right > lSplit) {
                 pipesNeeded++;
-            } else {
-                pipesNeeded += 2;
             }
         }
     }
     return pipesNeeded;
 }
 
+bool MDPCompHighRes::arePipesAvailable(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
+    overlay::Overlay& ov = *ctx->mOverlay;
+
+    for(int i = 0; i < Overlay::MIXER_MAX; i++) {
+        int numPipesNeeded = pipesNeeded(ctx, list, i);
+        int availPipes = ov.availablePipes(mDpy, i);
+
+        //Reserve pipe(s)for FB
+        if(mCurrentFrame.fbCount)
+            availPipes -= 1;
+
+        if(numPipesNeeded > availPipes) {
+            ALOGD_IF(isDebug(), "%s: Insufficient pipes for "
+                     "dpy %d mixer %d needed %d, avail %d",
+                     __FUNCTION__, mDpy, i, numPipesNeeded, availPipes);
+            return false;
+        }
+    }
+    return true;
+}
+
 bool MDPCompHighRes::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
         MdpPipeInfoHighRes& pipe_info,
         ePipeType type) {
@@ -1032,23 +1037,21 @@
     }
 
     hwc_rect_t dst = layer->displayFrame;
-    if(dst.left > lSplit) {
-        pipe_info.lIndex = ovutils::OV_INVALID;
-        pipe_info.rIndex = getMdpPipe(ctx, type);
-        if(pipe_info.rIndex == ovutils::OV_INVALID)
-            return false;
-    } else if (dst.right <= lSplit) {
-        pipe_info.rIndex = ovutils::OV_INVALID;
-        pipe_info.lIndex = getMdpPipe(ctx, type);
+    pipe_info.lIndex = ovutils::OV_INVALID;
+    pipe_info.rIndex = ovutils::OV_INVALID;
+
+    if (dst.left < lSplit) {
+        pipe_info.lIndex = getMdpPipe(ctx, type, Overlay::MIXER_LEFT);
         if(pipe_info.lIndex == ovutils::OV_INVALID)
             return false;
-    } else {
-        pipe_info.rIndex = getMdpPipe(ctx, type);
-        pipe_info.lIndex = getMdpPipe(ctx, type);
-        if(pipe_info.rIndex == ovutils::OV_INVALID ||
-           pipe_info.lIndex == ovutils::OV_INVALID)
+    }
+
+    if(dst.right > lSplit) {
+        pipe_info.rIndex = getMdpPipe(ctx, type, Overlay::MIXER_RIGHT);
+        if(pipe_info.rIndex == ovutils::OV_INVALID)
             return false;
     }
+
     return true;
 }
 
@@ -1083,6 +1086,7 @@
     }
     return true;
 }
+
 /*
  * Configures pipe(s) for MDP composition
  */
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index cc4b76a..1385fbb 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -115,24 +115,21 @@
         void updateCounts(const FrameInfo&);
     };
 
-    /* No of pipes needed for Framebuffer */
-    virtual int pipesForFB() = 0;
-    /* calculates pipes needed for the panel */
-    virtual int pipesNeeded(hwc_context_t *ctx,
-                            hwc_display_contents_1_t* list) = 0;
     /* allocates pipe from pipe book */
     virtual bool allocLayerPipes(hwc_context_t *ctx,
                                  hwc_display_contents_1_t* list) = 0;
+    /* allocate MDP pipes from overlay */
+    ovutils::eDest getMdpPipe(hwc_context_t *ctx, ePipeType type, int mixer);
     /* configures MPD pipes */
     virtual int configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
                           PipeLayerPair& pipeLayerPair) = 0;
+    /* Checks for pipes needed versus pipes available */
+    virtual bool arePipesAvailable(hwc_context_t *ctx,
+            hwc_display_contents_1_t* list) = 0;
 
     /* set/reset flags for MDPComp */
     void setMDPCompLayerFlags(hwc_context_t *ctx,
                               hwc_display_contents_1_t* list);
-    /* allocate MDP pipes from overlay */
-    ovutils::eDest getMdpPipe(hwc_context_t *ctx, ePipeType type);
-
     /* checks for conditions where mdpcomp is not possible */
     bool isFrameDoable(hwc_context_t *ctx);
     /* checks for conditions where RGB layers cannot be bypassed */
@@ -158,8 +155,6 @@
     void updateLayerCache(hwc_context_t* ctx, hwc_display_contents_1_t* list);
     /* optimize layers for mdp comp*/
     void batchLayers();
-    /* gets available pipes for mdp comp */
-    int getAvailablePipes(hwc_context_t* ctx);
     /* updates cache map with YUV info */
     void updateYUV(hwc_context_t* ctx, hwc_display_contents_1_t* list);
     bool programMDP(hwc_context_t *ctx, hwc_display_contents_1_t* list);
@@ -190,7 +185,6 @@
         virtual ~MdpPipeInfoLowRes() {};
     };
 
-    virtual int pipesForFB() { return 1; };
     /* configure's overlay pipes for the frame */
     virtual int configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
                           PipeLayerPair& pipeLayerPair);
@@ -199,7 +193,9 @@
     virtual bool allocLayerPipes(hwc_context_t *ctx,
                                  hwc_display_contents_1_t* list);
 
-    virtual int pipesNeeded(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+    /* Checks for pipes needed versus pipes available */
+    virtual bool arePipesAvailable(hwc_context_t *ctx,
+            hwc_display_contents_1_t* list);
 };
 
 class MDPCompHighRes : public MDPComp {
@@ -217,7 +213,6 @@
     bool acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
                          MdpPipeInfoHighRes& pipe_info, ePipeType type);
 
-    virtual int pipesForFB() { return 2; };
     /* configure's overlay pipes for the frame */
     virtual int configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
                           PipeLayerPair& pipeLayerPair);
@@ -226,7 +221,12 @@
     virtual bool allocLayerPipes(hwc_context_t *ctx,
                                  hwc_display_contents_1_t* list);
 
-    virtual int pipesNeeded(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+    /* Checks for pipes needed versus pipes available */
+    virtual bool arePipesAvailable(hwc_context_t *ctx,
+            hwc_display_contents_1_t* list);
+
+    int pipesNeeded(hwc_context_t *ctx, hwc_display_contents_1_t* list,
+            int mixer);
 };
 
 }; //namespace
diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp
index 5115a5b..fac0c49 100644
--- a/liboverlay/overlay.cpp
+++ b/liboverlay/overlay.cpp
@@ -70,8 +70,9 @@
             //fds
             if(mPipeBook[i].valid()) {
                 char str[32];
-                sprintf(str, "Unset=%s dpy=%d; ",
-                        PipeBook::getDestStr((eDest)i), mPipeBook[i].mDisplay);
+                sprintf(str, "Unset=%s dpy=%d mix=%d; ",
+                        PipeBook::getDestStr((eDest)i),
+                        mPipeBook[i].mDisplay, mPipeBook[i].mMixer);
 #if PIPE_DEBUG
                 strncat(mDumpStr, str, strlen(str));
 #endif
@@ -83,46 +84,41 @@
     PipeBook::save();
 }
 
-eDest Overlay::nextPipe(eMdpPipeType type, int dpy) {
+eDest Overlay::nextPipe(eMdpPipeType type, int dpy, int mixer) {
     eDest dest = OV_INVALID;
 
     for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
-        //Match requested pipe type
-        if(type == OV_MDP_PIPE_ANY || type == PipeBook::getPipeType((eDest)i)) {
-            //If the pipe is not allocated to any display or used by the
-            //requesting display already in previous round.
-            if((mPipeBook[i].mDisplay == DPY_UNUSED ||
-                    mPipeBook[i].mDisplay == dpy) &&
-                    PipeBook::isNotAllocated(i)) {
-                //In block mode we don't allow line operations
-                if(sDMAMode == DMA_BLOCK_MODE &&
-                    PipeBook::getPipeType((eDest)i) == OV_MDP_PIPE_DMA)
-                    continue;
-
-                dest = (eDest)i;
-                PipeBook::setAllocation(i);
-                break;
-            }
+        if( (type == OV_MDP_PIPE_ANY || //Pipe type match
+             type == PipeBook::getPipeType((eDest)i)) &&
+            (mPipeBook[i].mDisplay == DPY_UNUSED || //Free or same display
+             mPipeBook[i].mDisplay == dpy) &&
+            (mPipeBook[i].mMixer == MIXER_UNUSED || //Free or same mixer
+             mPipeBook[i].mMixer == mixer) &&
+            PipeBook::isNotAllocated(i) && //Free pipe
+            !(sDMAMode == DMA_BLOCK_MODE && //DMA pipe in Line mode
+               PipeBook::getPipeType((eDest)i) == OV_MDP_PIPE_DMA)) {
+            dest = (eDest)i;
+            PipeBook::setAllocation(i);
+            break;
         }
     }
 
     if(dest != OV_INVALID) {
         int index = (int)dest;
-        //If the pipe is not registered with any display OR if the pipe is
-        //requested again by the same display using it, then go ahead.
         mPipeBook[index].mDisplay = dpy;
+        mPipeBook[index].mMixer = mixer;
         if(not mPipeBook[index].valid()) {
             mPipeBook[index].mPipe = new GenericPipe(dpy);
             char str[32];
-            snprintf(str, 32, "Set=%s dpy=%d; ",
-                     PipeBook::getDestStr(dest), dpy);
+            snprintf(str, 32, "Set=%s dpy=%d mix=%d; ",
+                     PipeBook::getDestStr(dest), dpy, mixer);
 #if PIPE_DEBUG
             strncat(mDumpStr, str, strlen(str));
 #endif
         }
     } else {
-        ALOGD_IF(PIPE_DEBUG, "Pipe unavailable type=%d display=%d",
-                (int)type, dpy);
+        ALOGD_IF(PIPE_DEBUG, "Pipe unavailable type=%d display=%d mixer=%d",
+                (int)type, dpy, mixer);
     }
 
     return dest;
@@ -376,6 +372,7 @@
 void Overlay::PipeBook::init() {
     mPipe = NULL;
     mDisplay = DPY_UNUSED;
+    mMixer = MIXER_UNUSED;
 }
 
 void Overlay::PipeBook::destroy() {
@@ -384,6 +381,7 @@
         mPipe = NULL;
     }
     mDisplay = DPY_UNUSED;
+    mMixer = MIXER_UNUSED;
 }
 
 Overlay* Overlay::sInstance = 0;
diff --git a/liboverlay/overlay.h b/liboverlay/overlay.h
index 10ae10d..63f5bf1 100644
--- a/liboverlay/overlay.h
+++ b/liboverlay/overlay.h
@@ -46,6 +46,8 @@
     //High res panels can be backed by 2 layer mixers and a single fb node.
     enum { DPY_PRIMARY, DPY_EXTERNAL, DPY_WRITEBACK, DPY_UNUSED };
     enum { DPY_MAX = DPY_UNUSED };
+    enum { MIXER_LEFT, MIXER_RIGHT, MIXER_UNUSED };
+    enum { MIXER_DEFAULT = MIXER_LEFT, MIXER_MAX = MIXER_UNUSED };
     enum { MAX_FB_DEVICES = DPY_MAX };
 
     /* dtor close */
@@ -67,8 +69,10 @@
      * is requested, the first available VG or RGB is returned. If no pipe is
      * available for the display "dpy" then INV is returned. Note: If a pipe is
      * assigned to a certain display, then it cannot be assigned to another
-     * display without being garbage-collected once */
-    utils::eDest nextPipe(utils::eMdpPipeType, int dpy);
+     * display without being garbage-collected once. To add if a pipe is
+     * asisgned to a mixer within a display it cannot be reused for another
+     * mixer without being UNSET once*/
+    utils::eDest nextPipe(utils::eMdpPipeType, int dpy, int mixer);
 
     void setSource(const utils::PipeArgs args, utils::eDest dest);
     void setCrop(const utils::Dim& d, utils::eDest dest);
@@ -82,8 +86,8 @@
     static int initOverlay();
     /* Returns the singleton instance of overlay */
     static Overlay* getInstance();
-    /* Returns available ("unallocated") pipes for a display */
-    int availablePipes(int dpy);
+    /* Returns available ("unallocated") pipes for a display's mixer */
+    int availablePipes(int dpy, int mixer);
     /* Returns if any of the requested pipe type is attached to any of the
      * displays
      */
@@ -123,6 +127,8 @@
         GenericPipe *mPipe;
         /* Display using this pipe. Refer to enums above */
         int mDisplay;
+        /* Mixer within a split display this pipe is attached to */
+        int mMixer;
 
         /* operations on bitmap */
         static bool pipeUsageUnchanged();
@@ -178,12 +184,18 @@
             PipeBook::getDestStr((utils::eDest)index));
 }
 
-inline int Overlay::availablePipes(int dpy) {
-     int avail = 0;
-     for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
-       if((mPipeBook[i].mDisplay == DPY_UNUSED ||
-           mPipeBook[i].mDisplay == dpy) && PipeBook::isNotAllocated(i)) {
-                avail++;
+inline int Overlay::availablePipes(int dpy, int mixer) {
+    int avail = 0;
+    for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
+        if( (mPipeBook[i].mDisplay == DPY_UNUSED ||
+             mPipeBook[i].mDisplay == dpy) &&
+            (mPipeBook[i].mMixer == MIXER_UNUSED ||
+             mPipeBook[i].mMixer == mixer) &&
+            PipeBook::isNotAllocated(i) &&
+            !(Overlay::getDMAMode() == Overlay::DMA_BLOCK_MODE &&
+              PipeBook::getPipeType((utils::eDest)i) ==
+              utils::OV_MDP_PIPE_DMA)) {
+            avail++;
         }
     }
     return avail;