diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp index a0a0c82d..c8410c96 100644 --- a/libhwcomposer/hwc.cpp +++ b/libhwcomposer/hwc.cpp @@ -93,9 +93,11 @@ static void reset(hwc_context_t *ctx, int numDisplays, list->hwLayers[j].compositionType = HWC_FRAMEBUFFER; } } + + if(ctx->mFBUpdate[i]) + ctx->mFBUpdate[i]->reset(); } VideoOverlay::reset(); - FBUpdate::reset(); } //clear prev layer prop flags and realloc for current frame @@ -115,20 +117,21 @@ static void reset_layer_prop(hwc_context_t* ctx, int dpy) { static int hwc_prepare_primary(hwc_composer_device_1 *dev, hwc_display_contents_1_t *list) { hwc_context_t* ctx = (hwc_context_t*)(dev); + const int dpy = HWC_DISPLAY_PRIMARY; if (LIKELY(list && list->numHwLayers > 1) && - ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isActive) { + ctx->dpyAttr[dpy].isActive) { uint32_t last = list->numHwLayers - 1; hwc_layer_1_t *fbLayer = &list->hwLayers[last]; if(fbLayer->handle) { - setListStats(ctx, list, HWC_DISPLAY_PRIMARY); - reset_layer_prop(ctx, HWC_DISPLAY_PRIMARY); + setListStats(ctx, list, dpy); + reset_layer_prop(ctx, dpy); if(!MDPComp::configure(ctx, list)) { - VideoOverlay::prepare(ctx, list, HWC_DISPLAY_PRIMARY); - FBUpdate::prepare(ctx, fbLayer, HWC_DISPLAY_PRIMARY); + VideoOverlay::prepare(ctx, list, dpy); + ctx->mFBUpdate[dpy]->prepare(ctx, fbLayer); } - ctx->mLayerCache[HWC_DISPLAY_PRIMARY]->updateLayerCache(list); + ctx->mLayerCache[dpy]->updateLayerCache(list); } } return 0; @@ -137,20 +140,20 @@ static int hwc_prepare_primary(hwc_composer_device_1 *dev, static int hwc_prepare_external(hwc_composer_device_1 *dev, hwc_display_contents_1_t *list) { hwc_context_t* ctx = (hwc_context_t*)(dev); + const int dpy = HWC_DISPLAY_EXTERNAL; if (LIKELY(list && list->numHwLayers > 1) && - ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive && - ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected) { + ctx->dpyAttr[dpy].isActive && + ctx->dpyAttr[dpy].connected) { uint32_t last = list->numHwLayers - 1; hwc_layer_1_t *fbLayer = &list->hwLayers[last]; if(fbLayer->handle) { - setListStats(ctx, list, HWC_DISPLAY_EXTERNAL); - reset_layer_prop(ctx, HWC_DISPLAY_EXTERNAL); - - VideoOverlay::prepare(ctx, list, HWC_DISPLAY_EXTERNAL); - FBUpdate::prepare(ctx, fbLayer, HWC_DISPLAY_EXTERNAL); - ctx->mLayerCache[HWC_DISPLAY_EXTERNAL]->updateLayerCache(list); + setListStats(ctx, list, dpy); + reset_layer_prop(ctx, dpy); + VideoOverlay::prepare(ctx, list, dpy); + ctx->mFBUpdate[dpy]->prepare(ctx, fbLayer); + ctx->mLayerCache[dpy]->updateLayerCache(list); } } return 0; @@ -173,15 +176,14 @@ static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays, ret = hwc_prepare_primary(dev, list); break; case HWC_DISPLAY_EXTERNAL: - ret = hwc_prepare_external(dev, list); break; default: ret = -EINVAL; } } - ctx->mOverlay->configDone(); + ctx->mOverlay->configDone(); return ret; } @@ -282,14 +284,15 @@ static int hwc_query(struct hwc_composer_device_1* dev, static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) { int ret = 0; + const int dpy = HWC_DISPLAY_PRIMARY; if (LIKELY(list && list->numHwLayers > 1) && - ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isActive) { + ctx->dpyAttr[dpy].isActive) { uint32_t last = list->numHwLayers - 1; hwc_layer_1_t *fbLayer = &list->hwLayers[last]; - hwc_sync(ctx, list, HWC_DISPLAY_PRIMARY); - if (!VideoOverlay::draw(ctx, list, HWC_DISPLAY_PRIMARY)) { + hwc_sync(ctx, list, dpy); + if (!VideoOverlay::draw(ctx, list, dpy)) { ALOGE("%s: VideoOverlay::draw fail!", __FUNCTION__); ret = -1; } @@ -303,7 +306,7 @@ static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) { private_handle_t *hnd = (private_handle_t *)fbLayer->handle; if(fbLayer->compositionType == HWC_FRAMEBUFFER_TARGET && hnd) { if(!(fbLayer->flags & HWC_SKIP_LAYER)) { - if (!FBUpdate::draw(ctx, fbLayer, HWC_DISPLAY_PRIMARY)) { + if (!ctx->mFBUpdate[dpy]->draw(ctx, fbLayer)) { ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__); ret = -1; } @@ -320,17 +323,19 @@ static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) { static int hwc_set_external(hwc_context_t *ctx, hwc_display_contents_1_t* list) { int ret = 0; + const int dpy = HWC_DISPLAY_EXTERNAL; + Locker::Autolock _l(ctx->mExtSetLock); if (LIKELY(list && list->numHwLayers > 1) && - ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive && - ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected) { + ctx->dpyAttr[dpy].isActive && + ctx->dpyAttr[dpy].connected) { uint32_t last = list->numHwLayers - 1; hwc_layer_1_t *fbLayer = &list->hwLayers[last]; - hwc_sync(ctx, list, HWC_DISPLAY_EXTERNAL); + hwc_sync(ctx, list, dpy); - if (!VideoOverlay::draw(ctx, list, HWC_DISPLAY_EXTERNAL)) { + if (!VideoOverlay::draw(ctx, list, dpy)) { ALOGE("%s: VideoOverlay::draw fail!", __FUNCTION__); ret = -1; } @@ -338,7 +343,7 @@ static int hwc_set_external(hwc_context_t *ctx, private_handle_t *hnd = (private_handle_t *)fbLayer->handle; if(fbLayer->compositionType == HWC_FRAMEBUFFER_TARGET && !(fbLayer->flags & HWC_SKIP_LAYER) && hnd) { - if (!FBUpdate::draw(ctx, fbLayer, HWC_DISPLAY_EXTERNAL)) { + if (!ctx->mFBUpdate[dpy]->draw(ctx, fbLayer)) { ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__); ret = -1; } diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp index 0d0787ec..ecbf8136 100644 --- a/libhwcomposer/hwc_fbupdate.cpp +++ b/libhwcomposer/hwc_fbupdate.cpp @@ -18,7 +18,7 @@ * limitations under the License. */ -#define HWC_FB_UPDATE 0 +#define DEBUG_FBUPDATE 0 #include #include #include "hwc_fbupdate.h" @@ -28,30 +28,38 @@ namespace qhwc { namespace ovutils = overlay::utils; -//Static Members -bool FBUpdate::sModeOn[] = {false}; -ovutils::eDest FBUpdate::sDest[] = {ovutils::OV_INVALID}; - -void FBUpdate::reset() { - sModeOn[HWC_DISPLAY_PRIMARY] = false; - sModeOn[HWC_DISPLAY_EXTERNAL] = false; - sDest[HWC_DISPLAY_PRIMARY] = ovutils::OV_INVALID; - sDest[HWC_DISPLAY_EXTERNAL] = ovutils::OV_INVALID; +IFBUpdate* IFBUpdate::getObject(const int& width, const int& dpy) { + if(width > MAX_DISPLAY_DIM) { + return new FBUpdateHighRes(dpy); + } + return new FBUpdateLowRes(dpy); } -bool FBUpdate::prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer, int dpy) { +inline void IFBUpdate::reset() { + mModeOn = false; +} + +//================= Low res==================================== +FBUpdateLowRes::FBUpdateLowRes(const int& dpy): IFBUpdate(dpy) {} + +inline void FBUpdateLowRes::reset() { + IFBUpdate::reset(); + mDest = ovutils::OV_INVALID; +} + +bool FBUpdateLowRes::prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer) { if(!ctx->mMDP.hasOverlay) { - ALOGD_IF(HWC_FB_UPDATE, "%s, this hw doesnt support mirroring", + ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays", __FUNCTION__); return false; } - - return (sModeOn[dpy] = configure(ctx, fblayer, dpy)); - + mModeOn = configure(ctx, fblayer); + ALOGD_IF(DEBUG_FBUPDATE, "%s, mModeOn = %d", __FUNCTION__, mModeOn); + return mModeOn; } // Configure -bool FBUpdate::configure(hwc_context_t *ctx, hwc_layer_1_t *layer, int dpy) +bool FBUpdateLowRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer) { bool ret = false; if (LIKELY(ctx->mOverlay)) { @@ -64,12 +72,12 @@ bool FBUpdate::configure(hwc_context_t *ctx, hwc_layer_1_t *layer, int dpy) ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size); //Request an RGB pipe - ovutils::eDest dest = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, dpy); + ovutils::eDest dest = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, mDpy); if(dest == ovutils::OV_INVALID) { //None available return false; } - sDest[dpy] = dest; + mDest = dest; ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE; if(ctx->mSecureMode) { @@ -112,14 +120,14 @@ bool FBUpdate::configure(hwc_context_t *ctx, hwc_layer_1_t *layer, int dpy) return ret; } -bool FBUpdate::draw(hwc_context_t *ctx, hwc_layer_1_t *layer, int dpy) +bool FBUpdateLowRes::draw(hwc_context_t *ctx, hwc_layer_1_t *layer) { - if(!sModeOn[dpy]) { + if(!mModeOn) { return true; } bool ret = true; overlay::Overlay& ov = *(ctx->mOverlay); - ovutils::eDest dest = sDest[dpy]; + ovutils::eDest dest = mDest; private_handle_t *hnd = (private_handle_t *)layer->handle; if (!ov.queueBuffer(hnd->fd, hnd->offset, dest)) { ALOGE("%s: queueBuffer failed for external", __FUNCTION__); @@ -128,5 +136,138 @@ bool FBUpdate::draw(hwc_context_t *ctx, hwc_layer_1_t *layer, int dpy) return ret; } +//================= High res==================================== +FBUpdateHighRes::FBUpdateHighRes(const int& dpy): IFBUpdate(dpy) {} + +inline void FBUpdateHighRes::reset() { + IFBUpdate::reset(); + mDestLeft = ovutils::OV_INVALID; + mDestRight = ovutils::OV_INVALID; +} + +bool FBUpdateHighRes::prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer) { + if(!ctx->mMDP.hasOverlay) { + ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays", + __FUNCTION__); + return false; + } + ALOGD_IF(DEBUG_FBUPDATE, "%s, mModeOn = %d", __FUNCTION__, mModeOn); + mModeOn = configure(ctx, fblayer); + return mModeOn; +} + +// Configure +bool FBUpdateHighRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer) +{ + bool ret = false; + if (LIKELY(ctx->mOverlay)) { + overlay::Overlay& ov = *(ctx->mOverlay); + private_handle_t *hnd = (private_handle_t *)layer->handle; + if (!hnd) { + ALOGE("%s:NULL private handle for layer!", __FUNCTION__); + return false; + } + ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size); + + //Request left RGB pipe + ovutils::eDest destL = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, mDpy); + if(destL == ovutils::OV_INVALID) { //None available + return false; + } + //Request right RGB pipe + ovutils::eDest destR = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, mDpy); + if(destR == ovutils::OV_INVALID) { //None available + return false; + } + + mDestLeft = destL; + mDestRight = destR; + + ovutils::eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE; + if(ctx->mSecureMode) { + ovutils::setMdpFlags(mdpFlagsL, + ovutils::OV_MDP_SECURE_OVERLAY_SESSION); + } + + ovutils::PipeArgs pargL(mdpFlagsL, + info, + ovutils::ZORDER_0, + ovutils::IS_FG_SET, + ovutils::ROT_FLAG_DISABLED); + ov.setSource(pargL, destL); + + ovutils::eMdpFlags mdpFlagsR = mdpFlagsL; + ovutils::setMdpFlags(mdpFlagsR, ovutils::OV_MDSS_MDP_RIGHT_MIXER); + ovutils::PipeArgs pargR(mdpFlagsR, + info, + ovutils::ZORDER_0, + ovutils::IS_FG_SET, + ovutils::ROT_FLAG_DISABLED); + ov.setSource(pargR, destR); + + hwc_rect_t sourceCrop = layer->sourceCrop; + ovutils::Dim dcropL(sourceCrop.left, sourceCrop.top, + (sourceCrop.right - sourceCrop.left) / 2, + sourceCrop.bottom - sourceCrop.top); + ovutils::Dim dcropR( + sourceCrop.left + (sourceCrop.right - sourceCrop.left) / 2, + sourceCrop.top, + (sourceCrop.right - sourceCrop.left) / 2, + sourceCrop.bottom - sourceCrop.top); + ov.setCrop(dcropL, destL); + ov.setCrop(dcropR, destR); + + int transform = layer->transform; + ovutils::eTransform orient = + static_cast(transform); + ov.setTransform(orient, destL); + ov.setTransform(orient, destR); + + hwc_rect_t displayFrame = layer->displayFrame; + //For FB left, top will always be 0 + //That should also be the case if using 2 mixers for single display + ovutils::Dim dpos(displayFrame.left, + displayFrame.top, + (displayFrame.right - displayFrame.left) / 2, + displayFrame.bottom - displayFrame.top); + ov.setPosition(dpos, destL); + ov.setPosition(dpos, 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; + } + } + return ret; +} + +bool FBUpdateHighRes::draw(hwc_context_t *ctx, hwc_layer_1_t *layer) +{ + if(!mModeOn) { + return true; + } + bool ret = true; + overlay::Overlay& ov = *(ctx->mOverlay); + ovutils::eDest destL = mDestLeft; + ovutils::eDest destR = mDestRight; + private_handle_t *hnd = (private_handle_t *)layer->handle; + if (!ov.queueBuffer(hnd->fd, hnd->offset, destL)) { + ALOGE("%s: queue failed for left of dpy = %d", + __FUNCTION__, mDpy); + ret = false; + } + if (!ov.queueBuffer(hnd->fd, hnd->offset, destR)) { + ALOGE("%s: queue failed for right of dpy = %d", + __FUNCTION__, mDpy); + ret = false; + } + return ret; +} + //--------------------------------------------------------------------- }; //namespace qhwc diff --git a/libhwcomposer/hwc_fbupdate.h b/libhwcomposer/hwc_fbupdate.h index 708eb6f9..a30a3aff 100644 --- a/libhwcomposer/hwc_fbupdate.h +++ b/libhwcomposer/hwc_fbupdate.h @@ -28,22 +28,50 @@ namespace qhwc { namespace ovutils = overlay::utils; -//Framebuffer update -class FBUpdate { - public: - // Sets up members and prepares overlay if conditions are met - static bool prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer, int dpy); - // Draws layer if this feature is on - static bool draw(hwc_context_t *ctx, hwc_layer_1_t *fblayer, int dpy); - //Reset values - static void reset(); - private: - //Configures overlay - static bool configure(hwc_context_t *ctx, hwc_layer_1_t *fblayer, - int dpy); - //Flags if this feature is on. - static bool sModeOn[HWC_NUM_DISPLAY_TYPES]; - static ovutils::eDest sDest[HWC_NUM_DISPLAY_TYPES]; +//Framebuffer update Interface +class IFBUpdate { +public: + explicit IFBUpdate(const int& dpy) : mDpy(dpy) {} + virtual ~IFBUpdate() {}; + // Sets up members and prepares overlay if conditions are met + virtual bool prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer) = 0; + // Draws layer + virtual bool draw(hwc_context_t *ctx, hwc_layer_1_t *fblayer) = 0; + //Reset values + virtual void reset(); + //Factory method that returns a low-res or high-res version + static IFBUpdate *getObject(const int& width, const int& dpy); + +protected: + const int mDpy; // display to update + bool mModeOn; // if prepare happened +}; + +//Low resolution (<= 2048) panel handler. +class FBUpdateLowRes : public IFBUpdate { +public: + explicit FBUpdateLowRes(const int& dpy); + virtual ~FBUpdateLowRes() {}; + bool prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer); + bool draw(hwc_context_t *ctx, hwc_layer_1_t *fblayer); + void reset(); +private: + bool configure(hwc_context_t *ctx, hwc_layer_1_t *fblayer); + ovutils::eDest mDest; //pipe to draw on +}; + +//High resolution (> 2048) panel handler. +class FBUpdateHighRes : public IFBUpdate { +public: + explicit FBUpdateHighRes(const int& dpy); + virtual ~FBUpdateHighRes() {}; + bool prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer); + bool draw(hwc_context_t *ctx, hwc_layer_1_t *fblayer); + void reset(); +private: + bool configure(hwc_context_t *ctx, hwc_layer_1_t *fblayer); + ovutils::eDest mDestLeft; //left pipe to draw on + ovutils::eDest mDestRight; //right pipe to draw on }; }; //namespace qhwc diff --git a/libhwcomposer/hwc_uevents.cpp b/libhwcomposer/hwc_uevents.cpp index 78f67880..7e15b8f6 100644 --- a/libhwcomposer/hwc_uevents.cpp +++ b/libhwcomposer/hwc_uevents.cpp @@ -26,6 +26,7 @@ #include #include #include "hwc_utils.h" +#include "hwc_fbupdate.h" #include "external.h" namespace qhwc { @@ -65,10 +66,18 @@ static void handle_uevent(hwc_context_t* ctx, const char* udata, int len) if(connected != -1) { //either we got switch_state connected or disconnect ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected = connected; - if(connected) { + if (connected) { ctx->mExtDisplay->processUEventOnline(udata); - }else { + ctx->mFBUpdate[HWC_DISPLAY_EXTERNAL] = + IFBUpdate::getObject(ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].xres, + HWC_DISPLAY_EXTERNAL); + } else { ctx->mExtDisplay->processUEventOffline(udata); + if(ctx->mFBUpdate[HWC_DISPLAY_EXTERNAL]) { + Locker::Autolock _l(ctx->mExtSetLock); + delete ctx->mFBUpdate[HWC_DISPLAY_EXTERNAL]; + ctx->mFBUpdate[HWC_DISPLAY_EXTERNAL] = NULL; + } } ALOGD("%s sending hotplug: connected = %d", __FUNCTION__, connected); Locker::Autolock _l(ctx->mExtSetLock); //hwc comp could be on diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp index 2f355671..d302049e 100644 --- a/libhwcomposer/hwc_utils.cpp +++ b/libhwcomposer/hwc_utils.cpp @@ -23,6 +23,7 @@ #include #include "hwc_utils.h" #include "hwc_mdpcomp.h" +#include "hwc_fbupdate.h" #include "mdp_version.h" #include "external.h" #include "QService.h" @@ -59,6 +60,12 @@ void initContext(hwc_context_t *ctx) ctx->mMDP.version = qdutils::MDPVersion::getInstance().getMDPVersion(); ctx->mMDP.hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay(); ctx->mMDP.panel = qdutils::MDPVersion::getInstance().getPanelType(); + //Is created and destroyed only once for primary + //For external it could get created and destroyed multiple times depending + //on what external we connect to. + ctx->mFBUpdate[HWC_DISPLAY_PRIMARY] = + IFBUpdate::getObject(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres, + HWC_DISPLAY_PRIMARY); ctx->mExtDisplay = new ExternalDisplay(ctx); for (uint32_t i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) ctx->mLayerCache[i] = new LayerCache(); @@ -91,6 +98,13 @@ void closeContext(hwc_context_t *ctx) ctx->mExtDisplay = NULL; } + for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) { + if(ctx->mFBUpdate[i]) { + delete ctx->mFBUpdate[i]; + ctx->mFBUpdate[i] = NULL; + } + } + pthread_mutex_destroy(&(ctx->vstate.lock)); pthread_cond_destroy(&(ctx->vstate.cond)); } diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h index d7200b06..f3a0fd69 100644 --- a/libhwcomposer/hwc_utils.h +++ b/libhwcomposer/hwc_utils.h @@ -31,6 +31,7 @@ #define FINAL_TRANSFORM_MASK 0x000F #define MAX_NUM_DISPLAYS 4 //Yes, this is ambitious #define MAX_NUM_LAYERS 32 +#define MAX_DISPLAY_DIM 2048 //Fwrd decls struct hwc_context_t; @@ -48,6 +49,7 @@ namespace qhwc { //fwrd decl class QueuedBufferStore; class ExternalDisplay; +class IFBUpdate; struct MDPInfo { int version; @@ -215,6 +217,9 @@ struct hwc_context_t { overlay::Overlay *mOverlay; //QService object qService::QService *mQService; + + //Primary and external FB updater + qhwc::IFBUpdate *mFBUpdate[HWC_NUM_DISPLAY_TYPES]; // External display related information qhwc::ExternalDisplay *mExtDisplay; qhwc::MDPInfo mMDP; diff --git a/liboverlay/overlayUtils.h b/liboverlay/overlayUtils.h index f9fcca82..3b2f6d7c 100644 --- a/liboverlay/overlayUtils.h +++ b/liboverlay/overlayUtils.h @@ -63,6 +63,10 @@ #define DEBUG_OVERLAY 0 #define PROFILE_OVERLAY 0 +#ifndef MDSS_MDP_RIGHT_MIXER +#define MDSS_MDP_RIGHT_MIXER 0x100 +#endif + namespace overlay { // fwd @@ -297,6 +301,7 @@ enum eMdpFlags { OV_MDP_BLEND_FG_PREMULT = MDP_BLEND_FG_PREMULT, OV_MDP_FLIP_H = MDP_FLIP_LR, OV_MDP_FLIP_V = MDP_FLIP_UD, + OV_MDSS_MDP_RIGHT_MIXER = MDSS_MDP_RIGHT_MIXER, }; enum eZorder {