Merge "libexternal: limit ext downscale to FullHD Resolution"
diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp
index 5d8da05..47d9b93 100644
--- a/libcopybit/copybit.cpp
+++ b/libcopybit/copybit.cpp
@@ -714,6 +714,10 @@
ctx->mAlpha = MDP_ALPHA_NOP;
ctx->mFlags = 0;
ctx->sync.flags = 0;
+ ctx->relFence = -1;
+ for (int i=0; i < MDP_MAX_FENCE_FD; i++) {
+ ctx->acqFence[i] = -1;
+ }
ctx->sync.acq_fen_fd = ctx->acqFence;
ctx->sync.rel_fen_fd = &ctx->relFence;
ctx->list.count = 0;
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index bb1b032..bb6a49c 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -178,13 +178,14 @@
hwc_layer_1_t *layer = (hwc_layer_1_t *) &list->hwLayers[i];
if (layer->planeAlpha != 0xFF)
return true;
+ hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
if (layer->transform & HAL_TRANSFORM_ROT_90) {
- src_h = layer->sourceCrop.right - layer->sourceCrop.left;
- src_w = layer->sourceCrop.bottom - layer->sourceCrop.top;
+ src_h = sourceCrop.right - sourceCrop.left;
+ src_w = sourceCrop.bottom - sourceCrop.top;
} else {
- src_h = layer->sourceCrop.bottom - layer->sourceCrop.top;
- src_w = layer->sourceCrop.right - layer->sourceCrop.left;
+ src_h = sourceCrop.bottom - sourceCrop.top;
+ src_w = sourceCrop.right - sourceCrop.left;
}
dst_h = layer->displayFrame.bottom - layer->displayFrame.top;
dst_w = layer->displayFrame.right - layer->displayFrame.left;
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 7d4fa3e..a0b9646 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -43,8 +43,9 @@
bool MDPComp::sEnableMixedMode = true;
bool MDPComp::sEnablePartialFrameUpdate = false;
int MDPComp::sMaxPipesPerMixer = MAX_PIPES_PER_MIXER;
-float MDPComp::sMaxBw = 2.3f;
+double MDPComp::sMaxBw = 0.0;
double MDPComp::sBwClaimed = 0.0;
+bool MDPComp::sEnable4k2kYUVSplit = false;
MDPComp* MDPComp::getObject(hwc_context_t *ctx, const int& dpy) {
if(isDisplaySplit(ctx, dpy)) {
@@ -128,13 +129,6 @@
sMaxPipesPerMixer = min(val, MAX_PIPES_PER_MIXER);
}
- if(property_get("debug.mdpcomp.bw", property, "0") > 0) {
- float val = atof(property);
- if(val > 0.0f) {
- sMaxBw = val;
- }
- }
-
if(ctx->mMDP.panel != MIPI_CMD_PANEL) {
// Idle invalidation is not necessary on command mode panels
long idle_timeout = DEFAULT_IDLE_TIME;
@@ -154,6 +148,12 @@
idleInvalidator->init(timeout_handler, ctx, idle_timeout);
}
}
+
+ if((property_get("debug.mdpcomp.4k2kSplit", property, "0") > 0) &&
+ (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
+ (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+ sEnable4k2kYUVSplit = true;
+ }
return true;
}
@@ -594,6 +594,10 @@
mCurrentFrame.mdpCount = mCurrentFrame.layerCount - mCurrentFrame.fbCount -
mCurrentFrame.dropCount;
+ if(sEnable4k2kYUVSplit){
+ modifymdpCountfor4k2k(ctx, list);
+ }
+
if(!resourceCheck(ctx, list)) {
ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
return false;
@@ -649,6 +653,10 @@
int mdpCount = mCurrentFrame.mdpCount;
+ if(sEnable4k2kYUVSplit){
+ modifymdpCountfor4k2k(ctx, list);
+ }
+
//Will benefit cases where a video has non-updating background.
if((mDpy > HWC_DISPLAY_PRIMARY) and
(mdpCount > MAX_SEC_LAYERS)) {
@@ -719,6 +727,10 @@
mCurrentFrame.fbCount = batchSize;
mCurrentFrame.mdpCount = mCurrentFrame.layerCount - batchSize;
+ if(sEnable4k2kYUVSplit){
+ modifymdpCountfor4k2k(ctx, list);
+ }
+
if(!resourceCheck(ctx, list)) {
ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
return false;
@@ -770,6 +782,10 @@
mCurrentFrame.fbCount = fbBatchSize;
mCurrentFrame.mdpCount = mCurrentFrame.layerCount - fbBatchSize;
+ if(sEnable4k2kYUVSplit){
+ modifymdpCountfor4k2k(ctx, list);
+ }
+
if(!resourceCheck(ctx, list)) {
ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
return false;
@@ -1098,10 +1114,23 @@
MdpPipeInfo* cur_pipe = mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
cur_pipe->zOrder = mdpNextZOrder++;
-
+ private_handle_t *hnd = (private_handle_t *)layer->handle;
+ if(is4kx2kYuvBuffer(hnd) && sEnable4k2kYUVSplit){
+ if(configure4k2kYuv(ctx, layer,
+ mCurrentFrame.mdpToLayer[mdpIndex])
+ != 0 ){
+ ALOGD_IF(isDebug(), "%s: Failed to configure split pipes \
+ for layer %d",__FUNCTION__, index);
+ return false;
+ }
+ else{
+ mdpNextZOrder++;
+ }
+ continue;
+ }
if(configure(ctx, layer, mCurrentFrame.mdpToLayer[mdpIndex]) != 0 ){
ALOGD_IF(isDebug(), "%s: Failed to configure overlay for \
- layer %d",__FUNCTION__, index);
+ layer %d",__FUNCTION__, index);
return false;
}
}
@@ -1125,6 +1154,20 @@
mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
cur_pipe->zOrder = mdpIdx++;
+ private_handle_t *hnd = (private_handle_t *)layer->handle;
+ if(is4kx2kYuvBuffer(hnd) && sEnable4k2kYUVSplit){
+ if(configure4k2kYuv(ctx, layer,
+ mCurrentFrame.mdpToLayer[mdpIndex])
+ != 0 ){
+ ALOGD_IF(isDebug(), "%s: Failed to configure split pipes \
+ for layer %d",__FUNCTION__, index);
+ return false;
+ }
+ else{
+ mdpIdx++;
+ }
+ continue;
+ }
if(configure(ctx, layer,
mCurrentFrame.mdpToLayer[mdpIndex]) != 0 ){
ALOGD_IF(isDebug(), "%s: Failed to configure overlay for \
@@ -1148,7 +1191,7 @@
return false;
}
- uint32_t size = calcMDPBytesRead(ctx, list);
+ double size = calcMDPBytesRead(ctx, list);
if(!bandwidthCheck(ctx, size)) {
ALOGD_IF(isDebug(), "%s: Exceeds bandwidth",__FUNCTION__);
return false;
@@ -1157,12 +1200,15 @@
return true;
}
-uint32_t MDPComp::calcMDPBytesRead(hwc_context_t *ctx,
+double MDPComp::calcMDPBytesRead(hwc_context_t *ctx,
hwc_display_contents_1_t* list) {
- uint32_t size = 0;
+ double size = 0;
+ const double GIG = 1000000000.0;
- if(!qdutils::MDPVersion::getInstance().is8x74v2())
- return 0;
+ //Skip for targets where no device tree value for bw is supplied
+ if(sMaxBw <= 0.0) {
+ return 0.0;
+ }
for (uint32_t i = 0; i < list->numHwLayers - 1; i++) {
if(!mCurrentFrame.isFBComposed[i]) {
@@ -1172,33 +1218,37 @@
hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
hwc_rect_t dst = layer->displayFrame;
float bpp = ((float)hnd->size) / (hnd->width * hnd->height);
- size += bpp * (crop.right - crop.left) *
- (crop.bottom - crop.top) *
- ctx->dpyAttr[mDpy].yres / (dst.bottom - dst.top);
+ size += (bpp * (crop.right - crop.left) *
+ (crop.bottom - crop.top) *
+ ctx->dpyAttr[mDpy].yres / (dst.bottom - dst.top)) /
+ GIG;
}
}
}
if(mCurrentFrame.fbCount) {
hwc_layer_1_t* layer = &list->hwLayers[list->numHwLayers - 1];
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- if (hnd)
- size += hnd->size;
+ int tempw, temph;
+ size += (getBufferSizeAndDimensions(
+ layer->displayFrame.right - layer->displayFrame.left,
+ layer->displayFrame.bottom - layer->displayFrame.top,
+ HAL_PIXEL_FORMAT_RGBA_8888,
+ tempw, temph)) / GIG;
}
return size;
}
-bool MDPComp::bandwidthCheck(hwc_context_t *ctx, const uint32_t& size) {
- //Will be added for other targets if we run into bandwidth issues and when
- //we have profiling data to set an upper limit.
- if(qdutils::MDPVersion::getInstance().is8x74v2()) {
- const uint32_t ONE_GIG = 1000 * 1000 * 1000;
- double panelRefRate =
- 1000000000.0 / ctx->dpyAttr[mDpy].vsync_period;
- if((size * panelRefRate) > ((sMaxBw - sBwClaimed) * ONE_GIG)) {
- return false;
- }
+bool MDPComp::bandwidthCheck(hwc_context_t *ctx, const double& size) {
+ //Skip for targets where no device tree value for bw is supplied
+ if(sMaxBw <= 0.0) {
+ return true;
+ }
+
+ double panelRefRate =
+ 1000000000.0 / ctx->dpyAttr[mDpy].vsync_period;
+ if((size * panelRefRate) > (sMaxBw - sBwClaimed)) {
+ return false;
}
return true;
}
@@ -1206,6 +1256,7 @@
int MDPComp::prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
int ret = 0;
const int numLayers = ctx->listStats[mDpy].numAppLayers;
+ MDPVersion& mdpVersion = qdutils::MDPVersion::getInstance();
//reset old data
mCurrentFrame.reset(numLayers);
@@ -1233,11 +1284,31 @@
generateROI(ctx, list);
+ //Convert from kbps to gbps
+ sMaxBw = mdpVersion.getHighBw() / 1000000.0;
+ if (ctx->mExtDisplay->isConnected() || ctx->mMDP.panel != MIPI_CMD_PANEL) {
+ sMaxBw = mdpVersion.getLowBw() / 1000000.0;
+ }
+
//Check whether layers marked for MDP Composition is actually doable.
if(isFullFrameDoable(ctx, list)) {
mCurrentFrame.map();
//Configure framebuffer first if applicable
if(mCurrentFrame.fbZ >= 0) {
+ //If 4k2k Yuv layer split is possible, and if
+ //fbz is above 4k2k layer, increment fb zorder by 1
+ //as we split 4k2k layer and increment zorder for right half
+ //of the layer
+ if(sEnable4k2kYUVSplit){
+ int n4k2kYuvCount = ctx->listStats[mDpy].yuv4k2kCount;
+ for(int index = 0; index < n4k2kYuvCount; index++){
+ int n4k2kYuvIndex =
+ ctx->listStats[mDpy].yuv4k2kIndices[index];
+ if(mCurrentFrame.fbZ > n4k2kYuvIndex){
+ mCurrentFrame.fbZ += 1;
+ }
+ }
+ }
if(!ctx->mFBUpdate[mDpy]->prepare(ctx, list,
mCurrentFrame.fbZ)) {
ALOGE("%s configure framebuffer failed", __func__);
@@ -1268,6 +1339,11 @@
//Try to compose atleast YUV layers through MDP comp and let
//all the RGB layers compose in FB
//Destination over
+
+ if(sEnable4k2kYUVSplit){
+ modifymdpCountfor4k2k(ctx, list);
+ }
+
mCurrentFrame.fbZ = -1;
if(mCurrentFrame.fbCount)
mCurrentFrame.fbZ = mCurrentFrame.mdpCount;
@@ -1311,14 +1387,51 @@
}
exit:
- //gbps (bytes / nanosec = gigabytes / sec)
- sBwClaimed += calcMDPBytesRead(ctx, list) /
- (double)ctx->dpyAttr[mDpy].vsync_period;
+ double panelRefRate =
+ 1000000000.0 / ctx->dpyAttr[mDpy].vsync_period;
+ sBwClaimed += calcMDPBytesRead(ctx, list) * panelRefRate;
return ret;
}
+bool MDPComp::allocSplitVGPipesfor4k2k(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list, int index) {
+
+ bool bRet = true;
+ hwc_layer_1_t* layer = &list->hwLayers[index];
+ private_handle_t *hnd = (private_handle_t *)layer->handle;
+ int mdpIndex = mCurrentFrame.layerToMDP[index];
+ PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
+ info.pipeInfo = new MdpYUVPipeInfo;
+ info.rot = NULL;
+ MdpYUVPipeInfo& pipe_info = *(MdpYUVPipeInfo*)info.pipeInfo;
+ ePipeType type = MDPCOMP_OV_VG;
+
+ pipe_info.lIndex = ovutils::OV_INVALID;
+ pipe_info.rIndex = ovutils::OV_INVALID;
+
+ pipe_info.lIndex = getMdpPipe(ctx, type, Overlay::MIXER_DEFAULT);
+ if(pipe_info.lIndex == ovutils::OV_INVALID){
+ bRet = false;
+ ALOGD_IF(isDebug(),"%s: allocating first VG pipe failed",
+ __FUNCTION__);
+ }
+ pipe_info.rIndex = getMdpPipe(ctx, type, Overlay::MIXER_DEFAULT);
+ if(pipe_info.rIndex == ovutils::OV_INVALID){
+ bRet = false;
+ ALOGD_IF(isDebug(),"%s: allocating second VG pipe failed",
+ __FUNCTION__);
+ }
+ return bRet;
+}
//=============MDPCompNonSplit===================================================
+void MDPCompNonSplit::modifymdpCountfor4k2k(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list){
+ //As we split 4kx2k yuv layer and program to 2 VG pipes
+ //(if available) increase mdpcount accordingly
+ mCurrentFrame.mdpCount += ctx->listStats[mDpy].yuv4k2kCount;
+}
+
/*
* Configures pipe(s) for MDP composition
*/
@@ -1370,7 +1483,10 @@
hwc_layer_1_t* layer = &list->hwLayers[i];
hwc_rect_t dst = layer->displayFrame;
private_handle_t *hnd = (private_handle_t *)layer->handle;
- if(isYuvBuffer(hnd)) {
+ if(is4kx2kYuvBuffer(hnd) && sEnable4k2kYUVSplit){
+ pipesNeeded = pipesNeeded + 2;
+ }
+ else if(isYuvBuffer(hnd)) {
pipesNeeded++;
}
}
@@ -1395,6 +1511,12 @@
hwc_layer_1_t* layer = &list->hwLayers[index];
private_handle_t *hnd = (private_handle_t *)layer->handle;
+ if(is4kx2kYuvBuffer(hnd) && sEnable4k2kYUVSplit){
+ if(allocSplitVGPipesfor4k2k(ctx, list, index)){
+ continue;
+ }
+ }
+
int mdpIndex = mCurrentFrame.layerToMDP[index];
PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
info.pipeInfo = new MdpPipeInfoNonSplit;
@@ -1420,6 +1542,20 @@
return true;
}
+int MDPCompNonSplit::configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
+ PipeLayerPair& PipeLayerPair) {
+ MdpYUVPipeInfo& mdp_info =
+ *(static_cast<MdpYUVPipeInfo*>(PipeLayerPair.pipeInfo));
+ eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
+ eIsFg isFg = IS_FG_OFF;
+ eMdpFlags mdpFlagsL = OV_MDP_BACKEND_COMPOSITION;
+ eDest lDest = mdp_info.lIndex;
+ eDest rDest = mdp_info.rIndex;
+
+ return configureSourceSplit(ctx, layer, mDpy, mdpFlagsL, zOrder, isFg,
+ lDest, rDest, &PipeLayerPair.rot);
+}
+
bool MDPCompNonSplit::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
if(!isEnabled()) {
@@ -1463,36 +1599,75 @@
int mdpIndex = mCurrentFrame.layerToMDP[i];
- MdpPipeInfoNonSplit& pipe_info =
+ if(is4kx2kYuvBuffer(hnd) && sEnable4k2kYUVSplit)
+ {
+ MdpYUVPipeInfo& pipe_info =
+ *(MdpYUVPipeInfo*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
+ Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
+ ovutils::eDest indexL = pipe_info.lIndex;
+ ovutils::eDest indexR = pipe_info.rIndex;
+ int fd = hnd->fd;
+ uint32_t offset = hnd->offset;
+ if(rot) {
+ rot->queueBuffer(fd, offset);
+ fd = rot->getDstMemId();
+ offset = rot->getDstOffset();
+ }
+ if(indexL != ovutils::OV_INVALID) {
+ ovutils::eDest destL = (ovutils::eDest)indexL;
+ ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
+ using pipe: %d", __FUNCTION__, layer, hnd, indexL );
+ if (!ov.queueBuffer(fd, offset, destL)) {
+ ALOGE("%s: queueBuffer failed for display:%d",
+ __FUNCTION__, mDpy);
+ return false;
+ }
+ }
+
+ if(indexR != ovutils::OV_INVALID) {
+ ovutils::eDest destR = (ovutils::eDest)indexR;
+ ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
+ using pipe: %d", __FUNCTION__, layer, hnd, indexR );
+ if (!ov.queueBuffer(fd, offset, destR)) {
+ ALOGE("%s: queueBuffer failed for display:%d",
+ __FUNCTION__, mDpy);
+ return false;
+ }
+ }
+ }
+ else{
+ MdpPipeInfoNonSplit& pipe_info =
*(MdpPipeInfoNonSplit*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
- ovutils::eDest dest = pipe_info.index;
- if(dest == ovutils::OV_INVALID) {
- ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, dest);
- return false;
- }
-
- if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
- continue;
- }
-
- ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
- using pipe: %d", __FUNCTION__, layer,
- hnd, dest );
-
- int fd = hnd->fd;
- uint32_t offset = hnd->offset;
-
- Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
- if(rot) {
- if(!rot->queueBuffer(fd, offset))
+ ovutils::eDest dest = pipe_info.index;
+ if(dest == ovutils::OV_INVALID) {
+ ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, dest);
return false;
- fd = rot->getDstMemId();
- offset = rot->getDstOffset();
- }
+ }
- if (!ov.queueBuffer(fd, offset, dest)) {
- ALOGE("%s: queueBuffer failed for display:%d ", __FUNCTION__, mDpy);
- return false;
+ if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
+ continue;
+ }
+
+ ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
+ using pipe: %d", __FUNCTION__, layer,
+ hnd, dest );
+
+ int fd = hnd->fd;
+ uint32_t offset = hnd->offset;
+
+ Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
+ if(rot) {
+ if(!rot->queueBuffer(fd, offset))
+ return false;
+ fd = rot->getDstMemId();
+ offset = rot->getDstOffset();
+ }
+
+ if (!ov.queueBuffer(fd, offset, dest)) {
+ ALOGE("%s: queueBuffer failed for display:%d ",
+ __FUNCTION__, mDpy);
+ return false;
+ }
}
layerProp[i].mFlags &= ~HWC_MDPCOMP;
@@ -1502,6 +1677,23 @@
//=============MDPCompSplit===================================================
+void MDPCompSplit::modifymdpCountfor4k2k(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list){
+ //if 4kx2k yuv layer is totally present in either in left half
+ //or right half then try splitting the yuv layer to avoid decimation
+ int n4k2kYuvCount = ctx->listStats[mDpy].yuv4k2kCount;
+ const int lSplit = getLeftSplit(ctx, mDpy);
+ for(int index = 0; index < n4k2kYuvCount; index++){
+ int n4k2kYuvIndex = ctx->listStats[mDpy].yuv4k2kIndices[index];
+ hwc_layer_1_t* layer = &list->hwLayers[n4k2kYuvIndex];
+ hwc_rect_t dst = layer->displayFrame;
+
+ if((dst.left > lSplit)||(dst.right < lSplit)){
+ mCurrentFrame.mdpCount += 1;
+ }
+ }
+}
+
int MDPCompSplit::pipesNeeded(hwc_context_t *ctx,
hwc_display_contents_1_t* list,
int mixer) {
@@ -1574,6 +1766,12 @@
hwc_layer_1_t* layer = &list->hwLayers[i];
hwc_rect_t dst = layer->displayFrame;
private_handle_t *hnd = (private_handle_t *)layer->handle;
+ if(is4kx2kYuvBuffer(hnd) && sEnable4k2kYUVSplit){
+ if((dst.left > lSplit)||(dst.right < lSplit)){
+ pipesNeeded = pipesNeeded + 2;
+ continue;
+ }
+ }
if(isYuvBuffer(hnd)) {
if(dst.left < lSplit) {
pipesNeeded++;
@@ -1629,6 +1827,15 @@
hwc_layer_1_t* layer = &list->hwLayers[index];
private_handle_t *hnd = (private_handle_t *)layer->handle;
+ hwc_rect_t dst = layer->displayFrame;
+ const int lSplit = getLeftSplit(ctx, mDpy);
+ if(is4kx2kYuvBuffer(hnd) && sEnable4k2kYUVSplit){
+ if((dst.left > lSplit)||(dst.right < lSplit)){
+ if(allocSplitVGPipesfor4k2k(ctx, list, index)){
+ continue;
+ }
+ }
+ }
int mdpIndex = mCurrentFrame.layerToMDP[index];
PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
info.pipeInfo = new MdpPipeInfoSplit;
@@ -1653,6 +1860,27 @@
return true;
}
+int MDPCompSplit::configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
+ PipeLayerPair& PipeLayerPair) {
+ const int lSplit = getLeftSplit(ctx, mDpy);
+ hwc_rect_t dst = layer->displayFrame;
+ if((dst.left > lSplit)||(dst.right < lSplit)){
+ MdpYUVPipeInfo& mdp_info =
+ *(static_cast<MdpYUVPipeInfo*>(PipeLayerPair.pipeInfo));
+ eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
+ eIsFg isFg = IS_FG_OFF;
+ eMdpFlags mdpFlagsL = OV_MDP_BACKEND_COMPOSITION;
+ eDest lDest = mdp_info.lIndex;
+ eDest rDest = mdp_info.rIndex;
+
+ return configureSourceSplit(ctx, layer, mDpy, mdpFlagsL, zOrder, isFg,
+ lDest, rDest, &PipeLayerPair.rot);
+ }
+ else{
+ return configure(ctx, layer, PipeLayerPair);
+ }
+}
+
/*
* Configures pipe(s) for MDP composition
*/
@@ -1715,48 +1943,88 @@
int mdpIndex = mCurrentFrame.layerToMDP[i];
- MdpPipeInfoSplit& pipe_info =
- *(MdpPipeInfoSplit*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
- Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
+ if(is4kx2kYuvBuffer(hnd) && sEnable4k2kYUVSplit)
+ {
+ MdpYUVPipeInfo& pipe_info =
+ *(MdpYUVPipeInfo*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
+ Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
+ ovutils::eDest indexL = pipe_info.lIndex;
+ ovutils::eDest indexR = pipe_info.rIndex;
+ int fd = hnd->fd;
+ uint32_t offset = hnd->offset;
+ if(rot) {
+ rot->queueBuffer(fd, offset);
+ fd = rot->getDstMemId();
+ offset = rot->getDstOffset();
+ }
+ if(indexL != ovutils::OV_INVALID) {
+ ovutils::eDest destL = (ovutils::eDest)indexL;
+ ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
+ using pipe: %d", __FUNCTION__, layer, hnd, indexL );
+ if (!ov.queueBuffer(fd, offset, destL)) {
+ ALOGE("%s: queueBuffer failed for display:%d",
+ __FUNCTION__, mDpy);
+ return false;
+ }
+ }
- ovutils::eDest indexL = pipe_info.lIndex;
- ovutils::eDest indexR = pipe_info.rIndex;
-
- int fd = hnd->fd;
- int offset = hnd->offset;
-
- if(ctx->mAD->isModeOn()) {
- if(ctx->mAD->draw(ctx, fd, offset)) {
- fd = ctx->mAD->getDstFd(ctx);
- offset = ctx->mAD->getDstOffset(ctx);
+ if(indexR != ovutils::OV_INVALID) {
+ ovutils::eDest destR = (ovutils::eDest)indexR;
+ ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
+ using pipe: %d", __FUNCTION__, layer, hnd, indexR );
+ if (!ov.queueBuffer(fd, offset, destR)) {
+ ALOGE("%s: queueBuffer failed for display:%d",
+ __FUNCTION__, mDpy);
+ return false;
+ }
}
}
+ else{
+ MdpPipeInfoSplit& pipe_info =
+ *(MdpPipeInfoSplit*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
+ Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
- if(rot) {
- rot->queueBuffer(fd, offset);
- fd = rot->getDstMemId();
- offset = rot->getDstOffset();
- }
+ ovutils::eDest indexL = pipe_info.lIndex;
+ ovutils::eDest indexR = pipe_info.rIndex;
- //************* play left mixer **********
- if(indexL != ovutils::OV_INVALID) {
- ovutils::eDest destL = (ovutils::eDest)indexL;
- ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
- using pipe: %d", __FUNCTION__, layer, hnd, indexL );
- if (!ov.queueBuffer(fd, offset, destL)) {
- ALOGE("%s: queueBuffer failed for left mixer", __FUNCTION__);
- return false;
+ int fd = hnd->fd;
+ int offset = hnd->offset;
+
+ if(ctx->mAD->isModeOn()) {
+ if(ctx->mAD->draw(ctx, fd, offset)) {
+ fd = ctx->mAD->getDstFd(ctx);
+ offset = ctx->mAD->getDstOffset(ctx);
+ }
}
- }
- //************* play right mixer **********
- if(indexR != ovutils::OV_INVALID) {
- ovutils::eDest destR = (ovutils::eDest)indexR;
- ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
- using pipe: %d", __FUNCTION__, layer, hnd, indexR );
- if (!ov.queueBuffer(fd, offset, destR)) {
- ALOGE("%s: queueBuffer failed for right mixer", __FUNCTION__);
- return false;
+ if(rot) {
+ rot->queueBuffer(fd, offset);
+ fd = rot->getDstMemId();
+ offset = rot->getDstOffset();
+ }
+
+ //************* play left mixer **********
+ if(indexL != ovutils::OV_INVALID) {
+ ovutils::eDest destL = (ovutils::eDest)indexL;
+ ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
+ using pipe: %d", __FUNCTION__, layer, hnd, indexL );
+ if (!ov.queueBuffer(fd, offset, destL)) {
+ ALOGE("%s: queueBuffer failed for left mixer",
+ __FUNCTION__);
+ return false;
+ }
+ }
+
+ //************* play right mixer **********
+ if(indexR != ovutils::OV_INVALID) {
+ ovutils::eDest destR = (ovutils::eDest)indexR;
+ ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
+ using pipe: %d", __FUNCTION__, layer, hnd, indexR );
+ if (!ov.queueBuffer(fd, offset, destR)) {
+ ALOGE("%s: queueBuffer failed for right mixer",
+ __FUNCTION__);
+ return false;
+ }
}
}
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index adf74bb..7e646d7 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -70,6 +70,12 @@
virtual ~MdpPipeInfo(){};
};
+ struct MdpYUVPipeInfo : public MdpPipeInfo{
+ ovutils::eDest lIndex;
+ ovutils::eDest rIndex;
+ virtual ~MdpYUVPipeInfo(){};
+ };
+
/* per layer data */
struct PipeLayerPair {
MdpPipeInfo *pipeInfo;
@@ -133,7 +139,12 @@
/* Checks for pipes needed versus pipes available */
virtual bool arePipesAvailable(hwc_context_t *ctx,
hwc_display_contents_1_t* list) = 0;
-
+ /* increments mdpCount if 4k2k yuv layer split is enabled*/
+ virtual void modifymdpCountfor4k2k(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list) = 0;
+ /* configures 4kx2k yuv layer*/
+ virtual int configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
+ PipeLayerPair& PipeLayerPair) = 0;
/* set/reset flags for MDPComp */
void setMDPCompLayerFlags(hwc_context_t *ctx,
hwc_display_contents_1_t* list);
@@ -165,11 +176,11 @@
bool secureOnly);
/* checks for conditions where YUV layers cannot be bypassed */
bool isYUVDoable(hwc_context_t* ctx, hwc_layer_1_t* layer);
- /* calcs bytes read by MDP for a given frame */
- uint32_t calcMDPBytesRead(hwc_context_t *ctx,
+ /* calcs bytes read by MDP in gigs for a given frame */
+ double calcMDPBytesRead(hwc_context_t *ctx,
hwc_display_contents_1_t* list);
/* checks if the required bandwidth exceeds a certain max */
- bool bandwidthCheck(hwc_context_t *ctx, const uint32_t& size);
+ bool bandwidthCheck(hwc_context_t *ctx, const double& size);
/* generates ROI based on the modified area of the frame */
void generateROI(hwc_context_t *ctx, hwc_display_contents_1_t* list);
bool validateAndApplyROI(hwc_context_t *ctx, hwc_display_contents_1_t* list,
@@ -212,13 +223,17 @@
static bool sIdleFallBack;
static int sMaxPipesPerMixer;
//Max bandwidth. Value is in GBPS. For ex: 2.3 means 2.3GBPS
- static float sMaxBw;
+ static double sMaxBw;
//Tracks composition bandwidth claimed. Represented as the total
//w*h*bpp*fps (gigabytes-per-second) going to MDP mixers.
static double sBwClaimed;
static IdleInvalidator *idleInvalidator;
struct FrameInfo mCurrentFrame;
struct LayerCache mCachedFrame;
+ //Enable 4kx2k yuv layer split
+ static bool sEnable4k2kYUVSplit;
+ bool allocSplitVGPipesfor4k2k(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list, int index);
};
class MDPCompNonSplit : public MDPComp {
@@ -248,6 +263,14 @@
/* Checks for video pipes needed versus pipes available */
virtual bool areVGPipesAvailable(hwc_context_t *ctx,
hwc_display_contents_1_t* list);
+
+ /* increments mdpCount if 4k2k yuv layer split is enabled*/
+ virtual void modifymdpCountfor4k2k(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list);
+
+ /* configures 4kx2k yuv layer to 2 VG pipes*/
+ virtual int configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
+ PipeLayerPair& PipeLayerPair);
};
class MDPCompSplit : public MDPComp {
@@ -281,6 +304,14 @@
virtual bool areVGPipesAvailable(hwc_context_t *ctx,
hwc_display_contents_1_t* list);
+ /* increments mdpCount if 4k2k yuv layer split is enabled*/
+ virtual void modifymdpCountfor4k2k(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list);
+
+ /* configures 4kx2k yuv layer*/
+ virtual int configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
+ PipeLayerPair& PipeLayerPair);
+
int pipesNeeded(hwc_context_t *ctx, hwc_display_contents_1_t* list,
int mixer);
};
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index eed6e9d..1167f3a 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -743,6 +743,7 @@
ctx->listStats[dpy].roi = ovutils::Dim(0, 0,
(int)ctx->dpyAttr[dpy].xres, (int)ctx->dpyAttr[dpy].yres);
ctx->listStats[dpy].secureUI = false;
+ ctx->listStats[dpy].yuv4k2kCount = 0;
trimList(ctx, list, dpy);
optimizeLayerRects(ctx, list, dpy);
@@ -765,6 +766,7 @@
//reset yuv indices
ctx->listStats[dpy].yuvIndices[i] = -1;
+ ctx->listStats[dpy].yuv4k2kIndices[i] = -1;
if (isSecureBuffer(hnd)) {
ctx->listStats[dpy].isSecurePresent = true;
@@ -779,6 +781,12 @@
ctx->listStats[dpy].yuvIndices[yuvCount] = i;
yuvCount++;
+ if(UNLIKELY(is4kx2kYuvBuffer(hnd))){
+ int& yuv4k2kCount = ctx->listStats[dpy].yuv4k2kCount;
+ ctx->listStats[dpy].yuv4k2kIndices[yuv4k2kCount] = i;
+ yuv4k2kCount++;
+ }
+
if((layer->transform & HWC_TRANSFORM_ROT_90) &&
canUseRotator(ctx, dpy)) {
if( (dpy == HWC_DISPLAY_PRIMARY) &&
@@ -1722,6 +1730,129 @@
return 0;
}
+int configureSourceSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
+ const int& dpy, eMdpFlags& mdpFlagsL, eZorder& z,
+ eIsFg& isFg, const eDest& lDest, const eDest& rDest,
+ Rotator **rot) {
+ private_handle_t *hnd = (private_handle_t *)layer->handle;
+ if(!hnd) {
+ ALOGE("%s: layer handle is NULL", __FUNCTION__);
+ return -1;
+ }
+
+ MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+
+ int hw_w = ctx->dpyAttr[dpy].xres;
+ int hw_h = ctx->dpyAttr[dpy].yres;
+ hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);;
+ hwc_rect_t dst = layer->displayFrame;
+ int transform = layer->transform;
+ eTransform orient = static_cast<eTransform>(transform);
+ const int downscale = 0;
+ int rotFlags = ROT_FLAGS_NONE;
+ //Splitting only YUV layer on primary panel needs different zorders
+ //for both layers as both the layers are configured to single mixer
+ eZorder lz = z;
+ eZorder rz = (eZorder)(z + 1);
+
+ Whf whf(getWidth(hnd), getHeight(hnd),
+ getMdpFormat(hnd->format), hnd->size);
+
+ setMdpFlags(layer, mdpFlagsL, 0, transform);
+ trimLayer(ctx, dpy, transform, crop, dst);
+
+ if(isYuvBuffer(hnd) && (transform & HWC_TRANSFORM_ROT_90)) {
+ (*rot) = ctx->mRotMgr->getNext();
+ if((*rot) == NULL) return -1;
+ if(!dpy)
+ BwcPM::setBwc(ctx, crop, dst, transform, mdpFlagsL);
+ //Configure rotator for pre-rotation
+ if(configRotator(*rot, whf, crop, mdpFlagsL, orient, downscale) < 0) {
+ ALOGE("%s: configRotator failed!", __FUNCTION__);
+ ctx->mOverlay->clear(dpy);
+ return -1;
+ }
+ ctx->mLayerRotMap[dpy]->add(layer, *rot);
+ whf.format = (*rot)->getDstFormat();
+ updateSource(orient, whf, crop);
+ rotFlags |= ROT_PREROTATED;
+ }
+
+ eMdpFlags mdpFlagsR = mdpFlagsL;
+ int lSplit = dst.left + (dst.right - dst.left)/2;
+
+ hwc_rect_t tmp_cropL = {0}, tmp_dstL = {0};
+ hwc_rect_t tmp_cropR = {0}, tmp_dstR = {0};
+
+ if(lDest != OV_INVALID) {
+ tmp_cropL = crop;
+ tmp_dstL = dst;
+ hwc_rect_t scissor = {dst.left, dst.top, lSplit, dst.bottom };
+ qhwc::calculate_crop_rects(tmp_cropL, tmp_dstL, scissor, 0);
+ }
+ if(rDest != OV_INVALID) {
+ tmp_cropR = crop;
+ tmp_dstR = dst;
+ hwc_rect_t scissor = {lSplit, dst.top, dst.right, dst.bottom };
+ qhwc::calculate_crop_rects(tmp_cropR, tmp_dstR, scissor, 0);
+ }
+
+ sanitizeSourceCrop(tmp_cropL, tmp_cropR, hnd);
+
+ //When buffer is H-flipped, contents of mixer config also needs to swapped
+ //Not needed if the layer is confined to one half of the screen.
+ //If rotator has been used then it has also done the flips, so ignore them.
+ if((orient & OVERLAY_TRANSFORM_FLIP_H) && lDest != OV_INVALID
+ && rDest != OV_INVALID && (*rot) == NULL) {
+ hwc_rect_t new_cropR;
+ new_cropR.left = tmp_cropL.left;
+ new_cropR.right = new_cropR.left + (tmp_cropR.right - tmp_cropR.left);
+
+ hwc_rect_t new_cropL;
+ new_cropL.left = new_cropR.right;
+ new_cropL.right = tmp_cropR.right;
+
+ tmp_cropL.left = new_cropL.left;
+ tmp_cropL.right = new_cropL.right;
+
+ tmp_cropR.left = new_cropR.left;
+ tmp_cropR.right = new_cropR.right;
+
+ }
+
+ //For the mdp, since either we are pre-rotating or MDP does flips
+ orient = OVERLAY_TRANSFORM_0;
+ transform = 0;
+
+ //configure left half
+ if(lDest != OV_INVALID) {
+ PipeArgs pargL(mdpFlagsL, whf, lz, isFg,
+ static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
+ (ovutils::eBlending) getBlending(layer->blending));
+
+ if(configMdp(ctx->mOverlay, pargL, orient,
+ tmp_cropL, tmp_dstL, metadata, lDest) < 0) {
+ ALOGE("%s: commit failed for left half config", __FUNCTION__);
+ return -1;
+ }
+ }
+
+ //configure right half
+ if(rDest != OV_INVALID) {
+ PipeArgs pargR(mdpFlagsR, whf, rz, isFg,
+ static_cast<eRotFlags>(rotFlags),
+ layer->planeAlpha,
+ (ovutils::eBlending) getBlending(layer->blending));
+ if(configMdp(ctx->mOverlay, pargR, orient,
+ tmp_cropR, tmp_dstR, metadata, rDest) < 0) {
+ ALOGE("%s: commit failed for right half config", __FUNCTION__);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
bool canUseRotator(hwc_context_t *ctx, int dpy) {
if(qdutils::MDPVersion::getInstance().is8x26() &&
ctx->mVirtualDisplay->isConnected() &&
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 6288057..29b38fc 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -99,6 +99,8 @@
int extOnlyLayerIndex;
bool needsAlphaScale;
bool preMultipliedAlpha;
+ int yuv4k2kIndices[MAX_NUM_APP_LAYERS];
+ int yuv4k2kCount;
// Notifies hwcomposer about the start and end of animation
// This will be set to true during animation, otherwise false.
bool isDisplayAnimating;
@@ -287,6 +289,13 @@
ovutils::eIsFg& isFg, const ovutils::eDest& lDest,
const ovutils::eDest& rDest, overlay::Rotator **rot);
+//Routine to split and configure high resolution YUV layer (> 2048 width)
+int configureSourceSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
+ const int& dpy,
+ ovutils::eMdpFlags& mdpFlags, ovutils::eZorder& z,
+ ovutils::eIsFg& isFg, const ovutils::eDest& lDest,
+ const ovutils::eDest& rDest, overlay::Rotator **rot);
+
//On certain targets DMA pipes are used for rotation and they won't be available
//for line operations. On a per-target basis we can restrict certain use cases
//from using rotator, since we know before-hand that such scenarios can lead to
@@ -309,6 +318,12 @@
return (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO));
}
+// Returns true if the buffer is yuv
+static inline bool is4kx2kYuvBuffer(const private_handle_t* hnd) {
+ return (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO) &&
+ (hnd->width > 2048));
+}
+
// Returns true if the buffer is secure
static inline bool isSecureBuffer(const private_handle_t* hnd) {
return (hnd && (private_handle_t::PRIV_FLAGS_SECURE_BUFFER & hnd->flags));
diff --git a/libqdutils/mdp_version.cpp b/libqdutils/mdp_version.cpp
index 0809fd0..e12b319 100644
--- a/libqdutils/mdp_version.cpp
+++ b/libqdutils/mdp_version.cpp
@@ -48,6 +48,8 @@
mMDPUpscale = 0;
mMDPDownscale = 0;
mPanelType = NO_PANEL;
+ mLowBw = 0;
+ mHighBw = 0;
if(!updatePanelInfo()) {
ALOGE("Unable to read Primary Panel Information");
@@ -168,8 +170,13 @@
else if(!strncmp(tokens[0], "max_upscale_ratio",
strlen("max_upscale_ratio"))) {
mMDPUpscale = atoi(tokens[1]);
- }
- else if(!strncmp(tokens[0], "features", strlen("features"))) {
+ } else if(!strncmp(tokens[0], "max_bandwidth_low",
+ strlen("max_bandwidth_low"))) {
+ mLowBw = atol(tokens[1]);
+ } else if(!strncmp(tokens[0], "max_bandwidth_high",
+ strlen("max_bandwidth_high"))) {
+ mHighBw = atol(tokens[1]);
+ } else if(!strncmp(tokens[0], "features", strlen("features"))) {
for(int i=1; i<index;i++) {
if(!strncmp(tokens[i], "bwc", strlen("bwc"))) {
mFeatures |= MDP_BWC_EN;
@@ -191,6 +198,9 @@
mRGBPipes, mVGPipes);
ALOGD_IF(DEBUG, "%s:mDMAPipes:%d \t mMDPDownscale:%d, mFeatures:%d",
__FUNCTION__, mDMAPipes, mMDPDownscale, mFeatures);
+ ALOGD_IF(DEBUG, "%s:mLowBw: %lu mHighBw: %lu", __FUNCTION__, mLowBw,
+ mHighBw);
+
return true;
}
diff --git a/libqdutils/mdp_version.h b/libqdutils/mdp_version.h
index 1e1e35e..fb7920e 100644
--- a/libqdutils/mdp_version.h
+++ b/libqdutils/mdp_version.h
@@ -113,6 +113,8 @@
bool is8x92();
int getLeftSplit() { return mSplit.left(); }
int getRightSplit() { return mSplit.right(); }
+ unsigned long getLowBw() { return mLowBw; }
+ unsigned long getHighBw() { return mHighBw; }
private:
bool updateSysFsInfo();
bool updatePanelInfo();
@@ -131,6 +133,8 @@
uint32_t mMDPDownscale;
uint32_t mMDPUpscale;
Split mSplit;
+ unsigned long mLowBw; //kbps
+ unsigned long mHighBw; //kbps
};
}; //namespace qdutils
#endif //INCLUDE_LIBQCOMUTILS_MDPVER