Merge "hwc: Call blank IOCTL on virtual as well if it is connected."
diff --git a/libcopybit/copybit_c2d.cpp b/libcopybit/copybit_c2d.cpp
index da0396f..771d483 100644
--- a/libcopybit/copybit_c2d.cpp
+++ b/libcopybit/copybit_c2d.cpp
@@ -257,6 +257,7 @@
static int get_format(int format) {
switch (format) {
case HAL_PIXEL_FORMAT_RGB_565: return C2D_COLOR_FORMAT_565_RGB;
+ case HAL_PIXEL_FORMAT_RGB_888: return C2D_COLOR_FORMAT_888_RGB;
case HAL_PIXEL_FORMAT_RGBX_8888: return C2D_COLOR_FORMAT_8888_ARGB |
C2D_FORMAT_SWAP_RB |
C2D_FORMAT_DISABLE_ALPHA;
@@ -315,6 +316,9 @@
case C2D_COLOR_FORMAT_8888_ARGB:
c2dBpp = 32;
break;
+ case C2D_COLOR_FORMAT_888_RGB:
+ c2dBpp = 24;
+ break;
case C2D_COLOR_FORMAT_8_L:
case C2D_COLOR_FORMAT_8_A:
c2dBpp = 8;
@@ -396,6 +400,7 @@
switch(format) {
case HAL_PIXEL_FORMAT_RGBA_8888:
case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_RGB_888:
case HAL_PIXEL_FORMAT_RGB_565:
case HAL_PIXEL_FORMAT_BGRA_8888: {
return COPYBIT_SUCCESS;
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index a69e6ee..1702336 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -271,7 +271,12 @@
//-------------- IonController-----------------------//
IonController::IonController()
{
- mIonAlloc = new IonAlloc();
+ allocateIonMem();
+}
+
+void IonController::allocateIonMem()
+{
+ mIonAlloc = new IonAlloc();
}
int IonController::allocate(alloc_data& data, int usage)
diff --git a/libgralloc/alloc_controller.h b/libgralloc/alloc_controller.h
index 5fe81fa..f0b8ed9 100644
--- a/libgralloc/alloc_controller.h
+++ b/libgralloc/alloc_controller.h
@@ -65,6 +65,7 @@
private:
IonAlloc* mIonAlloc;
+ void allocateIonMem();
};
} //end namespace gralloc
diff --git a/libgralloc/gralloc.cpp b/libgralloc/gralloc.cpp
index 6b41ce6..c1c61aa 100644
--- a/libgralloc/gralloc.cpp
+++ b/libgralloc/gralloc.cpp
@@ -105,6 +105,9 @@
gpu_context_t *dev;
IAllocController* alloc_ctrl = IAllocController::getInstance();
dev = new gpu_context_t(m, alloc_ctrl);
+ if(!dev)
+ return status;
+
*device = &dev->common;
status = 0;
} else {
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index 83966b8..37958f7 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -551,7 +551,8 @@
if(ctx->mMDP.hasOverlay) {
supported |= HWC_DISPLAY_VIRTUAL_BIT;
if(!(qdutils::MDPVersion::getInstance().is8x26() ||
- qdutils::MDPVersion::getInstance().is8x16()))
+ qdutils::MDPVersion::getInstance().is8x16() ||
+ qdutils::MDPVersion::getInstance().is8x39()))
supported |= HWC_DISPLAY_EXTERNAL_BIT;
}
value[0] = supported;
@@ -607,8 +608,20 @@
}
}
- if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd,
- ctx->listStats[dpy].roi)) {
+ int lSplit = getLeftSplit(ctx, dpy);
+ qhwc::ovutils::Dim lRoi = qhwc::ovutils::Dim {
+ ctx->listStats[dpy].lRoi.left,
+ ctx->listStats[dpy].lRoi.top,
+ ctx->listStats[dpy].lRoi.right - ctx->listStats[dpy].lRoi.left,
+ ctx->listStats[dpy].lRoi.bottom - ctx->listStats[dpy].lRoi.top };
+
+ qhwc::ovutils::Dim rRoi = qhwc::ovutils::Dim {
+ ctx->listStats[dpy].rRoi.left - lSplit,
+ ctx->listStats[dpy].rRoi.top,
+ ctx->listStats[dpy].rRoi.right - ctx->listStats[dpy].rRoi.left,
+ ctx->listStats[dpy].rRoi.bottom - ctx->listStats[dpy].rRoi.top };
+
+ if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd, lRoi, rRoi)) {
ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy);
ret = -1;
}
diff --git a/libhwcomposer/hwc_ad.cpp b/libhwcomposer/hwc_ad.cpp
index fdf6e67..49e7e2a 100644
--- a/libhwcomposer/hwc_ad.cpp
+++ b/libhwcomposer/hwc_ad.cpp
@@ -41,37 +41,6 @@
using namespace overlay::utils;
namespace qhwc {
-//Opens writeback framebuffer and returns fd.
-static int openWbFb() {
- int wbFd = -1;
- //Check opening which FB would connect LM to WB
- const int wbFbNum = Overlay::getFbForDpy(Overlay::DPY_WRITEBACK);
- if(wbFbNum >= 0) {
- char wbFbPath[256];
- snprintf (wbFbPath, sizeof(wbFbPath),
- "/sys/class/graphics/fb%d", wbFbNum);
- //Opening writeback fb first time would create ad node if the device
- //supports adaptive display
- wbFd = open(wbFbPath, O_RDONLY);
- if(wbFd < 0) {
- ALOGE("%s: Failed to open /sys/class/graphics/fb%d with error %s",
- __func__, wbFbNum, strerror(errno));
- }
- } else {
- ALOGD_IF(DEBUG, "%s: No writeback available", __func__);
- }
- return wbFd;
-}
-
-static inline void closeWbFb(int& fd) {
- if(fd >= 0) {
- close(fd);
- fd = -1;
- } else {
- ALOGE("%s: Invalid fd %d", __func__, fd);
- }
-}
-
//Helper to write data to ad node
static void adWrite(const int& value) {
const int wbFbNum = Overlay::getFbForDpy(Overlay::DPY_WRITEBACK);
@@ -124,32 +93,31 @@
return ret;
}
-AssertiveDisplay::AssertiveDisplay(hwc_context_t *ctx) : mWbFd(-1),
- mDoable(false), mFeatureEnabled(false),
- mDest(overlay::utils::OV_INVALID) {
- int fd = openWbFb();
- if(fd >= 0) {
- //Values in ad node:
- //-1 means feature is disabled on device
- // 0 means feature exists but turned off, will be turned on by hwc
- // 1 means feature is turned on by hwc
- // Plus, we do this feature only on split primary displays.
- // Plus, we do this feature only if ro.qcom.ad=2
+AssertiveDisplay::AssertiveDisplay(hwc_context_t *ctx) :
+ mTurnedOff(true), mFeatureEnabled(false),
+ mDest(overlay::utils::OV_INVALID)
+{
+ //Values in ad node:
+ //-1 means feature is disabled on device
+ // 0 means feature exists but turned off, will be turned on by hwc
+ // 1 means feature is turned on by hwc
+ // Plus, we do this feature only on split primary displays.
+ // Plus, we do this feature only if ro.qcom.ad=2
- char property[PROPERTY_VALUE_MAX];
- const int ENABLED = 2;
- int val = 0;
+ char property[PROPERTY_VALUE_MAX];
+ const int ENABLED = 2;
+ int val = 0;
- if(property_get("ro.qcom.ad", property, "0") > 0) {
- val = atoi(property);
- }
+ if(property_get("ro.qcom.ad", property, "0") > 0) {
+ val = atoi(property);
+ }
- if(adRead() >= 0 && isDisplaySplit(ctx, HWC_DISPLAY_PRIMARY) &&
- val == ENABLED) {
- ALOGD_IF(DEBUG, "Assertive display feature supported");
- mFeatureEnabled = true;
- }
- closeWbFb(fd);
+ if(adRead() >= 0 && isDisplaySplit(ctx, HWC_DISPLAY_PRIMARY) &&
+ val == ENABLED) {
+ ALOGD_IF(DEBUG, "Assertive display feature supported");
+ mFeatureEnabled = true;
+ // If feature exists but is turned off, set mTurnedOff to true
+ mTurnedOff = adRead() > 0 ? false : true;
}
}
@@ -168,17 +136,24 @@
}
}
+void AssertiveDisplay::turnOffAD() {
+ if(mFeatureEnabled) {
+ if(!mTurnedOff) {
+ const int off = 0;
+ adWrite(off);
+ mTurnedOff = true;
+ }
+ }
+ mDoable = false;
+}
+
bool AssertiveDisplay::prepare(hwc_context_t *ctx,
const hwc_rect_t& crop,
const Whf& whf,
const private_handle_t *hnd) {
if(!isDoable()) {
- if(isModeOn()) {
- //Cleanup one time during this switch
- const int off = 0;
- adWrite(off);
- closeWbFb(mWbFd);
- }
+ //Cleanup one time during this switch
+ turnOffAD();
return false;
}
@@ -246,27 +221,30 @@
}
mDest = dest;
- if(!isModeOn()) {
- mWbFd = openWbFb();
- if(mWbFd >= 0) {
- //write to sysfs, one time during this switch
- const int on = 1;
- adWrite(on);
- }
- }
-
- if(!ctx->mOverlay->validateAndSet(overlay::Overlay::DPY_WRITEBACK,
- mWbFd)) {
+ int wbFd = wb->getFbFd();
+ if(mFeatureEnabled && wbFd >= 0 &&
+ !ctx->mOverlay->validateAndSet(overlay::Overlay::DPY_WRITEBACK, wbFd))
+ {
ALOGE("%s: Failed to validate and set overlay for dpy %d"
,__FUNCTION__, overlay::Overlay::DPY_WRITEBACK);
+ turnOffAD();
return false;
}
+ // Only turn on AD if there are no errors during configuration stage
+ // and if it was previously in OFF state.
+ if(mFeatureEnabled && mTurnedOff) {
+ //write to sysfs, one time during this switch
+ const int on = 1;
+ adWrite(on);
+ mTurnedOff = false;
+ }
+
return true;
}
bool AssertiveDisplay::draw(hwc_context_t *ctx, int fd, uint32_t offset) {
- if(!isDoable() || !isModeOn()) {
+ if(!isDoable()) {
return false;
}
diff --git a/libhwcomposer/hwc_ad.h b/libhwcomposer/hwc_ad.h
index 3bfde17..0be5f5d 100644
--- a/libhwcomposer/hwc_ad.h
+++ b/libhwcomposer/hwc_ad.h
@@ -50,17 +50,16 @@
mDest = overlay::utils::OV_INVALID;
}
bool isDoable() const { return mDoable; }
- bool isModeOn() const { return (mWbFd >= 0); }
int getDstFd() const;
uint32_t getDstOffset() const;
private:
- //State of feature turned on and off
- int mWbFd;
bool mDoable;
+ bool mTurnedOff;
//State of feature existence on certain devices and configs.
bool mFeatureEnabled;
overlay::utils::eDest mDest;
+ void turnOffAD();
};
}
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index d7afa19..f379cf8 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -811,7 +811,7 @@
}
CopyBit::CopyBit(hwc_context_t *ctx, const int& dpy) : mIsModeOn(false),
- mCopyBitDraw(false), mCurRenderBufferIndex(0) {
+ mCopyBitDraw(false), mCurRenderBufferIndex(0), mEngine(0) {
getBufferSizeAndDimensions(ctx->dpyAttr[dpy].xres,
ctx->dpyAttr[dpy].yres,
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 8a717c0..b75af03 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -42,7 +42,6 @@
bool MDPComp::sDebugLogs = false;
bool MDPComp::sEnabled = false;
bool MDPComp::sEnableMixedMode = true;
-bool MDPComp::sEnablePartialFrameUpdate = false;
int MDPComp::sMaxPipesPerMixer = MAX_PIPES_PER_MIXER;
bool MDPComp::sEnable4k2kYUVSplit = false;
bool MDPComp::sSrcSplitEnabled = false;
@@ -116,18 +115,6 @@
sDebugLogs = true;
}
- // We read from drivers if panel supports partial updating
- // and we enable partial update computations if supported.
- // Keeping this property to disable partial update for
- // debugging by setting below property to 0 & only 0.
- property_get("persist.hwc.partialupdate", property, "-1");
- if((atoi(property) != 0) &&
- qdutils::MDPVersion::getInstance().isPartialUpdateEnabled()) {
- sEnablePartialFrameUpdate = true;
- }
- ALOGE_IF(isDebug(), "%s: Partial Update applicable?: %d",__FUNCTION__,
- sEnablePartialFrameUpdate);
-
sMaxPipesPerMixer = MAX_PIPES_PER_MIXER;
if(property_get("debug.mdpcomp.maxpermixer", property, "-1") > 0) {
int val = atoi(property);
@@ -402,7 +389,8 @@
ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
ret = false;
} else if((qdutils::MDPVersion::getInstance().is8x26() ||
- qdutils::MDPVersion::getInstance().is8x16()) &&
+ qdutils::MDPVersion::getInstance().is8x16() ||
+ qdutils::MDPVersion::getInstance().is8x39()) &&
ctx->mVideoTransFlag &&
isSecondaryConnected(ctx)) {
//1 Padding round to shift pipes across mixers
@@ -421,23 +409,21 @@
return ret;
}
-/*
- * 1) Identify layers that are not visible in the updating ROI and drop them
- * from composition.
- * 2) If we have a scaling layers which needs cropping against generated ROI.
- * Reset ROI to full resolution.
- */
-bool MDPComp::validateAndApplyROI(hwc_context_t *ctx,
- hwc_display_contents_1_t* list, hwc_rect_t roi) {
+void MDPCompNonSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect) {
+ hwc_rect_t roi = ctx->listStats[mDpy].lRoi;
+ fbRect = getIntersection(fbRect, roi);
+}
+
+/* 1) Identify layers that are not visible or lying outside the updating ROI and
+ * drop them from composition.
+ * 2) If we have a scaling layer which needs cropping against generated
+ * ROI, reset ROI to full resolution. */
+bool MDPCompNonSplit::validateAndApplyROI(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list) {
int numAppLayers = ctx->listStats[mDpy].numAppLayers;
-
- if(!isValidRect(roi))
- return false;
-
- hwc_rect_t visibleRect = roi;
+ hwc_rect_t visibleRect = ctx->listStats[mDpy].lRoi;
for(int i = numAppLayers - 1; i >= 0; i--){
-
if(!isValidRect(visibleRect)) {
mCurrentFrame.drop[i] = true;
mCurrentFrame.dropCount++;
@@ -445,24 +431,16 @@
}
const hwc_layer_1_t* layer = &list->hwLayers[i];
-
hwc_rect_t dstRect = layer->displayFrame;
- hwc_rect_t srcRect = integerizeSourceCrop(layer->sourceCropf);
-
hwc_rect_t res = getIntersection(visibleRect, dstRect);
- int res_w = res.right - res.left;
- int res_h = res.bottom - res.top;
- int dst_w = dstRect.right - dstRect.left;
- int dst_h = dstRect.bottom - dstRect.top;
-
if(!isValidRect(res)) {
mCurrentFrame.drop[i] = true;
mCurrentFrame.dropCount++;
- }else {
+ } else {
/* Reset frame ROI when any layer which needs scaling also needs ROI
* cropping */
- if((res_w != dst_w || res_h != dst_h) && needsScaling (layer)) {
+ if(!isSameRect(res, dstRect) && needsScaling (layer)) {
ALOGI("%s: Resetting ROI due to scaling", __FUNCTION__);
memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
mCurrentFrame.dropCount = 0;
@@ -477,52 +455,183 @@
return true;
}
-bool MDPComp::canDoPartialUpdate(hwc_context_t *ctx,
- hwc_display_contents_1_t* list){
- if(!qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() || mDpy ||
- isSkipPresent(ctx, mDpy) || (list->flags & HWC_GEOMETRY_CHANGED)||
- isDisplaySplit(ctx, mDpy)) {
- return false;
- }
- return true;
-}
-
-void MDPComp::generateROI(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
+/* Calculate ROI for the frame by accounting all the layer's dispalyFrame which
+ * are updating. If DirtyRegion is applicable, calculate it by accounting all
+ * the changing layer's dirtyRegion. */
+void MDPCompNonSplit::generateROI(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list) {
int numAppLayers = ctx->listStats[mDpy].numAppLayers;
-
- if(!canDoPartialUpdate(ctx, list))
+ if(!canPartialUpdate(ctx, list))
return;
struct hwc_rect roi = (struct hwc_rect){0, 0, 0, 0};
+ hwc_rect fullFrame = (struct hwc_rect) {0, 0,(int)ctx->dpyAttr[mDpy].xres,
+ (int)ctx->dpyAttr[mDpy].yres};
+
for(int index = 0; index < numAppLayers; index++ ) {
hwc_layer_1_t* layer = &list->hwLayers[index];
if ((mCachedFrame.hnd[index] != layer->handle) ||
- isYuvBuffer((private_handle_t *)layer->handle)) {
+ isYuvBuffer((private_handle_t *)layer->handle)) {
hwc_rect_t updatingRect = layer->displayFrame;
+
#ifdef QCOM_BSP
- if(!needsScaling(layer))
+ if(!needsScaling(layer) && !layer->transform)
updatingRect = layer->dirtyRect;
#endif
+
roi = getUnion(roi, updatingRect);
}
}
- hwc_rect fullFrame = (struct hwc_rect) {0, 0,(int)ctx->dpyAttr[mDpy].xres,
- (int)ctx->dpyAttr[mDpy].yres};
+ /* No layer is updating. Still SF wants a refresh.*/
+ if(!isValidRect(roi))
+ return;
// Align ROI coordinates to panel restrictions
- roi = sanitizeROI(roi, fullFrame);
+ roi = getSanitizeROI(roi, fullFrame);
- if(!validateAndApplyROI(ctx, list, roi))
- roi = fullFrame;
-
- ctx->listStats[mDpy].roi.x = roi.left;
- ctx->listStats[mDpy].roi.y = roi.top;
- ctx->listStats[mDpy].roi.w = roi.right - roi.left;
- ctx->listStats[mDpy].roi.h = roi.bottom - roi.top;
+ ctx->listStats[mDpy].lRoi = roi;
+ if(!validateAndApplyROI(ctx, list))
+ resetROI(ctx, mDpy);
ALOGD_IF(isDebug(),"%s: generated ROI: [%d, %d, %d, %d]", __FUNCTION__,
- roi.left, roi.top, roi.right, roi.bottom);
+ ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
+ ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom);
+}
+
+void MDPCompSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect) {
+ hwc_rect l_roi = ctx->listStats[mDpy].lRoi;
+ hwc_rect r_roi = ctx->listStats[mDpy].rRoi;
+
+ hwc_rect_t l_fbRect = getIntersection(fbRect, l_roi);
+ hwc_rect_t r_fbRect = getIntersection(fbRect, r_roi);
+ fbRect = getUnion(l_fbRect, r_fbRect);
+}
+/* 1) Identify layers that are not visible or lying outside BOTH the updating
+ * ROI's and drop them from composition. If a layer is spanning across both
+ * the halves of the screen but needed by only ROI, the non-contributing
+ * half will not be programmed for MDP.
+ * 2) If we have a scaling layer which needs cropping against generated
+ * ROI, reset ROI to full resolution. */
+bool MDPCompSplit::validateAndApplyROI(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list) {
+
+ int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+
+ hwc_rect_t visibleRectL = ctx->listStats[mDpy].lRoi;
+ hwc_rect_t visibleRectR = ctx->listStats[mDpy].rRoi;
+
+ for(int i = numAppLayers - 1; i >= 0; i--){
+ if(!isValidRect(visibleRectL) && !isValidRect(visibleRectR))
+ {
+ mCurrentFrame.drop[i] = true;
+ mCurrentFrame.dropCount++;
+ continue;
+ }
+
+ const hwc_layer_1_t* layer = &list->hwLayers[i];
+ hwc_rect_t dstRect = layer->displayFrame;
+
+ hwc_rect_t l_res = getIntersection(visibleRectL, dstRect);
+ hwc_rect_t r_res = getIntersection(visibleRectR, dstRect);
+ hwc_rect_t res = getUnion(l_res, r_res);
+
+ if(!isValidRect(l_res) && !isValidRect(r_res)) {
+ mCurrentFrame.drop[i] = true;
+ mCurrentFrame.dropCount++;
+ } else {
+ /* Reset frame ROI when any layer which needs scaling also needs ROI
+ * cropping */
+ if(!isSameRect(res, dstRect) && needsScaling (layer)) {
+ memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
+ mCurrentFrame.dropCount = 0;
+ return false;
+ }
+
+ if (layer->blending == HWC_BLENDING_NONE) {
+ visibleRectL = deductRect(visibleRectL, l_res);
+ visibleRectR = deductRect(visibleRectR, r_res);
+ }
+ }
+ }
+ return true;
+}
+/* Calculate ROI for the frame by accounting all the layer's dispalyFrame which
+ * are updating. If DirtyRegion is applicable, calculate it by accounting all
+ * the changing layer's dirtyRegion. */
+void MDPCompSplit::generateROI(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list) {
+ if(!canPartialUpdate(ctx, list))
+ return;
+
+ int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+ int lSplit = getLeftSplit(ctx, mDpy);
+
+ int hw_h = (int)ctx->dpyAttr[mDpy].yres;
+ int hw_w = (int)ctx->dpyAttr[mDpy].xres;
+
+ struct hwc_rect l_frame = (struct hwc_rect){0, 0, lSplit, hw_h};
+ struct hwc_rect r_frame = (struct hwc_rect){lSplit, 0, hw_w, hw_h};
+
+ struct hwc_rect l_roi = (struct hwc_rect){0, 0, 0, 0};
+ struct hwc_rect r_roi = (struct hwc_rect){0, 0, 0, 0};
+
+ for(int index = 0; index < numAppLayers; index++ ) {
+ hwc_layer_1_t* layer = &list->hwLayers[index];
+ if ((mCachedFrame.hnd[index] != layer->handle) ||
+ isYuvBuffer((private_handle_t *)layer->handle)) {
+ hwc_rect_t dst = layer->displayFrame;
+ hwc_rect_t updatingRect = dst;
+
+#ifdef QCOM_BSP
+ if(!needsScaling(layer) && !layer->transform)
+ {
+ hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
+ int x_off = dst.left - src.left;
+ int y_off = dst.top - src.top;
+ updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
+ }
+#endif
+
+ hwc_rect_t l_dst = getIntersection(l_frame, updatingRect);
+ if(isValidRect(l_dst))
+ l_roi = getUnion(l_roi, l_dst);
+
+ hwc_rect_t r_dst = getIntersection(r_frame, updatingRect);
+ if(isValidRect(r_dst))
+ r_roi = getUnion(r_roi, r_dst);
+ }
+ }
+
+ /* For panels that cannot accept commands in both the interfaces, we cannot
+ * send two ROI's (for each half). We merge them into single ROI and split
+ * them across lSplit for MDP mixer use. The ROI's will be merged again
+ * finally before udpating the panel in the driver. */
+ if(qdutils::MDPVersion::getInstance().needsROIMerge()) {
+ hwc_rect_t temp_roi = getUnion(l_roi, r_roi);
+ l_roi = getIntersection(temp_roi, l_frame);
+ r_roi = getIntersection(temp_roi, r_frame);
+ }
+
+ /* No layer is updating. Still SF wants a refresh. */
+ if(!isValidRect(l_roi) && !isValidRect(r_roi))
+ return;
+
+ l_roi = getSanitizeROI(l_roi, l_frame);
+ r_roi = getSanitizeROI(r_roi, r_frame);
+
+ ctx->listStats[mDpy].lRoi = l_roi;
+ ctx->listStats[mDpy].rRoi = r_roi;
+
+ if(!validateAndApplyROI(ctx, list))
+ resetROI(ctx, mDpy);
+
+ ALOGD_IF(isDebug(),"%s: generated L_ROI: [%d, %d, %d, %d]"
+ "R_ROI: [%d, %d, %d, %d]", __FUNCTION__,
+ ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
+ ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom,
+ ctx->listStats[mDpy].rRoi.left, ctx->listStats[mDpy].rRoi.top,
+ ctx->listStats[mDpy].rRoi.right, ctx->listStats[mDpy].rRoi.bottom);
}
/* Checks for conditions where all the layers marked for MDP comp cannot be
@@ -799,6 +908,16 @@
return true;
}
+bool MDPComp::canPartialUpdate(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list){
+ if(!qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() ||
+ isSkipPresent(ctx, mDpy) || (list->flags & HWC_GEOMETRY_CHANGED) ||
+ mDpy ) {
+ return false;
+ }
+ return true;
+}
+
bool MDPComp::tryVideoOnly(hwc_context_t *ctx,
hwc_display_contents_1_t* list) {
const bool secureOnly = true;
@@ -1093,7 +1212,8 @@
mCurrentFrame.fbCount);
}
-hwc_rect_t MDPComp::getUpdatingFBRect(hwc_display_contents_1_t* list){
+hwc_rect_t MDPComp::getUpdatingFBRect(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list){
hwc_rect_t fbRect = (struct hwc_rect){0, 0, 0, 0};
/* Update only the region of FB needed for composition */
@@ -1104,6 +1224,7 @@
fbRect = getUnion(fbRect, dst);
}
}
+ trimAgainstROI(ctx, fbRect);
return fbRect;
}
@@ -1124,7 +1245,7 @@
//Configure framebuffer first if applicable
if(mCurrentFrame.fbZ >= 0) {
- hwc_rect_t fbRect = getUpdatingFBRect(list);
+ hwc_rect_t fbRect = getUpdatingFBRect(ctx, list);
if(!ctx->mFBUpdate[mDpy]->prepare(ctx, list, fbRect, mCurrentFrame.fbZ))
{
ALOGD_IF(isDebug(), "%s configure framebuffer failed",
@@ -1276,6 +1397,7 @@
if(tryFullFrame(ctx, list) || tryVideoOnly(ctx, list)) {
setMDPCompLayerFlags(ctx, list);
} else {
+ resetROI(ctx, mDpy);
reset(ctx);
memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
mCurrentFrame.dropCount = 0;
@@ -1587,13 +1709,17 @@
pipeSpecs.mixer = Overlay::MIXER_LEFT;
pipeSpecs.fb = false;
- if (dst.left < lSplit) {
+ // Acquire pipe only for the updating half
+ hwc_rect_t l_roi = ctx->listStats[mDpy].lRoi;
+ hwc_rect_t r_roi = ctx->listStats[mDpy].rRoi;
+
+ if (dst.left < lSplit && isValidRect(getIntersection(dst, l_roi))) {
pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
if(pipe_info.lIndex == ovutils::OV_INVALID)
return false;
}
- if(dst.right > lSplit) {
+ if(dst.right > lSplit && isValidRect(getIntersection(dst, r_roi))) {
pipeSpecs.mixer = Overlay::MIXER_RIGHT;
pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
if(pipe_info.rIndex == ovutils::OV_INVALID)
@@ -1766,11 +1892,9 @@
int fd = hnd->fd;
int offset = (uint32_t)hnd->offset;
- if(ctx->mAD->isModeOn()) {
- if(ctx->mAD->draw(ctx, fd, offset)) {
- fd = ctx->mAD->getDstFd();
- offset = ctx->mAD->getDstOffset();
- }
+ if(ctx->mAD->draw(ctx, fd, offset)) {
+ fd = ctx->mAD->getDstFd();
+ offset = ctx->mAD->getDstOffset();
}
if(rot) {
@@ -1904,6 +2028,10 @@
(*rot) = ctx->mRotMgr->getNext();
if((*rot) == NULL) return -1;
ctx->mLayerRotMap[mDpy]->add(layer, *rot);
+ //If the video is using a single pipe, enable BWC
+ if(rDest == OV_INVALID) {
+ BwcPM::setBwc(crop, dst, transform, mdpFlags);
+ }
//Configure rotator for pre-rotation
if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale) < 0) {
ALOGE("%s: configRotator failed!", __FUNCTION__);
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index 8186fff..d974875 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -142,6 +142,15 @@
/* configures 4kx2k yuv layer*/
virtual int configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
PipeLayerPair& PipeLayerPair) = 0;
+ /* generates ROI based on the modified area of the frame */
+ virtual void generateROI(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list) = 0;
+ /* validates the ROI generated for fallback conditions */
+ virtual bool validateAndApplyROI(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list) = 0;
+ /* Trims fbRect calculated against ROI generated */
+ virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect) = 0;
+
/* set/reset flags for MDPComp */
void setMDPCompLayerFlags(hwc_context_t *ctx,
hwc_display_contents_1_t* list);
@@ -173,11 +182,6 @@
/* checks if MDP/MDSS can process current list w.r.to HW limitations
* All peculiar HW limitations should go here */
bool hwLimitationsCheck(hwc_context_t* ctx, hwc_display_contents_1_t* list);
- /* 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,
- hwc_rect_t roi);
-
/* Is debug enabled */
static bool isDebug() { return sDebugLogs ? true : false; };
/* Is feature enabled */
@@ -212,14 +216,14 @@
void reset(hwc_context_t *ctx);
bool isSupportedForMDPComp(hwc_context_t *ctx, hwc_layer_1_t* layer);
bool resourceCheck();
- hwc_rect_t getUpdatingFBRect(hwc_display_contents_1_t* list);
- bool canDoPartialUpdate(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+ hwc_rect_t getUpdatingFBRect(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list);
+ /* checks for conditions to enable partial udpate */
+ bool canPartialUpdate(hwc_context_t *ctx, hwc_display_contents_1_t* list);
int mDpy;
static bool sEnabled;
static bool sEnableMixedMode;
- /* Enables Partial frame composition */
- static bool sEnablePartialFrameUpdate;
static bool sDebugLogs;
static bool sIdleFallBack;
/* Handles the timeout event from kernel, if the value is set to true */
@@ -262,6 +266,14 @@
/* configures 4kx2k yuv layer to 2 VG pipes*/
virtual int configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
PipeLayerPair& PipeLayerPair);
+ /* generates ROI based on the modified area of the frame */
+ virtual void generateROI(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list);
+ /* validates the ROI generated for fallback conditions */
+ virtual bool validateAndApplyROI(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list);
+ /* Trims fbRect calculated against ROI generated */
+ virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect);
};
class MDPCompSplit : public MDPComp {
@@ -287,7 +299,6 @@
/* allocates pipes to selected candidates */
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 */
@@ -297,6 +308,14 @@
/* configures 4kx2k yuv layer*/
virtual int configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
PipeLayerPair& PipeLayerPair);
+ /* generates ROI based on the modified area of the frame */
+ virtual void generateROI(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list);
+ /* validates the ROI generated for fallback conditions */
+ virtual bool validateAndApplyROI(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list);
+ /* Trims fbRect calculated against ROI generated */
+ virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect);
};
class MDPCompSrcSplit : public MDPCompSplit {
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 4cc8243..972f12f 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -834,13 +834,13 @@
char property[PROPERTY_VALUE_MAX];
ctx->listStats[dpy].extOnlyLayerIndex = -1;
ctx->listStats[dpy].isDisplayAnimating = false;
- 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;
ctx->mViewFrame[dpy] = (hwc_rect_t){0, 0, 0, 0};
ctx->dpyAttr[dpy].mActionSafePresent = isActionSafePresent(ctx, dpy);
+ resetROI(ctx, dpy);
+
// Calculate view frame of ext display from primary resolution
// and primary device orientation.
ctx->mViewFrame[dpy] = calculateDisplayViewFrame(ctx, dpy);
@@ -1070,6 +1070,12 @@
return isValidRect(irect);
}
+bool isSameRect(const hwc_rect& rect1, const hwc_rect& rect2)
+{
+ return ((rect1.left == rect2.left) && (rect1.top == rect2.top) &&
+ (rect1.right == rect2.right) && (rect1.bottom == rect2.bottom));
+}
+
bool isValidRect(const hwc_rect& rect)
{
return ((rect.bottom > rect.top) && (rect.right > rect.left)) ;
@@ -1082,6 +1088,21 @@
return false;
}
+hwc_rect_t moveRect(const hwc_rect_t& rect, const int& x_off, const int& y_off)
+{
+ hwc_rect_t res;
+
+ if(!isValidRect(rect))
+ return (hwc_rect_t){0, 0, 0, 0};
+
+ res.left = rect.left + x_off;
+ res.top = rect.top + y_off;
+ res.right = rect.right + x_off;
+ res.bottom = rect.bottom + y_off;
+
+ return res;
+}
+
/* computes the intersection of two rects */
hwc_rect_t getIntersection(const hwc_rect_t& rect1, const hwc_rect_t& rect2)
{
@@ -2164,7 +2185,20 @@
}
}
-hwc_rect_t sanitizeROI(struct hwc_rect roi, hwc_rect boundary)
+void resetROI(hwc_context_t *ctx, const int dpy) {
+ const int fbXRes = (int)ctx->dpyAttr[dpy].xres;
+ const int fbYRes = (int)ctx->dpyAttr[dpy].yres;
+ if(isDisplaySplit(ctx, dpy)) {
+ const int lSplit = getLeftSplit(ctx, dpy);
+ ctx->listStats[dpy].lRoi = (struct hwc_rect){0, 0, lSplit, fbYRes};
+ ctx->listStats[dpy].rRoi = (struct hwc_rect){lSplit, 0, fbXRes, fbYRes};
+ } else {
+ ctx->listStats[dpy].lRoi = (struct hwc_rect){0, 0,fbXRes, fbYRes};
+ ctx->listStats[dpy].rRoi = (struct hwc_rect){0, 0, 0, 0};
+ }
+}
+
+hwc_rect_t getSanitizeROI(struct hwc_rect roi, hwc_rect boundary)
{
if(!isValidRect(roi))
return roi;
@@ -2176,6 +2210,7 @@
const int TOP_ALIGN = qdutils::MDPVersion::getInstance().getTopAlign();
const int HEIGHT_ALIGN = qdutils::MDPVersion::getInstance().getHeightAlign();
const int MIN_WIDTH = qdutils::MDPVersion::getInstance().getMinROIWidth();
+ const int MIN_HEIGHT = qdutils::MDPVersion::getInstance().getMinROIHeight();
/* Align to minimum width recommended by the panel */
if((t_roi.right - t_roi.left) < MIN_WIDTH) {
@@ -2185,7 +2220,18 @@
t_roi.right = t_roi.left + MIN_WIDTH;
}
+ /* Align to minimum height recommended by the panel */
+ if((t_roi.bottom - t_roi.top) < MIN_HEIGHT) {
+ if((t_roi.top + MIN_HEIGHT) > boundary.bottom)
+ t_roi.top = t_roi.bottom - MIN_HEIGHT;
+ else
+ t_roi.bottom = t_roi.top + MIN_HEIGHT;
+ }
+
/* Align left and width to meet panel restrictions */
+ if(LEFT_ALIGN)
+ t_roi.left = t_roi.left - (t_roi.left % LEFT_ALIGN);
+
if(WIDTH_ALIGN) {
int width = t_roi.right - t_roi.left;
width = WIDTH_ALIGN * ((width + (WIDTH_ALIGN - 1)) / WIDTH_ALIGN);
@@ -2194,13 +2240,17 @@
if(t_roi.right > boundary.right) {
t_roi.right = boundary.right;
t_roi.left = t_roi.right - width;
+
+ if(LEFT_ALIGN)
+ t_roi.left = t_roi.left - (t_roi.left % LEFT_ALIGN);
}
}
- if(LEFT_ALIGN)
- t_roi.left = t_roi.left - (t_roi.left % LEFT_ALIGN);
/* Align top and height to meet panel restrictions */
+ if(TOP_ALIGN)
+ t_roi.top = t_roi.top - (t_roi.top % TOP_ALIGN);
+
if(HEIGHT_ALIGN) {
int height = t_roi.bottom - t_roi.top;
height = HEIGHT_ALIGN * ((height + (HEIGHT_ALIGN - 1)) / HEIGHT_ALIGN);
@@ -2209,11 +2259,12 @@
if(t_roi.bottom > boundary.bottom) {
t_roi.bottom = boundary.bottom;
t_roi.top = t_roi.bottom - height;
+
+ if(TOP_ALIGN)
+ t_roi.top = t_roi.top - (t_roi.top % TOP_ALIGN);
}
}
- if(TOP_ALIGN)
- t_roi.top = t_roi.top - (t_roi.top % TOP_ALIGN);
return t_roi;
}
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 0883a51..4cfed2a 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -123,9 +123,10 @@
// Notifies hwcomposer about the start and end of animation
// This will be set to true during animation, otherwise false.
bool isDisplayAnimating;
- ovutils::Dim roi;
bool secureUI; // Secure display layer
bool isSecurePresent;
+ hwc_rect_t lRoi; //left ROI
+ hwc_rect_t rRoi; //right ROI. Unused in single DSI panels.
};
struct LayerProp {
@@ -260,6 +261,8 @@
int getExtOrientation(hwc_context_t* ctx);
bool isValidRect(const hwc_rect_t& rect);
hwc_rect_t deductRect(const hwc_rect_t& rect1, const hwc_rect_t& rect2);
+bool isSameRect(const hwc_rect& rect1, const hwc_rect& rect2);
+hwc_rect_t moveRect(const hwc_rect_t& rect, const int& x_off, const int& y_off);
hwc_rect_t getIntersection(const hwc_rect_t& rect1, const hwc_rect_t& rect2);
hwc_rect_t getUnion(const hwc_rect_t& rect1, const hwc_rect_t& rect2);
void optimizeLayerRects(const hwc_display_contents_1_t *list);
@@ -295,8 +298,11 @@
/* Get External State names */
const char* getExternalDisplayState(uint32_t external_state);
+// Resets display ROI to full panel resoluion
+void resetROI(hwc_context_t *ctx, const int dpy);
+
// Aligns updating ROI to panel restrictions
-hwc_rect_t sanitizeROI(struct hwc_rect roi, hwc_rect boundary);
+hwc_rect_t getSanitizeROI(struct hwc_rect roi, hwc_rect boundary);
// Handles wfd Pause and resume events
void handle_pause(hwc_context_t *ctx, int dpy);
diff --git a/libmemtrack/kgsl.c b/libmemtrack/kgsl.c
index 6dd4e27..6194043 100644
--- a/libmemtrack/kgsl.c
+++ b/libmemtrack/kgsl.c
@@ -47,7 +47,6 @@
size_t allocated_records = min(*num_records, ARRAY_SIZE(record_templates));
int i;
FILE *fp;
- FILE *smaps_fp = NULL;
char line[1024];
char tmp[128];
size_t accounted_size = 0;
@@ -70,19 +69,14 @@
return -errno;
}
- if (type == MEMTRACK_TYPE_GL) {
- snprintf(tmp, sizeof(tmp), "/proc/%d/smaps", pid);
- smaps_fp = fopen(tmp, "r");
- if (smaps_fp == NULL) {
- fclose(fp);
- return -errno;
- }
- }
-
+ /* Go through each line of <pid>/mem file and for every entry of type "gpumem"
+ * check if the gpubuffer entry is usermapped or not. If the entry is usermapped
+ * count the entry as accounted else count the entry as unaccounted.
+ */
while (1) {
- unsigned long uaddr;
unsigned long size;
char line_type[7];
+ char flags[7];
int ret;
if (fgets(line, sizeof(line), fp) == NULL) {
@@ -91,49 +85,21 @@
/* Format:
* gpuaddr useraddr size id flags type usage sglen
- * 545ba000 545ba000 4096 1 ----p gpumem arraybuffer 1
+ * 545ba000 545ba000 4096 1 ----pY gpumem arraybuffer 1
*/
- ret = sscanf(line, "%*x %lx %lu %*d %*s %6s %*s %*d\n",
- &uaddr, &size, line_type);
+ ret = sscanf(line, "%*x %*lx %lu %*d %6s %6s %*s %*d\n",
+ &size, flags, line_type);
if (ret != 3) {
continue;
}
if (type == MEMTRACK_TYPE_GL && strcmp(line_type, "gpumem") == 0) {
- bool accounted = false;
- /*
- * We need to cross reference the user address against smaps,
- * luckily both are sorted.
- */
- while (smaps_addr <= uaddr) {
- unsigned long start;
- unsigned long end;
- unsigned long smaps_size;
- if (fgets(line, sizeof(line), smaps_fp) == NULL) {
- break;
- }
-
- if (sscanf(line, "%8lx-%8lx", &start, &end) == 2) {
- smaps_addr = start;
- continue;
- }
-
- if (smaps_addr != uaddr) {
- continue;
- }
-
- if (sscanf(line, "Rss: %lu kB", &smaps_size) == 1) {
- if (smaps_size) {
- accounted = true;
- accounted_size += size;
- break;
- }
- }
- }
- if (!accounted) {
+ if (flags[6] == 'Y')
+ accounted_size += size;
+ else
unaccounted_size += size;
- }
+
} else if (type == MEMTRACK_TYPE_GRAPHICS && strcmp(line_type, "ion") == 0) {
unaccounted_size += size;
}
@@ -146,8 +112,6 @@
records[1].size_in_bytes = unaccounted_size;
}
- if (smaps_fp)
- fclose(smaps_fp);
fclose(fp);
return 0;
diff --git a/liboverlay/Android.mk b/liboverlay/Android.mk
index d8c2ab5..277b44c 100644
--- a/liboverlay/Android.mk
+++ b/liboverlay/Android.mk
@@ -9,9 +9,6 @@
LOCAL_SHARED_LIBRARIES := $(common_libs) libqdutils libmemalloc \
libsync libdl
LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdoverlay\"
-ifeq ($(TARGET_USES_QSEED_SCALAR),true)
- LOCAL_CFLAGS += -DUSES_QSEED_SCALAR
-endif
LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
LOCAL_SRC_FILES := \
overlay.cpp \
diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp
index d53b46d..fe7bd2c 100644
--- a/liboverlay/overlay.cpp
+++ b/liboverlay/overlay.cpp
@@ -33,11 +33,6 @@
#include "mdp_version.h"
#include "qdMetaData.h"
-#ifdef USES_QSEED_SCALAR
-#include <scale/scale.h>
-using namespace scale;
-#endif
-
#define PIPE_DEBUG 0
namespace overlay {
@@ -163,6 +158,8 @@
return getPipe_8x26(pipeSpecs);
} else if(MDPVersion::getInstance().is8x16()) {
return getPipe_8x16(pipeSpecs);
+ } else if(MDPVersion::getInstance().is8x39()) {
+ return getPipe_8x39(pipeSpecs);
}
eDest dest = OV_INVALID;
@@ -251,6 +248,12 @@
return dest;
}
+utils::eDest Overlay::getPipe_8x39(const PipeSpecs& pipeSpecs) {
+ //8x16 & 8x36 has same number of pipes, pipe-types & scaling capabilities.
+ //Rely on 8x16 until we see a need to change.
+ return getPipe_8x16(pipeSpecs);
+}
+
void Overlay::endAllSessions() {
for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
if(mPipeBook[i].valid() && mPipeBook[i].mSession==PipeBook::START)
@@ -283,14 +286,13 @@
bool Overlay::commit(utils::eDest dest) {
bool ret = false;
- int index = (int)dest;
- validate(index);
+ validate((int)dest);
- if(mPipeBook[index].mPipe->commit()) {
+ if(mPipeBook[dest].mPipe->commit()) {
ret = true;
PipeBook::setUse((int)dest);
} else {
- int dpy = mPipeBook[index].mDisplay;
+ int dpy = mPipeBook[dest].mDisplay;
for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
if (mPipeBook[i].mDisplay == dpy) {
PipeBook::resetAllocation(i);
@@ -303,52 +305,46 @@
bool Overlay::queueBuffer(int fd, uint32_t offset,
utils::eDest dest) {
- int index = (int)dest;
bool ret = false;
- validate(index);
+ validate((int)dest);
//Queue only if commit() has succeeded (and the bit set)
if(PipeBook::isUsed((int)dest)) {
- ret = mPipeBook[index].mPipe->queueBuffer(fd, offset);
+ ret = mPipeBook[dest].mPipe->queueBuffer(fd, offset);
}
return ret;
}
void Overlay::setCrop(const utils::Dim& d,
utils::eDest dest) {
- int index = (int)dest;
- validate(index);
- mPipeBook[index].mPipe->setCrop(d);
+ validate((int)dest);
+ mPipeBook[dest].mPipe->setCrop(d);
}
void Overlay::setColor(const uint32_t color,
utils::eDest dest) {
- int index = (int)dest;
- validate(index);
- mPipeBook[index].mPipe->setColor(color);
+ validate((int)dest);
+ mPipeBook[dest].mPipe->setColor(color);
}
void Overlay::setPosition(const utils::Dim& d,
utils::eDest dest) {
- int index = (int)dest;
- validate(index);
- mPipeBook[index].mPipe->setPosition(d);
+ validate((int)dest);
+ mPipeBook[dest].mPipe->setPosition(d);
}
void Overlay::setTransform(const int orient,
utils::eDest dest) {
- int index = (int)dest;
- validate(index);
+ validate((int)dest);
utils::eTransform transform =
static_cast<utils::eTransform>(orient);
- mPipeBook[index].mPipe->setTransform(transform);
+ mPipeBook[dest].mPipe->setTransform(transform);
}
void Overlay::setSource(const utils::PipeArgs args,
utils::eDest dest) {
- int index = (int)dest;
- validate(index);
+ validate((int)dest);
PipeArgs newArgs(args);
if(PipeBook::getPipeType(dest) == OV_MDP_PIPE_VG) {
@@ -363,13 +359,12 @@
clearMdpFlags(newArgs.mdpFlags, OV_MDP_PIPE_FORCE_DMA);
}
- mPipeBook[index].mPipe->setSource(newArgs);
+ mPipeBook[dest].mPipe->setSource(newArgs);
}
void Overlay::setVisualParams(const MetaData_t& metadata, utils::eDest dest) {
- int index = (int)dest;
- validate(index);
- mPipeBook[index].mPipe->setVisualParams(metadata);
+ validate((int)dest);
+ mPipeBook[dest].mPipe->setVisualParams(metadata);
}
Overlay* Overlay::getInstance() {
@@ -471,19 +466,24 @@
}
bool Overlay::displayCommit(const int& fd) {
- utils::Dim roi;
- return displayCommit(fd, roi);
+ utils::Dim lRoi, rRoi;
+ return displayCommit(fd, lRoi, rRoi);
}
-bool Overlay::displayCommit(const int& fd, const utils::Dim& roi) {
+bool Overlay::displayCommit(const int& fd, const utils::Dim& lRoi,
+ const utils::Dim& rRoi) {
//Commit
struct mdp_display_commit info;
memset(&info, 0, sizeof(struct mdp_display_commit));
info.flags = MDP_DISPLAY_COMMIT_OVERLAY;
- info.roi.x = roi.x;
- info.roi.y = roi.y;
- info.roi.w = roi.w;
- info.roi.h = roi.h;
+ info.l_roi.x = lRoi.x;
+ info.l_roi.y = lRoi.y;
+ info.l_roi.w = lRoi.w;
+ info.l_roi.h = lRoi.h;
+ info.r_roi.x = rRoi.x;
+ info.r_roi.y = rRoi.y;
+ info.r_roi.w = rRoi.w;
+ info.r_roi.h = rRoi.h;
if(!mdp_wrapper::displayCommit(fd, info)) {
ALOGE("%s: commit failed", __func__);
@@ -530,7 +530,7 @@
bool Overlay::validateAndSet(const int& dpy, const int& fbFd) {
GenericPipe* pipeArray[PipeBook::NUM_PIPES];
- memset(&pipeArray, 0, sizeof(pipeArray));
+ memset(pipeArray, 0, sizeof(GenericPipe*)*(PipeBook::NUM_PIPES));
int num = 0;
for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
@@ -545,39 +545,20 @@
}
void Overlay::initScalar() {
-#ifdef USES_QSEED_SCALAR
if(sLibScaleHandle == NULL) {
sLibScaleHandle = dlopen("libscale.so", RTLD_NOW);
- }
-
- if(sLibScaleHandle) {
- if(sScale == NULL) {
- Scale* (*getInstance)();
- *(void **) &getInstance = dlsym(sLibScaleHandle, "getInstance");
- if(getInstance) {
- sScale = getInstance();
- }
+ if(sLibScaleHandle) {
+ *(void **) &sFnProgramScale =
+ dlsym(sLibScaleHandle, "programScale");
}
}
-#endif
}
void Overlay::destroyScalar() {
-#ifdef USES_QSEED_SCALAR
if(sLibScaleHandle) {
- if(sScale) {
- void (*destroyInstance)(Scale*);
- *(void **) &destroyInstance = dlsym(sLibScaleHandle,
- "destroyInstance");
- if(destroyInstance) {
- destroyInstance(sScale);
- sScale = NULL;
- }
- }
dlclose(sLibScaleHandle);
sLibScaleHandle = NULL;
}
-#endif
}
void Overlay::PipeBook::init() {
@@ -607,6 +588,6 @@
utils::eMdpPipeType Overlay::PipeBook::pipeTypeLUT[utils::OV_MAX] =
{utils::OV_MDP_PIPE_ANY};
void *Overlay::sLibScaleHandle = NULL;
-scale::Scale *Overlay::sScale = NULL;
+int (*Overlay::sFnProgramScale)(struct mdp_overlay_list *) = NULL;
}; // namespace overlay
diff --git a/liboverlay/overlay.h b/liboverlay/overlay.h
index 455f547..99186db 100644
--- a/liboverlay/overlay.h
+++ b/liboverlay/overlay.h
@@ -35,9 +35,6 @@
#include "utils/threads.h"
struct MetaData_t;
-namespace scale {
-class Scale;
-};
namespace overlay {
class GenericPipe;
@@ -149,8 +146,12 @@
static int getDMAMode();
/* Returns the framebuffer node backing up the display */
static int getFbForDpy(const int& dpy);
- static bool displayCommit(const int& fd, const utils::Dim& roi);
+
static bool displayCommit(const int& fd);
+ /* Overloads display commit with ROI's of each halves.
+ * Single interface panels will only update left ROI. */
+ static bool displayCommit(const int& fd, const utils::Dim& lRoi,
+ const utils::Dim& rRoi);
private:
/* Ctor setup */
@@ -170,9 +171,10 @@
/* Helpers that enfore target specific policies while returning pipes */
utils::eDest getPipe_8x26(const PipeSpecs& pipeSpecs);
utils::eDest getPipe_8x16(const PipeSpecs& pipeSpecs);
+ utils::eDest getPipe_8x39(const PipeSpecs& pipeSpecs);
- /* Returns the scalar object */
- static scale::Scale *getScalar();
+ /* Returns the handle to libscale.so's programScale function */
+ static int (*getFnProgramScale())(struct mdp_overlay_list *);
/* Creates a scalar object using libscale.so */
static void initScalar();
/* Destroys the scalar object using libscale.so */
@@ -243,7 +245,7 @@
static int sDMAMode;
static bool sDMAMultiplexingSupported;
static void *sLibScaleHandle;
- static scale::Scale *sScale;
+ static int (*sFnProgramScale)(struct mdp_overlay_list *);
friend class MdpCtrl;
};
@@ -317,7 +319,8 @@
inline bool Overlay::isUIScalingOnExternalSupported() {
if(qdutils::MDPVersion::getInstance().is8x26() or
- qdutils::MDPVersion::getInstance().is8x16()) {
+ qdutils::MDPVersion::getInstance().is8x16() or
+ qdutils::MDPVersion::getInstance().is8x39()) {
return false;
}
return true;
@@ -332,8 +335,8 @@
return sDpyFbMap[dpy];
}
-inline scale::Scale *Overlay::getScalar() {
- return sScale;
+inline int (*Overlay::getFnProgramScale())(struct mdp_overlay_list *) {
+ return sFnProgramScale;
}
inline bool Overlay::PipeBook::valid() {
diff --git a/liboverlay/overlayMdp.cpp b/liboverlay/overlayMdp.cpp
index 3af9eaa..c4427ae 100644
--- a/liboverlay/overlayMdp.cpp
+++ b/liboverlay/overlayMdp.cpp
@@ -22,11 +22,6 @@
#include "mdp_version.h"
#include <overlay.h>
-#ifdef USES_QSEED_SCALAR
-#include <scale/scale.h>
-using namespace scale;
-#endif
-
#define HSIC_SETTINGS_DEBUG 0
using namespace qdutils;
@@ -371,12 +366,11 @@
list.num_overlays = count;
list.overlay_list = ovArray;
-#ifdef USES_QSEED_SCALAR
- Scale *scalar = Overlay::getScalar();
- if(scalar) {
- scalar->applyScale(&list);
+ int (*fnProgramScale)(struct mdp_overlay_list *) =
+ Overlay::getFnProgramScale();
+ if(fnProgramScale) {
+ fnProgramScale(&list);
}
-#endif
if(!mdp_wrapper::validateAndSet(fbFd, list)) {
/* No dump for failure due to insufficient resource */
diff --git a/libqdutils/mdp_version.cpp b/libqdutils/mdp_version.cpp
index 16505ba..96ed4d2 100644
--- a/libqdutils/mdp_version.cpp
+++ b/libqdutils/mdp_version.cpp
@@ -61,6 +61,12 @@
#ifndef MDSS_MDP_HW_REV_107
#define MDSS_MDP_HW_REV_107 0x10070000 //Next version
#endif
+#ifndef MDSS_MDP_HW_REV_108
+#define MDSS_MDP_HW_REV_108 0x10080000 //8x39 & 8x36
+#endif
+#ifndef MDSS_MDP_HW_REV_109
+#define MDSS_MDP_HW_REV_109 0x10090000 //Next version
+#endif
#ifndef MDSS_MDP_HW_REV_200
#define MDSS_MDP_HW_REV_200 0x20000000 //8092
#endif
@@ -200,6 +206,10 @@
mPanelInfo.mMinROIHeight = atoi(tokens[1]);
ALOGI("Min ROI Height: %d", mPanelInfo.mMinROIHeight);
}
+ if(!strncmp(tokens[0], "roi_merge", strlen("roi_merge"))) {
+ mPanelInfo.mNeedsROIMerge = atoi(tokens[1]);
+ ALOGI("Needs ROI Merge: %d", mPanelInfo.mNeedsROIMerge);
+ }
}
}
fclose(panelInfoNodeFP);
@@ -390,5 +400,11 @@
mMdpRev < MDSS_MDP_HW_REV_107);
}
+bool MDPVersion::is8x39() {
+ return (mMdpRev >= MDSS_MDP_HW_REV_108 and
+ mMdpRev < MDSS_MDP_HW_REV_109);
+}
+
+
}; //namespace qdutils
diff --git a/libqdutils/mdp_version.h b/libqdutils/mdp_version.h
index cace430..e862d2d 100644
--- a/libqdutils/mdp_version.h
+++ b/libqdutils/mdp_version.h
@@ -101,9 +101,10 @@
int mHeightAlign; // ROI height alignment restriction
int mMinROIWidth; // Min width needed for ROI
int mMinROIHeight; // Min height needed for ROI
+ bool mNeedsROIMerge; // Merge ROI's of both the DSI's
PanelInfo() : mType(NO_PANEL), mPartialUpdateEnable(0),
mLeftAlign(0), mWidthAlign(0), mTopAlign(0), mHeightAlign(0),
- mMinROIWidth(0), mMinROIHeight(0){}
+ mMinROIWidth(0), mMinROIHeight(0), mNeedsROIMerge(false){}
friend class MDPVersion;
};
@@ -128,16 +129,14 @@
bool supportsMacroTile();
int getLeftSplit() { return mSplit.left(); }
int getRightSplit() { return mSplit.right(); }
- bool isPartialUpdateEnabled() {
- return mPanelInfo.mPartialUpdateEnable &&
- mPanelInfo.mType == MIPI_CMD_PANEL;
- }
+ bool isPartialUpdateEnabled() { return mPanelInfo.mPartialUpdateEnable; }
int getLeftAlign() { return mPanelInfo.mLeftAlign; }
int getWidthAlign() { return mPanelInfo.mWidthAlign; }
int getTopAlign() { return mPanelInfo.mTopAlign; }
int getHeightAlign() { return mPanelInfo.mHeightAlign; }
int getMinROIWidth() { return mPanelInfo.mMinROIWidth; }
int getMinROIHeight() { return mPanelInfo.mMinROIHeight; }
+ bool needsROIMerge() { return mPanelInfo.mNeedsROIMerge; }
unsigned long getLowBw() { return mLowBw; }
unsigned long getHighBw() { return mHighBw; }
bool isSrcSplit() const;
@@ -147,6 +146,7 @@
bool is8084();
bool is8092();
bool is8x16();
+ bool is8x39();
private:
bool updateSysFsInfo();