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;