hwc: Add support for SourceSplit
Add support for SourceSplit. The mixers are abstracted from hwc.
There would be no translations to mixer understood destinations.
1) If a layer's crop and position are < 2048, only 1 pipe can be used
irrespective of position.
2) Else 2 pipes can be used with the layer equally split, without
regard to position.
Change-Id: I501a53838d147887c1e2299366663e05320d5096
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index cc9e3b9..27abf6a 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -39,6 +39,9 @@
IFBUpdate* IFBUpdate::getObject(hwc_context_t *ctx, const int& dpy) {
if(isDisplaySplit(ctx, dpy)) {
+ if(qdutils::MDPVersion::getInstance().isSrcSplit()) {
+ return new FBSrcSplit(ctx, dpy);
+ }
return new FBUpdateSplit(ctx, dpy);
}
return new FBUpdateNonSplit(ctx, dpy);
@@ -422,5 +425,102 @@
return ret;
}
+//=================FBSrcSplit====================================
+FBSrcSplit::FBSrcSplit(hwc_context_t *ctx, const int& dpy):
+ FBUpdateSplit(ctx, dpy) {}
+
+bool FBSrcSplit::configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
+ hwc_rect_t fbUpdatingRect, int fbZorder) {
+ bool ret = false;
+ hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
+ int extOnlyLayerIndex = ctx->listStats[mDpy].extOnlyLayerIndex;
+ // ext only layer present..
+ if(extOnlyLayerIndex != -1) {
+ layer = &list->hwLayers[extOnlyLayerIndex];
+ layer->compositionType = HWC_OVERLAY;
+ }
+ overlay::Overlay& ov = *(ctx->mOverlay);
+
+ ovutils::Whf info(mAlignedFBWidth,
+ mAlignedFBHeight,
+ ovutils::getMdpFormat(HAL_PIXEL_FORMAT_RGBA_8888,
+ mTileEnabled));
+ //Request left pipe, VG first owing to higher prio
+ ovutils::eDest destL = ov.nextPipe(ovutils::OV_MDP_PIPE_VG, mDpy,
+ Overlay::MIXER_DEFAULT);
+ if(destL == ovutils::OV_INVALID) {
+ destL = ov.nextPipe(ovutils::OV_MDP_PIPE_ANY, mDpy,
+ Overlay::MIXER_DEFAULT);
+ if(destL == ovutils::OV_INVALID) {
+ 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,
+ Overlay::MIXER_DEFAULT);
+ if(destR == ovutils::OV_INVALID) {
+ ALOGE("%s: No pipes available to configure fb for dpy %d's right"
+ " mixer", __FUNCTION__, mDpy);
+ return false;
+ }
+
+ mDestLeft = destL;
+ mDestRight = destR;
+
+ ovutils::eMdpFlags mdpFlags = OV_MDP_BLEND_FG_PREMULT;
+ ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder);
+
+ ovutils::PipeArgs parg(mdpFlags,
+ info,
+ zOrder,
+ ovutils::IS_FG_OFF,
+ ovutils::ROT_FLAGS_NONE,
+ ovutils::DEFAULT_PLANE_ALPHA,
+ (ovutils::eBlending)
+ getBlending(layer->blending));
+ ov.setSource(parg, destL);
+ ov.setSource(parg, destR);
+
+ //Crop and Position are same for FB
+ ovutils::Dim cropPosL(
+ fbUpdatingRect.left,
+ fbUpdatingRect.top,
+ (fbUpdatingRect.right - fbUpdatingRect.left) / 2,
+ fbUpdatingRect.bottom - fbUpdatingRect.top);
+
+ ovutils::Dim cropPosR(
+ cropPosL.x + cropPosL.w,
+ cropPosL.y,
+ cropPosL.w,
+ cropPosL.h);
+
+ ov.setCrop(cropPosL, destL);
+ ov.setCrop(cropPosR, destR);
+ ov.setPosition(cropPosL, destL);
+ ov.setPosition(cropPosR, destR);
+
+ int transform = layer->transform;
+ ovutils::eTransform orient =
+ static_cast<ovutils::eTransform>(transform);
+ ov.setTransform(orient, destL);
+ ov.setTransform(orient, destR);
+
+ ret = true;
+ if (!ov.commit(destL)) {
+ ALOGE("%s: commit fails for left", __FUNCTION__);
+ ret = false;
+ }
+ if (!ov.commit(destR)) {
+ ALOGE("%s: commit fails for right", __FUNCTION__);
+ ret = false;
+ }
+ if(ret == false) {
+ ctx->mLayerRotMap[mDpy]->clear();
+ }
+ return ret;
+}
+
//---------------------------------------------------------------------
}; //namespace qhwc
diff --git a/libhwcomposer/hwc_fbupdate.h b/libhwcomposer/hwc_fbupdate.h
index c8347fa..545f5bd 100644
--- a/libhwcomposer/hwc_fbupdate.h
+++ b/libhwcomposer/hwc_fbupdate.h
@@ -88,13 +88,24 @@
hwc_rect_t fbUpdatingRect, int fbZorder);
bool draw(hwc_context_t *ctx, private_handle_t *hnd);
void reset();
-private:
- bool configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
+
+protected:
+ virtual bool configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
hwc_rect_t fbUpdatingRect, int fbZorder);
ovutils::eDest mDestLeft; //left pipe to draw on
ovutils::eDest mDestRight; //right pipe to draw on
};
+//Source Split Handler
+class FBSrcSplit : public FBUpdateSplit {
+public:
+ explicit FBSrcSplit(hwc_context_t *ctx, const int& dpy);
+ virtual ~FBSrcSplit() {};
+private:
+ bool configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
+ hwc_rect_t fbUpdatingRect, int fbZorder);
+};
+
}; //namespace qhwc
#endif //HWC_FBUPDATE_H
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 2356c9c..028af47 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -48,6 +48,9 @@
MDPComp* MDPComp::getObject(hwc_context_t *ctx, const int& dpy) {
if(isDisplaySplit(ctx, dpy)) {
+ if(qdutils::MDPVersion::getInstance().isSrcSplit()) {
+ return new MDPCompSrcSplit(dpy);
+ }
return new MDPCompSplit(dpy);
}
return new MDPCompNonSplit(dpy);
@@ -1825,5 +1828,183 @@
return true;
}
+
+//================MDPCompSrcSplit==============================================
+bool MDPCompSrcSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
+ MdpPipeInfoSplit& pipe_info, ePipeType /*type*/) {
+ private_handle_t *hnd = (private_handle_t *)layer->handle;
+ hwc_rect_t dst = layer->displayFrame;
+ hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
+ pipe_info.lIndex = ovutils::OV_INVALID;
+ pipe_info.rIndex = ovutils::OV_INVALID;
+
+ //If 2 pipes are staged on a single stage of a mixer, then the left pipe
+ //should have a higher priority than the right one. Pipe priorities are
+ //starting with VG0, VG1 ... , RGB0 ..., DMA1
+ //TODO Currently we acquire VG pipes for left side and RGB/DMA for right to
+ //make sure pipe priorities are satisfied. A better way is to have priority
+ //as part of overlay object and acquire any 2 pipes. Assign the higher
+ //priority one to left side and lower to right side.
+
+ //1 pipe by default for a layer
+ pipe_info.lIndex = getMdpPipe(ctx, MDPCOMP_OV_VG, Overlay::MIXER_DEFAULT);
+ if(pipe_info.lIndex == ovutils::OV_INVALID) {
+ if(isYuvBuffer(hnd)) {
+ return false;
+ }
+ pipe_info.lIndex = getMdpPipe(ctx, MDPCOMP_OV_ANY,
+ Overlay::MIXER_DEFAULT);
+ if(pipe_info.lIndex == ovutils::OV_INVALID) {
+ return false;
+ }
+ }
+
+ //If layer's crop width or dest width > 2048, use 2 pipes
+ if((dst.right - dst.left) > qdutils::MAX_DISPLAY_DIM or
+ (crop.right - crop.left) > qdutils::MAX_DISPLAY_DIM) {
+ ePipeType rightType = isYuvBuffer(hnd) ?
+ MDPCOMP_OV_VG : MDPCOMP_OV_ANY;
+ pipe_info.rIndex = getMdpPipe(ctx, rightType, Overlay::MIXER_DEFAULT);
+ if(pipe_info.rIndex == ovutils::OV_INVALID) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool MDPCompSrcSplit::allocLayerPipes(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list) {
+ for(int index = 0 ; index < mCurrentFrame.layerCount; index++) {
+ if(mCurrentFrame.isFBComposed[index]) continue;
+ hwc_layer_1_t* layer = &list->hwLayers[index];
+ int mdpIndex = mCurrentFrame.layerToMDP[index];
+ PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
+ info.pipeInfo = new MdpPipeInfoSplit;
+ info.rot = NULL;
+ MdpPipeInfoSplit& pipe_info = *(MdpPipeInfoSplit*)info.pipeInfo;
+
+ ePipeType type = MDPCOMP_OV_ANY;
+ if(!acquireMDPPipes(ctx, layer, pipe_info, type)) {
+ ALOGD_IF(isDebug(), "%s: Unable to get pipe for type = %d",
+ __FUNCTION__, (int) type);
+ return false;
+ }
+ }
+ return true;
+}
+
+int MDPCompSrcSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
+ PipeLayerPair& PipeLayerPair) {
+ 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;
+ MdpPipeInfoSplit& mdp_info =
+ *(static_cast<MdpPipeInfoSplit*>(PipeLayerPair.pipeInfo));
+ Rotator **rot = &PipeLayerPair.rot;
+ eZorder z = static_cast<eZorder>(mdp_info.zOrder);
+ eIsFg isFg = IS_FG_OFF;
+ eDest lDest = mdp_info.lIndex;
+ eDest rDest = mdp_info.rIndex;
+ 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;
+ uint32_t format = ovutils::getMdpFormat(hnd->format, isTileRendered(hnd));
+ Whf whf(getWidth(hnd), getHeight(hnd), format, hnd->size);
+
+ ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
+ "dest_pipeR: %d",__FUNCTION__, layer, z, lDest, rDest);
+
+ // Handle R/B swap
+ if (layer->flags & HWC_FORMAT_RB_SWAP) {
+ if (hnd->format == HAL_PIXEL_FORMAT_RGBA_8888)
+ whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRA_8888);
+ else if (hnd->format == HAL_PIXEL_FORMAT_RGBX_8888)
+ whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
+ }
+
+ eMdpFlags mdpFlagsL = OV_MDP_BACKEND_COMPOSITION;
+ setMdpFlags(layer, mdpFlagsL, 0, transform);
+ eMdpFlags mdpFlagsR = mdpFlagsL;
+
+ if(lDest != OV_INVALID && rDest != OV_INVALID) {
+ //Enable overfetch
+ setMdpFlags(mdpFlagsL, OV_MDSS_MDP_DUAL_PIPE);
+ }
+
+ if(isYuvBuffer(hnd) && (transform & HWC_TRANSFORM_ROT_90)) {
+ (*rot) = ctx->mRotMgr->getNext();
+ if((*rot) == NULL) return -1;
+ //Configure rotator for pre-rotation
+ if(configRotator(*rot, whf, crop, mdpFlagsL, orient, downscale) < 0) {
+ ALOGE("%s: configRotator failed!", __FUNCTION__);
+ return -1;
+ }
+ ctx->mLayerRotMap[mDpy]->add(layer, *rot);
+ whf.format = (*rot)->getDstFormat();
+ updateSource(orient, whf, crop);
+ rotFlags |= ROT_PREROTATED;
+ }
+
+ //If 2 pipes being used, divide layer into half, crop and dst
+ hwc_rect_t cropL = crop;
+ hwc_rect_t cropR = crop;
+ hwc_rect_t dstL = dst;
+ hwc_rect_t dstR = dst;
+ if(lDest != OV_INVALID && rDest != OV_INVALID) {
+ cropL.right = (crop.right + crop.left) / 2;
+ cropR.left = cropL.right;
+ sanitizeSourceCrop(cropL, cropR, hnd);
+
+ //Swap crops on H flip since 2 pipes are being used
+ if((orient & OVERLAY_TRANSFORM_FLIP_H) && (*rot) == NULL) {
+ hwc_rect_t tmp = cropL;
+ cropL = cropR;
+ cropR = tmp;
+ }
+
+ dstL.right = (dst.right + dst.left) / 2;
+ dstR.left = dstL.right;
+ }
+
+ //For the mdp, since either we are pre-rotating or MDP does flips
+ orient = OVERLAY_TRANSFORM_0;
+ transform = 0;
+
+ //configure left pipe
+ if(lDest != OV_INVALID) {
+ PipeArgs pargL(mdpFlagsL, whf, z, isFg,
+ static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
+ (ovutils::eBlending) getBlending(layer->blending));
+
+ if(configMdp(ctx->mOverlay, pargL, orient,
+ cropL, dstL, metadata, lDest) < 0) {
+ ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
+ return -1;
+ }
+ }
+
+ //configure right pipe
+ if(rDest != OV_INVALID) {
+ PipeArgs pargR(mdpFlagsR, whf, z, isFg,
+ static_cast<eRotFlags>(rotFlags),
+ layer->planeAlpha,
+ (ovutils::eBlending) getBlending(layer->blending));
+ if(configMdp(ctx->mOverlay, pargR, orient,
+ cropR, dstR, metadata, rDest) < 0) {
+ ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
}; //namespace
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index 4e4bea4..94199e3 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -269,14 +269,15 @@
explicit MDPCompSplit(int dpy):MDPComp(dpy){};
virtual ~MDPCompSplit(){};
virtual bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list);
-private:
+
+protected:
struct MdpPipeInfoSplit : public MdpPipeInfo {
ovutils::eDest lIndex;
ovutils::eDest rIndex;
virtual ~MdpPipeInfoSplit() {};
};
- bool acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
+ virtual bool acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
MdpPipeInfoSplit& pipe_info, ePipeType type);
/* configure's overlay pipes for the frame */
@@ -287,6 +288,7 @@
virtual bool allocLayerPipes(hwc_context_t *ctx,
hwc_display_contents_1_t* list);
+private:
/* Increments mdpCount if 4k2k yuv layer split is enabled.
* updates framebuffer z order if fb lies above source-split layer */
virtual void adjustForSourceSplit(hwc_context_t *ctx,
@@ -297,5 +299,20 @@
PipeLayerPair& PipeLayerPair);
};
+class MDPCompSrcSplit : public MDPCompSplit {
+public:
+ explicit MDPCompSrcSplit(int dpy) : MDPCompSplit(dpy){};
+ virtual ~MDPCompSrcSplit(){};
+private:
+ virtual bool acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
+ MdpPipeInfoSplit& pipe_info, ePipeType type);
+
+ virtual bool allocLayerPipes(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list);
+
+ virtual int configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
+ PipeLayerPair& pipeLayerPair);
+};
+
}; //namespace
#endif