am a4a4524a: am 0f2848ad: (-s ours) resolved conflicts for 25016fd2 to lmp-mr1-ub-dev [DO NOT MERGE]
* commit 'a4a4524adad910a01d8af8bd1fdb2e4530e9ce7c':
hwc: fix compilation issue on backport of Ieb91b70 [DO NOT MERGE]
diff --git a/msm8994/libgralloc/alloc_controller.cpp b/msm8994/libgralloc/alloc_controller.cpp
old mode 100644
new mode 100755
index 4cb1661..bc5e68c
--- a/msm8994/libgralloc/alloc_controller.cpp
+++ b/msm8994/libgralloc/alloc_controller.cpp
@@ -137,12 +137,37 @@
}
+bool isUncompressedRgbFormat(int format)
+{
+ bool is_rgb_format = false;
+
+ 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:
+ case HAL_PIXEL_FORMAT_RGBA_5551:
+ case HAL_PIXEL_FORMAT_RGBA_4444:
+ case HAL_PIXEL_FORMAT_R_8:
+ case HAL_PIXEL_FORMAT_RG_88:
+ case HAL_PIXEL_FORMAT_BGRX_8888: // Intentional fallthrough
+ is_rgb_format = true;
+ break;
+ default:
+ break;
+ }
+
+ return is_rgb_format;
+}
+
void AdrenoMemInfo::getAlignedWidthAndHeight(int width, int height, int format,
int usage, int& aligned_w, int& aligned_h)
{
// Currently surface padding is only computed for RGB* surfaces.
- if (format <= HAL_PIXEL_FORMAT_BGRA_8888) {
+ if (isUncompressedRgbFormat(format) == true) {
int tileEnabled = isMacroTileEnabled(format, usage);
AdrenoMemInfo::getInstance().getGpuAlignedWidthHeight(width,
height, format, tileEnabled, aligned_w, aligned_h);
diff --git a/msm8994/libgralloc/gpu.cpp b/msm8994/libgralloc/gpu.cpp
index 6789133..447dde4 100644
--- a/msm8994/libgralloc/gpu.cpp
+++ b/msm8994/libgralloc/gpu.cpp
@@ -192,12 +192,9 @@
{
*bufferType = BUFFER_TYPE_VIDEO;
- if (inputFormat <= HAL_PIXEL_FORMAT_BGRA_8888) {
+ if (isUncompressedRgbFormat(inputFormat) == TRUE) {
// RGB formats
*bufferType = BUFFER_TYPE_UI;
- } else if ((inputFormat == HAL_PIXEL_FORMAT_R_8) ||
- (inputFormat == HAL_PIXEL_FORMAT_RG_88)) {
- *bufferType = BUFFER_TYPE_UI;
}
}
@@ -295,11 +292,19 @@
grallocFormat = HAL_PIXEL_FORMAT_NV21_ZSL; //NV21 ZSL
else if(usage & GRALLOC_USAGE_HW_CAMERA_READ)
grallocFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP; //NV21
- else if(usage & GRALLOC_USAGE_HW_CAMERA_WRITE)
- grallocFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP; //NV21
- else if(usage & GRALLOC_USAGE_HW_COMPOSER)
+ else if(usage & GRALLOC_USAGE_HW_CAMERA_WRITE) {
+ if (format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+ grallocFormat = HAL_PIXEL_FORMAT_NV21_ZSL; //NV21
+ } else {
+ grallocFormat = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS; //NV12 preview
+ }
+ } else if(usage & GRALLOC_USAGE_HW_COMPOSER)
//XXX: If we still haven't set a format, default to RGBA8888
grallocFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+ else if(format == HAL_PIXEL_FORMAT_YCbCr_420_888)
+ //If no other usage flags are detected, default the
+ //flexible YUV format to NV21_ZSL
+ grallocFormat = HAL_PIXEL_FORMAT_NV21_ZSL;
}
getGrallocInformationFromFormat(grallocFormat, &bufferType);
diff --git a/msm8994/libgralloc/gr.h b/msm8994/libgralloc/gr.h
index 5ee0cf8..54202c5 100644
--- a/msm8994/libgralloc/gr.h
+++ b/msm8994/libgralloc/gr.h
@@ -75,6 +75,9 @@
// To query if UBWC is enabled, based on format and usage flags
bool isUBwcEnabled(int format, int usage);
+// Function to check if the format is an uncompressed RGB format
+bool isUncompressedRgbFormat(int format);
+
/*****************************************************************************/
class Locker {
diff --git a/msm8994/libhdmi/hdmi.cpp b/msm8994/libhdmi/hdmi.cpp
index 7d709cb..c8d36ef 100644
--- a/msm8994/libhdmi/hdmi.cpp
+++ b/msm8994/libhdmi/hdmi.cpp
@@ -152,6 +152,7 @@
mUnderscanSupported(false), mMDPDownscaleEnabled(false)
{
memset(&mVInfo, 0, sizeof(mVInfo));
+ mFbNum = qdutils::getHDMINode();
mDisplayId = HWC_DISPLAY_EXTERNAL;
// Update the display if HDMI is connected as primary
@@ -159,7 +160,6 @@
mDisplayId = HWC_DISPLAY_PRIMARY;
}
- mFbNum = overlay::Overlay::getInstance()->getFbForDpy(mDisplayId);
// Disable HPD at start if HDMI is external, it will be enabled later
// when the display powers on
// This helps for framework reboot or adb shell stop/start
@@ -684,8 +684,7 @@
}
bool HDMIDisplay::isHDMIPrimaryDisplay() {
- int hdmiNode = qdutils::getHDMINode();
- return (hdmiNode == HWC_DISPLAY_PRIMARY);
+ return (mFbNum == HWC_DISPLAY_PRIMARY);
}
int HDMIDisplay::getConnectedState() {
diff --git a/msm8994/libhwcomposer/Android.mk b/msm8994/libhwcomposer/Android.mk
index df3e464..293eb49 100644
--- a/msm8994/libhwcomposer/Android.mk
+++ b/msm8994/libhwcomposer/Android.mk
@@ -17,7 +17,8 @@
LOCAL_SHARED_LIBRARIES += libskia
endif #TARGET_USES_QCOM_BSP
-LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdhwcomposer\"
+LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdhwcomposer\" \
+ -std=c++11
#Enable Dynamic FPS if PHASE_OFFSET is not set
ifeq ($(VSYNC_EVENT_PHASE_OFFSET_NS),)
LOCAL_CFLAGS += -DDYNAMIC_FPS
diff --git a/msm8994/libhwcomposer/hwc.cpp b/msm8994/libhwcomposer/hwc.cpp
index beade83..fc0842b 100644
--- a/msm8994/libhwcomposer/hwc.cpp
+++ b/msm8994/libhwcomposer/hwc.cpp
@@ -255,6 +255,8 @@
hwc_context_t* ctx = (hwc_context_t*)(dev);
const int dpy = HWC_DISPLAY_PRIMARY;
bool fbComp = false;
+ if (!ctx->mDefaultModeApplied)
+ applyDefaultMode(ctx);
if (LIKELY(list && list->numHwLayers > 1) && ctx->dpyAttr[dpy].connected &&
(ctx->dpyAttr[dpy].isActive ||
ctx->mHDMIDisplay->isHDMIPrimaryDisplay())
@@ -633,7 +635,11 @@
}
}
- int lSplit = getLeftSplit(ctx, dpy);
+ /* When source split is enabled, right ROI will always be NULL since the
+ * ROI for the whole panel generated in a single coordinate system will
+ * be populuated in left ROI. So leave the right ROI untouched */
+ int lSplit = qdutils::MDPVersion::getInstance().isSrcSplit() ? 0 :
+ (isDisplaySplit(ctx, dpy) ? getLeftSplit(ctx, dpy) : 0);
qhwc::ovutils::Dim lRoi = qhwc::ovutils::Dim(
ctx->listStats[dpy].lRoi.left,
ctx->listStats[dpy].lRoi.top,
@@ -766,8 +772,15 @@
if (hotPluggable) {
ctx->mHDMIDisplay->getDisplayConfigs(configs, numConfigs);
} else {
- configs[0] = 0;
- *numConfigs = 1;
+ if(ctx->mColorMode->getNumModes() > 0) {
+ *numConfigs = ctx->mColorMode->getNumModes();
+ for (size_t i = 0; i < *numConfigs; i++)
+ configs[i] = (uint32_t) i;
+
+ } else {
+ configs[0] = 0;
+ *numConfigs = 1;
+ }
}
break;
case HWC_DISPLAY_EXTERNAL:
@@ -795,22 +808,6 @@
return -EINVAL;
}
- //From HWComposer
- static const uint32_t DISPLAY_ATTRIBUTES[] = {
- HWC_DISPLAY_VSYNC_PERIOD,
- HWC_DISPLAY_WIDTH,
- HWC_DISPLAY_HEIGHT,
- HWC_DISPLAY_DPI_X,
- HWC_DISPLAY_DPI_Y,
-#ifdef QCOM_BSP
- HWC_DISPLAY_SECURE,
-#endif
- HWC_DISPLAY_NO_ATTRIBUTE,
- };
-
- const size_t NUM_DISPLAY_ATTRIBUTES = (sizeof(DISPLAY_ATTRIBUTES) /
- sizeof(DISPLAY_ATTRIBUTES)[0]);
-
uint32_t xres = 0, yres = 0, refresh = 0;
int ret = 0;
if (hotPluggable) {
@@ -822,7 +819,7 @@
}
}
- for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) {
+ for (size_t i = 0; attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; i++) {
switch (attributes[i]) {
case HWC_DISPLAY_VSYNC_PERIOD:
values[i] =
@@ -851,11 +848,9 @@
case HWC_DISPLAY_DPI_Y:
values[i] = (int32_t) (ctx->dpyAttr[disp].ydpi*1000.0);
break;
-#ifdef QCOM_BSP
- case HWC_DISPLAY_SECURE:
- values[i] = (int32_t) (ctx->dpyAttr[disp].secure);
+ case HWC_DISPLAY_COLOR_TRANSFORM:
+ values[i] = ctx->mColorMode->getModeForIndex(config);
break;
-#endif
default:
ALOGE("Unknown display attribute %d",
attributes[i]);
@@ -908,7 +903,9 @@
// For use cases when primary panel is the default interface we only have
// the default config (0th index)
- if (!hotPluggable) {
+ if (!hotPluggable && HWC_DISPLAY_PRIMARY) {
+ return ctx->mColorMode->getActiveModeIndex();
+ } else if (isVirtualDisplay) {
return 0;
}
@@ -928,10 +925,12 @@
return -EINVAL;
}
- // For use cases when primary panel is the default interface we only have
- // the default config (0th index)
- if (!hotPluggable) {
- // Primary and virtual supports only the default config (0th index)
+ // For use cases when primary panel is the default interface we only switch
+ // color modes
+ if(!hotPluggable && disp == HWC_DISPLAY_PRIMARY) {
+ return ctx->mColorMode->applyModeByIndex(index);
+ } else if (isVirtualDisplay) {
+ // virtual supports only the default config (0th index)
return (index == 0) ? index : -EINVAL;
}
@@ -967,7 +966,7 @@
//Setup HWC methods
dev->device.common.tag = HARDWARE_DEVICE_TAG;
- dev->device.common.version = HWC_DEVICE_API_VERSION_1_4;
+ dev->device.common.version = HWC_DEVICE_API_VERSION_1_5;
dev->device.common.module = const_cast<hw_module_t*>(module);
dev->device.common.close = hwc_device_close;
dev->device.prepare = hwc_prepare;
diff --git a/msm8994/libhwcomposer/hwc_fbupdate.cpp b/msm8994/libhwcomposer/hwc_fbupdate.cpp
index b63fb3a..8660740 100644
--- a/msm8994/libhwcomposer/hwc_fbupdate.cpp
+++ b/msm8994/libhwcomposer/hwc_fbupdate.cpp
@@ -541,7 +541,7 @@
return false;
}
- if(ctx->mOverlay->comparePipePriority(destL, destR) == -1) {
+ if(ctx->mOverlay->needsPrioritySwap(destL, destR)) {
qhwc::swap(destL, destR);
}
diff --git a/msm8994/libhwcomposer/hwc_mdpcomp.cpp b/msm8994/libhwcomposer/hwc_mdpcomp.cpp
index d2962a3..4c7c7ad 100644
--- a/msm8994/libhwcomposer/hwc_mdpcomp.cpp
+++ b/msm8994/libhwcomposer/hwc_mdpcomp.cpp
@@ -51,6 +51,7 @@
int MDPComp::sMaxSecLayers = 1;
bool MDPComp::enablePartialUpdateForMDP3 = false;
bool MDPComp::sIsPartialUpdateActive = true;
+bool MDPComp::sIsSingleFullScreenUpdate = false;
void *MDPComp::sLibPerfHint = NULL;
int MDPComp::sPerfLockHandle = 0;
int (*MDPComp::sPerfLockAcquire)(int, int, int*, int) = NULL;
@@ -351,19 +352,11 @@
}
void MDPComp::LayerCache::reset() {
- memset(&hnd, 0, sizeof(hnd));
memset(&isFBComposed, true, sizeof(isFBComposed));
memset(&drop, false, sizeof(drop));
layerCount = 0;
}
-void MDPComp::LayerCache::cacheAll(hwc_display_contents_1_t* list) {
- const int numAppLayers = (int)list->numHwLayers - 1;
- for(int i = 0; i < numAppLayers; i++) {
- hnd[i] = list->hwLayers[i].handle;
- }
-}
-
void MDPComp::LayerCache::updateCounts(const FrameInfo& curFrame) {
layerCount = curFrame.layerCount;
memcpy(&isFBComposed, &curFrame.isFBComposed, sizeof(isFBComposed));
@@ -379,8 +372,8 @@
(curFrame.drop[i] != drop[i])) {
return false;
}
- if(curFrame.isFBComposed[i] &&
- (hnd[i] != list->hwLayers[i].handle)){
+ hwc_layer_1_t const* layer = &list->hwLayers[i];
+ if(curFrame.isFBComposed[i] && layerUpdating(layer)){
return false;
}
}
@@ -525,9 +518,37 @@
return ret;
}
-void MDPCompNonSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect) {
+hwc_rect_t MDPComp::calculateDirtyRect(const hwc_layer_1_t* layer,
+ hwc_rect_t& scissor) {
+ hwc_region_t surfDamage = layer->surfaceDamage;
+ hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
+ hwc_rect_t dst = layer->displayFrame;
+ int x_off = dst.left - src.left;
+ int y_off = dst.top - src.top;
+ hwc_rect dirtyRect = (hwc_rect){0, 0, 0, 0};
+ hwc_rect_t updatingRect = dst;
+
+ if (surfDamage.numRects == 0) {
+ // full layer updating, dirty rect is full frame
+ dirtyRect = getIntersection(layer->displayFrame, scissor);
+ } else {
+ for(uint32_t i = 0; i < surfDamage.numRects; i++) {
+ updatingRect = moveRect(surfDamage.rects[i], x_off, y_off);
+ hwc_rect_t intersect = getIntersection(updatingRect, scissor);
+ if(isValidRect(intersect)) {
+ dirtyRect = getUnion(intersect, dirtyRect);
+ }
+ }
+ }
+
+ return dirtyRect;
+}
+
+void MDPCompNonSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect &crop,
+ hwc_rect &dst) {
hwc_rect_t roi = ctx->listStats[mDpy].lRoi;
- fbRect = getIntersection(fbRect, roi);
+ dst = getIntersection(dst, roi);
+ crop = dst;
}
/* 1) Identify layers that are not visible or lying outside the updating ROI and
@@ -587,22 +608,15 @@
for(int index = 0; index < numAppLayers; index++ ) {
hwc_layer_1_t* layer = &list->hwLayers[index];
- if ((mCachedFrame.hnd[index] != layer->handle) ||
+ if (layerUpdating(layer) ||
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);
+ hwc_rect_t dirtyRect = getIntersection(layer->displayFrame,
+ fullFrame);
+ if(!needsScaling(layer) && !layer->transform) {
+ dirtyRect = calculateDirtyRect(layer, fullFrame);
}
-#endif
- roi = getUnion(roi, updatingRect);
+ roi = getUnion(roi, dirtyRect);
}
}
@@ -622,14 +636,20 @@
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);
+void MDPCompSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect &crop,
+ hwc_rect &dst) {
+ hwc_rect roi = getUnion(ctx->listStats[mDpy].lRoi,
+ ctx->listStats[mDpy].rRoi);
+ hwc_rect tmpDst = getIntersection(dst, roi);
+ if(!isSameRect(dst, tmpDst)) {
+ crop.left = crop.left + (tmpDst.left - dst.left);
+ crop.top = crop.top + (tmpDst.top - dst.top);
+ crop.right = crop.left + (tmpDst.right - tmpDst.left);
+ crop.bottom = crop.top + (tmpDst.bottom - tmpDst.top);
+ dst = tmpDst;
+ }
}
+
/* 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
@@ -703,28 +723,23 @@
for(int index = 0; index < numAppLayers; index++ ) {
hwc_layer_1_t* layer = &list->hwLayers[index];
private_handle_t *hnd = (private_handle_t *)layer->handle;
- if ((mCachedFrame.hnd[index] != layer->handle) ||
- isYuvBuffer(hnd)) {
- 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);
+ if (layerUpdating(layer) || isYuvBuffer(hnd)) {
+ hwc_rect_t l_dirtyRect = getIntersection(layer->displayFrame,
+ l_frame);
+ hwc_rect_t r_dirtyRect = getIntersection(layer->displayFrame,
+ r_frame);
+
+ if(!needsScaling(layer) && !layer->transform) {
+ l_dirtyRect = calculateDirtyRect(layer, l_frame);
+ r_dirtyRect = calculateDirtyRect(layer, r_frame);
}
-#endif
+ if(isValidRect(l_dirtyRect))
+ l_roi = getUnion(l_roi, l_dirtyRect);
- hwc_rect_t l_dst = getIntersection(l_frame, updatingRect);
- if(isValidRect(l_dst))
- l_roi = getUnion(l_roi, l_dst);
+ if(isValidRect(r_dirtyRect))
+ r_roi = getUnion(r_roi, r_dirtyRect);
- hwc_rect_t r_dst = getIntersection(r_frame, updatingRect);
- if(isValidRect(r_dst))
- r_roi = getUnion(r_roi, r_dst);
}
}
@@ -1290,6 +1305,11 @@
}
if(ctx->listStats[mDpy].secureUI)
return false;
+ if (sIsSingleFullScreenUpdate) {
+ // make sure one full screen update
+ sIsSingleFullScreenUpdate = false;
+ return false;
+ }
return true;
}
@@ -1657,7 +1677,8 @@
int fbCount = 0;
for(int i = 0; i < numAppLayers; i++) {
- if (mCachedFrame.hnd[i] == list->hwLayers[i].handle) {
+ hwc_layer_1_t * layer = &list->hwLayers[i];
+ if (!layerUpdating(layer)) {
if(!frame.drop[i])
fbCount++;
frame.isFBComposed[i] = true;
@@ -1761,7 +1782,7 @@
fbRect = getUnion(fbRect, dst);
}
}
- trimAgainstROI(ctx, fbRect);
+ trimAgainstROI(ctx, fbRect, fbRect);
return fbRect;
}
@@ -1994,11 +2015,12 @@
//Do not cache the information for next draw cycle.
if(numLayers > MAX_NUM_APP_LAYERS or (!numLayers)) {
- ALOGI("%s: Unsupported layer count for mdp composition",
- __FUNCTION__);
+ ALOGI_IF(numLayers, "%s: Unsupported layer count for mdp composition: %d",
+ __FUNCTION__, numLayers);
mCachedFrame.reset();
#ifdef DYNAMIC_FPS
- setDynRefreshRate(ctx, list);
+ // Reset refresh rate
+ setRefreshRate(ctx, mDpy, ctx->dpyAttr[mDpy].refreshRate);
#endif
return -1;
}
@@ -2014,7 +2036,8 @@
setMDPCompLayerFlags(ctx, list);
mCachedFrame.updateCounts(mCurrentFrame);
#ifdef DYNAMIC_FPS
- setDynRefreshRate(ctx, list);
+ // Reset refresh rate
+ setRefreshRate(ctx, mDpy, ctx->dpyAttr[mDpy].refreshRate);
#endif
ret = -1;
return ret;
@@ -2072,7 +2095,6 @@
#endif
setPerfHint(ctx, list);
- mCachedFrame.cacheAll(list);
mCachedFrame.updateCounts(mCurrentFrame);
return ret;
}
@@ -2608,6 +2630,120 @@
}
//================MDPCompSrcSplit==============================================
+
+bool MDPCompSrcSplit::validateAndApplyROI(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list) {
+ int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+ 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++;
+ continue;
+ }
+
+ const hwc_layer_1_t* layer = &list->hwLayers[i];
+ hwc_rect_t dstRect = layer->displayFrame;
+ hwc_rect_t res = getIntersection(visibleRect, dstRect);
+
+ if(!isValidRect(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)) {
+ ALOGI("%s: Resetting ROI due to scaling", __FUNCTION__);
+ memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
+ mCurrentFrame.dropCount = 0;
+ return false;
+ }
+
+ /* deduct any opaque region from visibleRect */
+ if (layer->blending == HWC_BLENDING_NONE &&
+ layer->planeAlpha == 0xFF)
+ visibleRect = deductRect(visibleRect, res);
+ }
+ }
+ return true;
+}
+
+/*
+ * HW Limitation: ping pong split can always split the ping pong output
+ * equally across two DSI's. So the ROI programmed should be of equal width
+ * for both the halves
+ */
+void MDPCompSrcSplit::generateROI(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list) {
+ int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+
+ 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 we have a RGB layer which needs rotation, no partial update
+ if(!isYuvBuffer((private_handle_t *)layer->handle) && layer->transform)
+ return;
+
+ if (layerUpdating(layer) ||
+ isYuvBuffer((private_handle_t *)layer->handle)) {
+ hwc_rect_t dirtyRect = getIntersection(layer->displayFrame,
+ fullFrame);
+ if (!needsScaling(layer) && !layer->transform) {
+ dirtyRect = calculateDirtyRect(layer, fullFrame);
+ }
+ roi = getUnion(roi, dirtyRect);
+ }
+ }
+
+ /* No layer is updating. Still SF wants a refresh.*/
+ if(!isValidRect(roi))
+ return;
+
+ if (isDisplaySplit(ctx, mDpy)) {
+ hwc_rect lFrame = fullFrame;
+ roi = expandROIFromMidPoint(roi, fullFrame);
+
+ lFrame.right = fullFrame.right / 2;
+ hwc_rect lRoi = getIntersection(roi, lFrame);
+ // Align ROI coordinates to panel restrictions
+ lRoi = getSanitizeROI(lRoi, lFrame);
+
+ hwc_rect rFrame = fullFrame;
+ rFrame.left = fullFrame.right/2;
+ hwc_rect rRoi = getIntersection(roi, rFrame);
+ // Align ROI coordinates to panel restrictions
+ rRoi = getSanitizeROI(rRoi, rFrame);
+
+ roi = getUnion(lRoi, rRoi);
+
+ ctx->listStats[mDpy].lRoi = roi;
+ } else {
+ hwc_rect lRoi = getIntersection(roi, fullFrame);
+ // Align ROI coordinates to panel restrictions
+ lRoi = getSanitizeROI(lRoi, fullFrame);
+
+ ctx->listStats[mDpy].lRoi = lRoi;
+ }
+
+ if(!validateAndApplyROI(ctx, list))
+ resetROI(ctx, mDpy);
+
+ ALOGD_IF(isDebug(),"%s: generated ROI: [%d, %d, %d, %d] [%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);
+}
+
bool MDPCompSrcSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
MdpPipeInfoSplit& pipe_info) {
private_handle_t *hnd = (private_handle_t *)layer->handle;
@@ -2616,6 +2752,9 @@
pipe_info.lIndex = ovutils::OV_INVALID;
pipe_info.rIndex = ovutils::OV_INVALID;
+ if(qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() && !mDpy)
+ trimAgainstROI(ctx,crop, dst);
+
//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
@@ -2647,19 +2786,21 @@
const uint32_t lSplit = getLeftSplit(ctx, mDpy);
const uint32_t dstWidth = dst.right - dst.left;
const uint32_t dstHeight = dst.bottom - dst.top;
- const uint32_t cropWidth = has90Transform(layer) ? crop.bottom - crop.top :
+ uint32_t cropWidth = has90Transform(layer) ? crop.bottom - crop.top :
crop.right - crop.left;
- const uint32_t cropHeight = has90Transform(layer) ? crop.right - crop.left :
+ uint32_t cropHeight = has90Transform(layer) ? crop.right - crop.left :
crop.bottom - crop.top;
//Approximation to actual clock, ignoring the common factors in pipe and
//mixer cases like line_time
const uint32_t layerClock = getLayerClock(dstWidth, dstHeight, cropHeight);
const uint32_t mixerClock = lSplit;
- //TODO Even if a 4k video is going to be rot-downscaled to dimensions under
- //pipe line length, we are still using 2 pipes. This is fine just because
- //this is source split where destination doesn't matter. Evaluate later to
- //see if going through all the calcs to save a pipe is worth it
+ const uint32_t downscale = getRotDownscale(ctx, layer);
+ if(downscale) {
+ cropWidth /= downscale;
+ cropHeight /= downscale;
+ }
+
if(dstWidth > mdpHw.getMaxPipeWidth() or
cropWidth > mdpHw.getMaxPipeWidth() or
(primarySplitAlways and
@@ -2669,12 +2810,8 @@
return false;
}
- // Return values
- // 1 Left pipe is higher priority, do nothing.
- // 0 Pipes of same priority.
- //-1 Right pipe is of higher priority, needs swap.
- if(ctx->mOverlay->comparePipePriority(pipe_info.lIndex,
- pipe_info.rIndex) == -1) {
+ if(ctx->mOverlay->needsPrioritySwap(pipe_info.lIndex,
+ pipe_info.rIndex)) {
qhwc::swap(pipe_info.lIndex, pipe_info.rIndex);
}
}
@@ -2707,6 +2844,17 @@
ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
"dest_pipeR: %d",__FUNCTION__, layer, z, lDest, rDest);
+ if(qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() && !mDpy) {
+ /* MDP driver crops layer coordinates against ROI in Non-Split
+ * and Split MDP comp. But HWC needs to crop them for source split.
+ * Reason: 1) Source split is efficient only when the final effective
+ * load is distributed evenly across mixers.
+ * 2) We have to know the effective width of the layer that
+ * the ROI needs to find the no. of pipes the layer needs.
+ */
+ trimAgainstROI(ctx, crop, dst);
+ }
+
// Handle R/B swap
if (layer->flags & HWC_FORMAT_RB_SWAP) {
if (hnd->format == HAL_PIXEL_FORMAT_RGBA_8888)
@@ -2910,9 +3058,7 @@
int perfHint = 0x4501; // 45-display layer hint, 01-Enable
sPerfLockHandle = sPerfLockAcquire(0 /*handle*/, 0/*duration*/,
&perfHint, sizeof(perfHint)/sizeof(int));
- if(sPerfLockHandle < 0) {
- ALOGE("Perf Lock Acquire Failed");
- } else {
+ if(sPerfLockHandle > 0) {
perflockFlag = 1;
}
}
diff --git a/msm8994/libhwcomposer/hwc_mdpcomp.h b/msm8994/libhwcomposer/hwc_mdpcomp.h
index 302b047..ca03392 100644
--- a/msm8994/libhwcomposer/hwc_mdpcomp.h
+++ b/msm8994/libhwcomposer/hwc_mdpcomp.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2013, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2012-2015, The Linux Foundation. All rights reserved.
*
* Not a Contribution, Apache license notifications and license are retained
* for attribution purposes only.
@@ -59,6 +59,7 @@
static int setPartialUpdatePref(hwc_context_t *ctx, bool enable);
static bool getPartialUpdatePref(hwc_context_t *ctx);
void setDynRefreshRate(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+ static void setSingleFullScreenUpdate() { sIsSingleFullScreenUpdate = true; }
protected:
enum ePipeType {
@@ -127,7 +128,6 @@
/* cached data */
struct LayerCache {
int layerCount;
- buffer_handle_t hnd[MAX_NUM_APP_LAYERS];
bool isFBComposed[MAX_NUM_APP_LAYERS];
bool drop[MAX_NUM_APP_LAYERS];
@@ -135,7 +135,6 @@
LayerCache();
/* clear caching info*/
void reset();
- void cacheAll(hwc_display_contents_1_t* list);
void updateCounts(const FrameInfo&);
bool isSameFrame(const FrameInfo& curFrame,
hwc_display_contents_1_t* list);
@@ -157,12 +156,15 @@
/* generates ROI based on the modified area of the frame */
virtual void generateROI(hwc_context_t *ctx,
hwc_display_contents_1_t* list) = 0;
+ /* Calculates the dirtyRegion for the given layer */
+ hwc_rect_t calculateDirtyRect(const hwc_layer_1_t* layer,
+ hwc_rect_t& scissor);
/* 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;
-
+ /* Trims layer coordinates against ROI generated */
+ virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& crop,
+ hwc_rect& dst) = 0;
/* set/reset flags for MDPComp */
void setMDPCompLayerFlags(hwc_context_t *ctx,
hwc_display_contents_1_t* list);
@@ -263,6 +265,7 @@
static int sMaxPipesPerMixer;
static bool sSrcSplitEnabled;
static IdleInvalidator *sIdleInvalidator;
+ static bool sIsSingleFullScreenUpdate;
static int sMaxSecLayers;
static bool sIsPartialUpdateActive;
struct FrameInfo mCurrentFrame;
@@ -315,8 +318,9 @@
/* 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);
+ /* Trims layer coordinates against ROI generated */
+ virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& crop,
+ hwc_rect& dst);
};
class MDPCompSplit : public MDPComp {
@@ -342,6 +346,9 @@
/* allocates pipes to selected candidates */
virtual bool allocLayerPipes(hwc_context_t *ctx,
hwc_display_contents_1_t* list);
+ /* Trims layer coordinates against ROI generated */
+ virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& crop,
+ hwc_rect& dst);
private:
/* Increments mdpCount if 4k2k yuv layer split is enabled.
* updates framebuffer z order if fb lies above source-split layer */
@@ -357,8 +364,6 @@
/* 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 {
@@ -371,6 +376,12 @@
virtual int configure(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);
};
}; //namespace
diff --git a/msm8994/libhwcomposer/hwc_qclient.cpp b/msm8994/libhwcomposer/hwc_qclient.cpp
index 09013c6..6d05d38 100644
--- a/msm8994/libhwcomposer/hwc_qclient.cpp
+++ b/msm8994/libhwcomposer/hwc_qclient.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-14, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-15, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -35,6 +35,7 @@
#include <hwc_virtual.h>
#include <overlay.h>
#include <display_config.h>
+#include <dlfcn.h>
#define QCLIENT_DEBUG 0
@@ -338,6 +339,14 @@
}
}
+static void applyModeById(hwc_context_t* ctx, int32_t modeId) {
+ int err = ctx->mColorMode->applyModeByID(modeId);
+ if (err)
+ ALOGD("%s: Not able to apply mode: %d", __FUNCTION__, modeId);
+ else
+ ctx->proc->invalidate(ctx->proc);
+}
+
status_t QClient::notifyCallback(uint32_t command, const Parcel* inParcel,
Parcel* outParcel) {
status_t ret = NO_ERROR;
@@ -350,6 +359,7 @@
unsecuring(mHwcContext, inParcel->readInt32());
break;
case IQService::SCREEN_REFRESH:
+ qhwc::MDPComp::setSingleFullScreenUpdate();
return screenRefresh(mHwcContext);
break;
case IQService::EXTERNAL_ORIENTATION:
@@ -398,6 +408,9 @@
case IQService::TOGGLE_SCREEN_UPDATE:
toggleScreenUpdate(mHwcContext, inParcel->readInt32());
break;
+ case IQService::APPLY_MODE_BY_ID:
+ applyModeById(mHwcContext, inParcel->readInt32());
+ break;
default:
ret = NO_ERROR;
}
diff --git a/msm8994/libhwcomposer/hwc_utils.cpp b/msm8994/libhwcomposer/hwc_utils.cpp
index 8139013..98c4166 100644
--- a/msm8994/libhwcomposer/hwc_utils.cpp
+++ b/msm8994/libhwcomposer/hwc_utils.cpp
@@ -44,6 +44,7 @@
#include "hwc_virtual.h"
#include "qd_utils.h"
#include <sys/sysinfo.h>
+#include <dlfcn.h>
using namespace qClient;
using namespace qService;
@@ -389,6 +390,9 @@
property_get("debug.sf.hwc.canUseABC", value, "0");
ctx->enableABC = atoi(value) ? true : false;
+ // Initializing boot anim completed check to false
+ ctx->mDefaultModeApplied = false;
+
// Initialize gpu perfomance hint related parameters
property_get("sys.hwc.gpu_perf_mode", value, "0");
#ifdef QCOM_BSP
@@ -414,6 +418,8 @@
memset(&(ctx->mPtorInfo), 0, sizeof(ctx->mPtorInfo));
ctx->mHPDEnabled = false;
+ ctx->mColorMode = new ColorMode();
+ ctx->mColorMode->init();
ALOGI("Initializing Qualcomm Hardware Composer");
ALOGI("MDP version: %d", ctx->mMDP.version);
}
@@ -468,7 +474,11 @@
ctx->mAD = NULL;
}
-
+ if(ctx->mColorMode) {
+ ctx->mColorMode->destroy();
+ delete ctx->mColorMode;
+ ctx->mColorMode = NULL;
+ }
}
//Helper to roundoff the refreshrates
@@ -1311,6 +1321,12 @@
return false;
}
+bool layerUpdating(const hwc_layer_1_t* layer) {
+ hwc_region_t surfDamage = layer->surfaceDamage;
+ return ((surfDamage.numRects == 0) ||
+ isValidRect(layer->surfaceDamage.rects[0]));
+}
+
hwc_rect_t moveRect(const hwc_rect_t& rect, const int& x_off, const int& y_off)
{
hwc_rect_t res;
@@ -2492,6 +2508,27 @@
return (eqBounds == 3);
}
+void applyDefaultMode(hwc_context_t *ctx) {
+ char value[PROPERTY_VALUE_MAX];
+ int boot_finished = 0;
+ static int ret = ctx->mColorMode->applyDefaultMode();
+ if(!ret) {
+ ctx->mDefaultModeApplied = true;
+ return;
+ }
+
+ // Reading property set on boot finish in SF
+ property_get("service.bootanim.exit", value, "0");
+ boot_finished = atoi(value);
+ if (!boot_finished)
+ return;
+
+ ret = ctx->mColorMode->applyDefaultMode();
+ if (ret)
+ ALOGD("%s: Not able to apply default mode", __FUNCTION__);
+ ctx->mDefaultModeApplied = true;
+}
+
void BwcPM::setBwc(const hwc_context_t *ctx, const int& dpy,
const private_handle_t *hnd,
const hwc_rect_t& crop, const hwc_rect_t& dst,
@@ -2522,6 +2559,10 @@
if(src_w > (int) qdutils::MDPVersion::getInstance().getMaxPipeWidth()) {
return;
}
+ //H/w requirement for BWC only. Pipe can still support 4096
+ if(src_h > 4092) {
+ return;
+ }
//Decimation necessary, cannot use BWC. H/W requirement.
if(qdutils::MDPVersion::getInstance().supportsDecimation()) {
uint8_t horzDeci = 0;
@@ -2578,10 +2619,40 @@
}
}
+hwc_rect expandROIFromMidPoint(hwc_rect roi, hwc_rect fullFrame) {
+ int lRoiWidth = 0, rRoiWidth = 0;
+ int half_frame_width = fullFrame.right/2;
+
+ hwc_rect lFrame = fullFrame;
+ hwc_rect rFrame = fullFrame;
+ lFrame.right = (lFrame.right - lFrame.left)/2;
+ rFrame.left = lFrame.right;
+
+ hwc_rect lRoi = getIntersection(roi, lFrame);
+ hwc_rect rRoi = getIntersection(roi, rFrame);
+
+ lRoiWidth = lRoi.right - lRoi.left;
+ rRoiWidth = rRoi.right - rRoi.left;
+
+ if(lRoiWidth && rRoiWidth) {
+ if(lRoiWidth < rRoiWidth)
+ roi.left = half_frame_width - rRoiWidth;
+ else
+ roi.right = half_frame_width + lRoiWidth;
+ }
+ return roi;
+}
+
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)) {
+
+ /* When source split is enabled, both the panels are calibrated
+ * in a single coordinate system. So only one ROI is generated
+ * for the whole panel extending equally from the midpoint and
+ * populated for the left side. */
+ if(!qdutils::MDPVersion::getInstance().isSrcSplit() &&
+ 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};
@@ -2607,18 +2678,28 @@
/* Align to minimum width recommended by the panel */
if((t_roi.right - t_roi.left) < MIN_WIDTH) {
- if((t_roi.left + MIN_WIDTH) > boundary.right)
- t_roi.left = t_roi.right - MIN_WIDTH;
- else
- t_roi.right = t_roi.left + MIN_WIDTH;
+ if(MIN_WIDTH == boundary.right - boundary.left) {
+ t_roi.left = 0;
+ t_roi.right = MIN_WIDTH;
+ } else {
+ if((t_roi.left + MIN_WIDTH) > boundary.right)
+ t_roi.left = t_roi.right - MIN_WIDTH;
+ else
+ 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;
+ if(MIN_HEIGHT == boundary.bottom - boundary.top) {
+ t_roi.top = 0;
+ t_roi.bottom = MIN_HEIGHT;
+ } else {
+ 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 */
@@ -2639,7 +2720,6 @@
}
}
-
/* Align top and height to meet panel restrictions */
if(TOP_ALIGN)
t_roi.top = t_roi.top - (t_roi.top % TOP_ALIGN);
@@ -2658,7 +2738,6 @@
}
}
-
return t_roi;
}
@@ -2769,4 +2848,104 @@
}
}
+void ColorMode::init() {
+ //Map symbols from libmm-qdcm and get list of modes
+ mModeHandle = dlopen("libmm-qdcm.so", RTLD_NOW);
+ if (mModeHandle) {
+ *(void **)& fnApplyDefaultMode = dlsym(mModeHandle, "applyDefaults");
+ *(void **)& fnApplyModeById = dlsym(mModeHandle, "applyModeById");
+ *(void **)& fnGetNumModes = dlsym(mModeHandle, "getNumDisplayModes");
+ *(void **)& fnGetModeList = dlsym(mModeHandle, "getDisplayModeIdList");
+ *(void **)& fnSetDefaultMode = dlsym(mModeHandle, "setDefaultMode");
+ } else {
+ ALOGW("Unable to load libmm-qdcm");
+ }
+
+ if(fnGetNumModes) {
+ mNumModes = fnGetNumModes(HWC_DISPLAY_PRIMARY);
+ if(mNumModes > MAX_NUM_COLOR_MODES) {
+ ALOGE("Number of modes is above the limit: %d", mNumModes);
+ mNumModes = 0;
+ return;
+ }
+ if(fnGetModeList) {
+ fnGetModeList(mModeList, &mCurMode, HWC_DISPLAY_PRIMARY);
+ mCurModeIndex = getIndexForMode(mCurMode);
+ ALOGI("ColorMode: current mode: %d current mode index: %d number of modes: %d",
+ mCurMode, mCurModeIndex, mNumModes);
+ }
+ }
+}
+
+//Legacy API
+int ColorMode::applyDefaultMode() {
+ if(fnApplyDefaultMode) {
+ return fnApplyDefaultMode(HWC_DISPLAY_PRIMARY);
+ } else {
+ return -EINVAL;
+ }
+}
+
+int ColorMode::applyModeByID(int modeID) {
+ if(fnApplyModeById) {
+ int ret = fnApplyModeById(modeID, HWC_DISPLAY_PRIMARY);
+ if (!ret)
+ ret = setDefaultMode(modeID);
+ return ret;
+ } else {
+ return -EINVAL;
+ }
+}
+
+//This API is called from setActiveConfig
+//The value here must be set as default
+int ColorMode::applyModeByIndex(int index) {
+ int ret = 0;
+ int mode = getModeForIndex(index);
+ if(mode < 0) {
+ ALOGE("Invalid mode for index: %d", index);
+ return -EINVAL;
+ }
+ ALOGD("%s: Applying mode index: %d modeID: %d", __FUNCTION__, index, mode);
+ ret = applyModeByID(mode);
+ if(!ret) {
+ mCurModeIndex = index;
+ setDefaultMode(mode);
+ }
+ return ret;
+}
+
+int ColorMode::setDefaultMode(int modeID) {
+ if(fnSetDefaultMode) {
+ ALOGD("Setting default color mode to %d", modeID);
+ return fnSetDefaultMode(modeID, HWC_DISPLAY_PRIMARY);
+ } else {
+ return -EINVAL;
+ }
+}
+
+int ColorMode::getModeForIndex(int index) {
+ if(index < mNumModes) {
+ return mModeList[index];
+ } else {
+ return -EINVAL;
+ }
+}
+
+int ColorMode::getIndexForMode(int mode) {
+ if(mModeList) {
+ for(int32_t i = 0; i < mNumModes; i++)
+ if(mModeList[i] == mode)
+ return i;
+ }
+ return -EINVAL;
+}
+
+void ColorMode::destroy() {
+ if(mModeHandle) {
+ dlclose(mModeHandle);
+ mModeHandle = NULL;
+ }
+}
+
};//namespace qhwc
diff --git a/msm8994/libhwcomposer/hwc_utils.h b/msm8994/libhwcomposer/hwc_utils.h
index 797f9b0..c9f35e5 100644
--- a/msm8994/libhwcomposer/hwc_utils.h
+++ b/msm8994/libhwcomposer/hwc_utils.h
@@ -48,6 +48,7 @@
#define STR(f) #f;
// Max number of PTOR layers handled
#define MAX_PTOR_LAYERS 2
+#define MAX_NUM_COLOR_MODES 32
//Fwrd decls
struct hwc_context_t;
@@ -229,6 +230,36 @@
uint32_t mCount;
};
+//ColorModes for primary displays
+class ColorMode {
+public:
+ void init();
+ void destroy();
+ int32_t getNumModes() { return mNumModes; }
+ const int32_t* getModeList() { return mModeList; }
+ int32_t getModeForIndex(int32_t index);
+ int32_t getIndexForMode(int32_t mode);
+ int applyDefaultMode();
+ int applyModeByID(int modeID);
+ int applyModeByIndex(int index);
+ int setDefaultMode(int modeID);
+ int getActiveModeIndex() { return mCurModeIndex; }
+private:
+ int32_t (*fnGetNumModes)(int /*dispID*/);
+ int32_t (*fnGetModeList)(int32_t* /*mModeList*/, int32_t* /*current default*/,
+ int32_t /*dispID*/);
+ int (*fnApplyDefaultMode)(int /*dispID*/);
+ int (*fnApplyModeById)(int /*modeID*/, int /*dispID*/);
+ int (*fnSetDefaultMode)(int /*modeID*/, int /*dispID*/);
+
+ void* mModeHandle = NULL;
+ int32_t mModeList[MAX_NUM_COLOR_MODES];
+ int32_t mNumModes = 0;
+ int32_t mCurModeIndex = 0;
+ int32_t mCurMode = 0;
+
+};
+
inline uint32_t LayerRotMap::getCount() const {
return mCount;
}
@@ -316,6 +347,7 @@
bool areLayersIntersecting(const hwc_layer_1_t* layer1,
const hwc_layer_1_t* layer2);
bool operator ==(const hwc_rect_t& lhs, const hwc_rect_t& rhs);
+bool layerUpdating(const hwc_layer_1_t* layer);
// returns true if Action safe dimensions are set and target supports Actionsafe
bool isActionSafePresent(hwc_context_t *ctx, int dpy);
@@ -352,6 +384,9 @@
// Resets display ROI to full panel resoluion
void resetROI(hwc_context_t *ctx, const int dpy);
+// Modifies ROI even from middle of the screen
+hwc_rect expandROIFromMidPoint(hwc_rect roi, hwc_rect fullFrame);
+
// Aligns updating ROI to panel restrictions
hwc_rect_t getSanitizeROI(struct hwc_rect roi, hwc_rect boundary);
@@ -439,6 +474,9 @@
// Returns true if rect1 is peripheral to rect2, false otherwise.
bool isPeripheral(const hwc_rect_t& rect1, const hwc_rect_t& rect2);
+// Applies default mode at boot
+void applyDefaultMode(hwc_context_t *ctx);
+
// Inline utility functions
static inline bool isSkipLayer(const hwc_layer_1_t* l) {
return (UNLIKELY(l && (l->flags & HWC_SKIP_LAYER)));
@@ -641,6 +679,10 @@
bool mUseMetaDataRefreshRate;
// Stores the hpd enabled status- avoids re-enabling HDP on suspend resume.
bool mHPDEnabled;
+ //Used to notify that default mode has been applied
+ bool mDefaultModeApplied;
+ //Manages color modes
+ qhwc::ColorMode *mColorMode;
};
namespace qhwc {
diff --git a/msm8994/libhwcomposer/hwc_virtual.cpp b/msm8994/libhwcomposer/hwc_virtual.cpp
index 06418bf..a294a75 100644
--- a/msm8994/libhwcomposer/hwc_virtual.cpp
+++ b/msm8994/libhwcomposer/hwc_virtual.cpp
@@ -223,13 +223,15 @@
private_handle_t* ohnd, int dpy) {
bool scalingMode = false;
int fbWidth = ctx->dpyAttr[dpy].xres;
- int fbHeight = ctx->dpyAttr[dpy].yres;
- if((getWidth(ohnd) != fbWidth) || (getHeight(ohnd) != fbHeight)) {
+ int fbHeight = ctx->dpyAttr[dpy].yres;
+ int alW = 0, alH = 0;
+ getBufferSizeAndDimensions(fbWidth, fbHeight, ohnd->format, alW, alH);
+ if((getWidth(ohnd) != alW) || (getHeight(ohnd) != alH)) {
scalingMode = true;
}
ctx->dpyAttr[dpy].mMDPScalingMode = scalingMode;
ALOGD_IF(HWCVIRTUAL_LOG, "%s fb(%dx%d) outputBuffer(%dx%d) scalingMode=%d",
- __FUNCTION__, fbWidth, fbHeight,
+ __FUNCTION__, alW, alH,
getWidth(ohnd), getHeight(ohnd), scalingMode);
}
diff --git a/msm8994/libmemtrack/kgsl.c b/msm8994/libmemtrack/kgsl.c
index 6dc9774..3a63d09 100644
--- a/msm8994/libmemtrack/kgsl.c
+++ b/msm8994/libmemtrack/kgsl.c
@@ -99,7 +99,7 @@
* gpuaddr useraddr size id flags type usage sglen
* 545ba000 545ba000 4096 1 ----pY gpumem arraybuffer 1
*/
- ret = sscanf(line, "%*x %*x %lu %*d %6s %6s %18s %*d\n",
+ ret = sscanf(line, "%*x %*lx %lu %*d %6s %6s %18s %*d\n",
&size, flags, line_type, line_usage);
if (ret != 4) {
continue;
@@ -113,7 +113,7 @@
unaccounted_size += size;
} else if (type == MEMTRACK_TYPE_GRAPHICS && strcmp(line_type, "ion") == 0) {
- if ( !(is_surfaceflinger == false && strcmp(line_usage, "egl_surface") == 0)) {
+ if (!is_surfaceflinger || strcmp(line_usage, "egl_image") != 0) {
unaccounted_size += size;
}
}
diff --git a/msm8994/liboverlay/overlay.cpp b/msm8994/liboverlay/overlay.cpp
index c250919..a34e599 100644
--- a/msm8994/liboverlay/overlay.cpp
+++ b/msm8994/liboverlay/overlay.cpp
@@ -282,38 +282,62 @@
return false;
}
-int Overlay::comparePipePriority(utils::eDest pipe1Index,
+bool Overlay::needsPrioritySwap(utils::eDest pipe1Index,
utils::eDest pipe2Index) {
validate((int)pipe1Index);
validate((int)pipe2Index);
+
uint8_t pipe1Prio = mPipeBook[(int)pipe1Index].mPipe->getPriority();
uint8_t pipe2Prio = mPipeBook[(int)pipe2Index].mPipe->getPriority();
- if(pipe1Prio > pipe2Prio)
- return -1;
- else if(pipe1Prio < pipe2Prio)
- return 1;
- else {
+
+ int pipe1Id = mPipeBook[(int)pipe1Index].mPipe->getPipeId();
+ int pipe2Id = mPipeBook[(int)pipe2Index].mPipe->getPipeId();
+
+ utils::eMdpPipeType leftType = PipeBook::getPipeType(pipe1Index);
+ utils::eMdpPipeType rightType = PipeBook::getPipeType(pipe2Index);
+
+ if(pipe1Id >=0 && pipe2Id >=0) {
+ // LEFT priority should be higher then RIGHT
+ return (pipe1Prio > pipe2Prio);
+ } else if(pipe1Id < 0 && pipe2Id < 0) {
// If we are here, Source Split is enabled and both pipes are
// new requests. In this case left type should be of higher prio
// than right type
- utils::eMdpPipeType leftType = PipeBook::getPipeType(pipe1Index);
- utils::eMdpPipeType rightType = PipeBook::getPipeType(pipe2Index);
-
if(leftType == rightType) {
//Safe. Onus on driver to assign correct pipes within same type
- return 1;
- } else if(leftType == OV_MDP_PIPE_DMA or rightType == OV_MDP_PIPE_VG) {
- //If we are here, right is definitely a higher prio type.
+ return false;
+ } else {
//This check takes advantage of having only 3 types and avoids 3
//different failure combination checks.
- return -1;
+ // Swap IF:
+ // ----------------
+ // | Left | Right |
+ // ================
+ // | DMA | ViG |
+ // ----------------
+ // | DMA | RGB |
+ // ----------------
+ // | RGB | ViG |
+ // ----------------
+ return (leftType == OV_MDP_PIPE_DMA or rightType == OV_MDP_PIPE_VG);
+ }
+ } else if(pipe1Id < 0) {
+ //LEFT needs new allocation.
+ if(leftType == rightType) {
+ // If RIGHT has highest priority(lowest id), swap it.
+ return (pipe2Id == PipeBook::pipeMinID[leftType]);
} else {
- //Types are correct priority-wise
- return 1;
+ return (leftType == OV_MDP_PIPE_DMA or rightType == OV_MDP_PIPE_VG);
+ }
+ } else { /* if (pipe2Id < 0) */
+ // RIGHT needs new allocation.
+ if(leftType == rightType) {
+ // If LEFT has lowest priority(highest id), swap it.
+ return (pipe1Id == PipeBook::pipeMaxID[leftType]);
+ } else {
+ return (leftType == OV_MDP_PIPE_DMA or rightType == OV_MDP_PIPE_VG);
}
}
-
- return 0;
}
bool Overlay::commit(utils::eDest dest) {
@@ -413,6 +437,13 @@
}
}
+ PipeBook::pipeMinID[OV_MDP_PIPE_RGB] = 8;
+ PipeBook::pipeMaxID[OV_MDP_PIPE_RGB] = (numPipesXType[OV_MDP_PIPE_RGB] == 3)? 32 : 512;
+ PipeBook::pipeMinID[OV_MDP_PIPE_VG] = 1;
+ PipeBook::pipeMaxID[OV_MDP_PIPE_VG] = (numPipesXType[OV_MDP_PIPE_VG] == 3)? 4 : 256;
+ PipeBook::pipeMinID[OV_MDP_PIPE_DMA] = 64;
+ PipeBook::pipeMaxID[OV_MDP_PIPE_DMA] = 128;
+
FILE *displayDeviceFP = NULL;
char fbType[MAX_FRAME_BUFFER_NAME_SIZE];
char msmFbTypePath[MAX_FRAME_BUFFER_NAME_SIZE];
@@ -578,6 +609,8 @@
int Overlay::PipeBook::sAllocatedBitmap = 0;
utils::eMdpPipeType Overlay::PipeBook::pipeTypeLUT[utils::OV_MAX] =
{utils::OV_MDP_PIPE_ANY};
+int Overlay::PipeBook::pipeMinID[utils::OV_MDP_PIPE_ANY] = {0};
+int Overlay::PipeBook::pipeMaxID[utils::OV_MDP_PIPE_ANY] = {0};
void *Overlay::sLibScaleHandle = NULL;
int (*Overlay::sFnProgramScale)(struct mdp_overlay_list *) = NULL;
/* Dynamically link ABL library */
diff --git a/msm8994/liboverlay/overlay.h b/msm8994/liboverlay/overlay.h
index 984b439..45b5e57 100644
--- a/msm8994/liboverlay/overlay.h
+++ b/msm8994/liboverlay/overlay.h
@@ -123,11 +123,10 @@
*/
bool isPipeTypeAttached(utils::eMdpPipeType type);
/* Compare pipe priorities and return
- * 1 if 1st pipe has a higher priority
- * 0 if both have the same priority
- *-1 if 2nd pipe has a higher priority
+ * true - A swap is needed to fix the priority.
+ * false - Good, priority wise.
*/
- int comparePipePriority(utils::eDest pipe1Index, utils::eDest pipe2Index);
+ bool needsPrioritySwap(utils::eDest pipe1Index, utils::eDest pipe2Index);
/* Returns pipe dump. Expects a NULL terminated buffer of big enough size
* to populate.
*/
@@ -229,6 +228,9 @@
static int NUM_PIPES;
static utils::eMdpPipeType pipeTypeLUT[utils::OV_MAX];
+ static int pipeMinID[utils::OV_MDP_PIPE_ANY];
+ static int pipeMaxID[utils::OV_MDP_PIPE_ANY];
+
/* Session for reserved pipes */
enum Session {
NONE,
diff --git a/msm8994/liboverlay/overlayMdp.cpp b/msm8994/liboverlay/overlayMdp.cpp
index 3932c4c..04e6672 100644
--- a/msm8994/liboverlay/overlayMdp.cpp
+++ b/msm8994/liboverlay/overlayMdp.cpp
@@ -353,8 +353,31 @@
mdp_overlay* ovArray[count];
memset(&ovArray, 0, sizeof(ovArray));
+ uint8_t max_horz_deci = 0, max_vert_deci = 0;
+
+ // Decimation factor for the left and right pipe differs, when there is a
+ // one pixel difference in the dst width of right pipe and the left pipe.
+ // libscalar returns a failure as it expects decimation on both the pipe
+ // to be same. So compare the decimation factor on both the pipes and assign
+ // the maximum of it.
for(int i = 0; i < count; i++) {
- ovArray[i] = &mdpCtrlArray[i]->mOVInfo;
+ mdp_overlay *ov_current = &mdpCtrlArray[i]->mOVInfo;
+ for(int j = i + 1; j < count; j++) {
+ mdp_overlay *ov_next = &mdpCtrlArray[j]->mOVInfo;
+ if(ov_current->z_order == ov_next->z_order) {
+ max_horz_deci = utils::max(ov_current->horz_deci,
+ ov_next->horz_deci);
+ max_vert_deci = utils::max(ov_current->vert_deci,
+ ov_next->vert_deci);
+
+ ov_current->horz_deci = max_horz_deci;
+ ov_next->horz_deci = max_horz_deci;
+ ov_current->vert_deci = max_vert_deci;
+ ov_next->vert_deci = max_vert_deci;
+ break;
+ }
+ }
+ ovArray[i] = ov_current;
}
struct mdp_overlay_list list;
diff --git a/msm8994/libqdutils/mdp_version.cpp b/msm8994/libqdutils/mdp_version.cpp
index 402e129..5949dc9 100644
--- a/msm8994/libqdutils/mdp_version.cpp
+++ b/msm8994/libqdutils/mdp_version.cpp
@@ -256,6 +256,7 @@
ALOGI("PartialUpdate disabled by property");
}
fclose(panelInfoNodeFP);
+ free(readLine);
} else {
ALOGE("Failed to open msm_fb_panel_info node");
}
diff --git a/msm8994/libqdutils/qd_utils.cpp b/msm8994/libqdutils/qd_utils.cpp
index 5726202..d841712 100644
--- a/msm8994/libqdutils/qd_utils.cpp
+++ b/msm8994/libqdutils/qd_utils.cpp
@@ -53,14 +53,14 @@
}
fclose(displayDeviceFP);
} else {
- ALOGE("%s: Failed to open fb node %d", __func__, j);
+ ALOGD("%s: fb node %d not present", __func__, j);
}
}
if (j < HWC_NUM_DISPLAY_TYPES)
return j;
else
- ALOGE("%s: Failed to find HDMI node", __func__);
+ ALOGI("%s: No HDMI node on this device", __func__);
return -1;
}
diff --git a/msm8994/libqservice/IQService.h b/msm8994/libqservice/IQService.h
index ef47475..8ece946 100644
--- a/msm8994/libqservice/IQService.h
+++ b/msm8994/libqservice/IQService.h
@@ -59,6 +59,7 @@
CONFIGURE_DYN_REFRESH_RATE = 18,
SET_PARTIAL_UPDATE = 19, // Preference on partial update feature
TOGGLE_SCREEN_UPDATE = 20, // Provides ability to disable screen updates
+ APPLY_MODE_BY_ID = 40, //Apply display mode by ID
COMMAND_LIST_END = 400,
};