Merge "display: libqdutils: add the MDP h/w version for msmferrum"
diff --git a/libexternal/external.cpp b/libexternal/external.cpp
index d12d9f0..0a1335a 100644
--- a/libexternal/external.cpp
+++ b/libexternal/external.cpp
@@ -589,9 +589,11 @@
// if primary resolution is more than the hdmi resolution
// configure dpy attr to primary resolution and set
// downscale mode
- // Restrict this upto 1080p resolution max
- if(((priW * priH) > (width * height)) &&
- ((priW * priH) <= SUPPORTED_DOWNSCALE_AREA)) {
+ // Restrict this upto 1080p resolution max, if target does not
+ // support source split feature.
+ if((priW * priH) > (width * height) &&
+ (((priW * priH) <= SUPPORTED_DOWNSCALE_AREA) ||
+ qdutils::MDPVersion::getInstance().isSrcSplit())) {
// tmpW and tmpH will hold the primary dimensions before we
// update the aspect ratio if necessary.
int tmpW = priW;
@@ -609,14 +611,39 @@
// keeping aspect ratio intact.
hwc_rect r = {0, 0, 0, 0};
qdutils::getAspectRatioPosition(tmpW, tmpH, width, height, r);
- mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].xres =
- r.right - r.left;
- mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].yres =
- r.bottom - r.top;
+ int newExtW = r.right - r.left;
+ int newExtH = r.bottom - r.top;
+ int alignedExtW;
+ int alignedExtH;
+ // On 8994 and below targets MDP supports only 4X downscaling,
+ // Restricting selected external resolution to be exactly 4X
+ // greater resolution than actual external resolution
+ int maxMDPDownScale =
+ qdutils::MDPVersion::getInstance().getMaxMDPDownscale();
+ if((width * height * maxMDPDownScale) < (newExtW * newExtH)) {
+ float upScaleFactor = (float)maxMDPDownScale / 2.0f;
+ newExtW = (int)((float)width * upScaleFactor);
+ newExtH = (int)((float)height * upScaleFactor);
+ }
+ // Align it down so that the new aligned resolution does not
+ // exceed the maxMDPDownscale factor
+ alignedExtW = overlay::utils::aligndown(newExtW, 4);
+ alignedExtH = overlay::utils::aligndown(newExtH, 4);
+ mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].xres = alignedExtW;
+ mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].yres = alignedExtH;
// Set External Display MDP Downscale mode indicator
mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].mDownScaleMode =true;
}
}
+ ALOGD_IF(DEBUG_MDPDOWNSCALE, "Selected external resolution [%d X %d] "
+ "maxMDPDownScale %d MDPDownScaleMode %d srcSplitEnabled %d "
+ "MDPDownscale feature %d",
+ mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].xres,
+ mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].yres,
+ qdutils::MDPVersion::getInstance().getMaxMDPDownscale(),
+ mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].mDownScaleMode,
+ qdutils::MDPVersion::getInstance().isSrcSplit(),
+ mHwcContext->mMDPDownscaleEnabled);
//Initialize the display viewFrame info
mHwcContext->mViewFrame[HWC_DISPLAY_EXTERNAL].left = 0;
mHwcContext->mViewFrame[HWC_DISPLAY_EXTERNAL].top = 0;
diff --git a/libgralloc/ionalloc.cpp b/libgralloc/ionalloc.cpp
index ccf6ed5..73bbe23 100644
--- a/libgralloc/ionalloc.cpp
+++ b/libgralloc/ionalloc.cpp
@@ -34,12 +34,14 @@
#include <fcntl.h>
#include <cutils/log.h>
#include <errno.h>
+#include <utils/Trace.h>
#include "gralloc_priv.h"
#include "ionalloc.h"
using gralloc::IonAlloc;
#define ION_DEVICE "/dev/ion"
+#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
int IonAlloc::open_device()
{
@@ -64,6 +66,7 @@
int IonAlloc::alloc_buffer(alloc_data& data)
{
+ ATRACE_CALL();
Locker::Autolock _l(mLock);
int err = 0;
struct ion_handle_data handle_data;
@@ -123,6 +126,7 @@
int IonAlloc::free_buffer(void* base, unsigned int size, unsigned int offset,
int fd)
{
+ ATRACE_CALL();
Locker::Autolock _l(mLock);
ALOGD_IF(DEBUG, "ion: Freeing buffer base:%p size:%u fd:%d",
base, size, fd);
@@ -140,6 +144,7 @@
int IonAlloc::map_buffer(void **pBase, unsigned int size, unsigned int offset,
int fd)
{
+ ATRACE_CALL();
int err = 0;
void *base = 0;
// It is a (quirky) requirement of ION to have opened the
@@ -165,6 +170,7 @@
int IonAlloc::unmap_buffer(void *base, unsigned int size,
unsigned int /*offset*/)
{
+ ATRACE_CALL();
ALOGD_IF(DEBUG, "ion: Unmapping buffer base:%p size:%u", base, size);
int err = 0;
if(munmap(base, size)) {
@@ -178,6 +184,8 @@
int IonAlloc::clean_buffer(void *base, unsigned int size, unsigned int offset,
int fd, int op)
{
+ ATRACE_CALL();
+ ATRACE_INT("operation id", op);
struct ion_flush_data flush_data;
struct ion_fd_data fd_data;
struct ion_handle_data handle_data;
diff --git a/libgralloc/mapper.cpp b/libgralloc/mapper.cpp
index 2f2ddc1..13e662a 100644
--- a/libgralloc/mapper.cpp
+++ b/libgralloc/mapper.cpp
@@ -29,6 +29,7 @@
#include <cutils/log.h>
#include <cutils/atomic.h>
+#include <utils/Trace.h>
#include <hardware/hardware.h>
#include <hardware/gralloc.h>
@@ -39,6 +40,8 @@
#include "memalloc.h"
#include <qdMetaData.h>
+#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
+
using namespace gralloc;
/*****************************************************************************/
@@ -55,6 +58,7 @@
static int gralloc_map(gralloc_module_t const* module,
buffer_handle_t handle)
{
+ ATRACE_CALL();
if(!module)
return -EINVAL;
@@ -92,6 +96,7 @@
static int gralloc_unmap(gralloc_module_t const* module,
buffer_handle_t handle)
{
+ ATRACE_CALL();
if(!module)
return -EINVAL;
@@ -130,6 +135,7 @@
int gralloc_register_buffer(gralloc_module_t const* module,
buffer_handle_t handle)
{
+ ATRACE_CALL();
if (!module || private_handle_t::validate(handle) < 0)
return -EINVAL;
@@ -157,6 +163,7 @@
int gralloc_unregister_buffer(gralloc_module_t const* module,
buffer_handle_t handle)
{
+ ATRACE_CALL();
if (!module || private_handle_t::validate(handle) < 0)
return -EINVAL;
@@ -179,6 +186,7 @@
int terminateBuffer(gralloc_module_t const* module,
private_handle_t* hnd)
{
+ ATRACE_CALL();
if(!module)
return -EINVAL;
@@ -207,6 +215,7 @@
static int gralloc_map_and_invalidate (gralloc_module_t const* module,
buffer_handle_t handle, int usage)
{
+ ATRACE_CALL();
if (!module || private_handle_t::validate(handle) < 0)
return -EINVAL;
@@ -243,6 +252,7 @@
int /*l*/, int /*t*/, int /*w*/, int /*h*/,
void** vaddr)
{
+ ATRACE_CALL();
private_handle_t* hnd = (private_handle_t*)handle;
int err = gralloc_map_and_invalidate(module, handle, usage);
if(!err)
@@ -255,6 +265,7 @@
int /*l*/, int /*t*/, int /*w*/, int /*h*/,
struct android_ycbcr *ycbcr)
{
+ ATRACE_CALL();
private_handle_t* hnd = (private_handle_t*)handle;
int err = gralloc_map_and_invalidate(module, handle, usage);
if(!err)
@@ -265,6 +276,7 @@
int gralloc_unlock(gralloc_module_t const* module,
buffer_handle_t handle)
{
+ ATRACE_CALL();
if (!module || private_handle_t::validate(handle) < 0)
return -EINVAL;
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index 24fd771..8164fd3 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -597,6 +597,21 @@
for(int j = 0; j < ptorInfo->count; j++) {
int ovlapIndex = ptorInfo->layerIndex[j];
hwc_rect_t overlap = list->hwLayers[ovlapIndex].displayFrame;
+ if(j) {
+ /**
+ * It's possible that 2 PTOR layers might have overlapping.
+ * In such case, remove the intersection(again if peripheral)
+ * from the lower PTOR layer to avoid overlapping.
+ * If intersection is not on peripheral then compromise
+ * by reducing number of PTOR layers.
+ **/
+ int prevOvlapIndex = ptorInfo->layerIndex[0];
+ hwc_rect_t prevOvlap = list->hwLayers[prevOvlapIndex].displayFrame;
+ hwc_rect_t commonRect = getIntersection(prevOvlap, overlap);
+ if(isValidRect(commonRect)) {
+ overlap = deductRect(overlap, commonRect);
+ }
+ }
// Draw overlapped content of layers on render buffer
for (int i = 0; i <= ovlapIndex; i++) {
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 5df0fa0..b222d32 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -333,7 +333,7 @@
// Color layer
return true;
}
- ALOGE("%s: layer handle is NULL", __FUNCTION__);
+ ALOGD_IF(isDebug(), "%s: layer handle is NULL", __FUNCTION__);
return false;
}
@@ -425,14 +425,21 @@
ALOGD_IF(isDebug(),"%s: MDP Comp. video transition padding round",
__FUNCTION__);
ret = false;
- } else if(isSecondaryConfiguring(ctx)) {
- ALOGD_IF( isDebug(),"%s: External Display connection is pending",
- __FUNCTION__);
- ret = false;
- } else if(ctx->isPaddingRound) {
- ALOGD_IF(isDebug(), "%s: padding round invoked for dpy %d",
- __FUNCTION__,mDpy);
- ret = false;
+ } else if(qdutils::MDPVersion::getInstance().getTotalPipes() < 8) {
+ /* TODO: freeing up all the resources only for the targets having total
+ number of pipes < 8. Need to analyze number of VIG pipes used
+ for primary in previous draw cycle and accordingly decide
+ whether to fall back to full GPU comp or video only comp
+ */
+ if(isSecondaryConfiguring(ctx)) {
+ ALOGD_IF( isDebug(),"%s: External Display connection is pending",
+ __FUNCTION__);
+ ret = false;
+ } else if(ctx->isPaddingRound) {
+ ALOGD_IF(isDebug(), "%s: padding round invoked for dpy %d",
+ __FUNCTION__,mDpy);
+ ret = false;
+ }
}
return ret;
}
@@ -691,6 +698,18 @@
return false;
}
+ // if secondary is configuring or Padding round, fall back to video only
+ // composition and release all assigned non VIG pipes from primary.
+ if(isSecondaryConfiguring(ctx)) {
+ ALOGD_IF( isDebug(),"%s: External Display connection is pending",
+ __FUNCTION__);
+ return false;
+ } else if(ctx->isPaddingRound) {
+ ALOGD_IF(isDebug(), "%s: padding round invoked for dpy %d",
+ __FUNCTION__,mDpy);
+ return false;
+ }
+
MDPVersion& mdpHw = MDPVersion::getInstance();
if(mDpy > HWC_DISPLAY_PRIMARY &&
(priDispW > mdpHw.getMaxMixerWidth()) &&
@@ -876,28 +895,10 @@
}
}
- if(isValidRect(getIntersection(overlapRect[0], overlapRect[1]))) {
- ALOGD_IF(isDebug(), "%s: Ignore Rect2 its intersects with Rect1",
- __FUNCTION__);
- // reset second minLayerIndex[1];
- minLayerIndex[1] = -1;
- numPTORLayersFound--;
- }
-
// No overlap layers
if (!numPTORLayersFound)
return false;
- ctx->mPtorInfo.count = numPTORLayersFound;
- for(int i = 0; i < MAX_PTOR_LAYERS; i++) {
- ctx->mPtorInfo.layerIndex[i] = minLayerIndex[i];
- }
-
- if (!ctx->mCopyBit[mDpy]->prepareOverlap(ctx, list)) {
- // reset PTOR
- ctx->mPtorInfo.count = 0;
- return false;
- }
// Store the displayFrame and the sourceCrops of the layers
hwc_rect_t displayFrame[numAppLayers];
hwc_rect_t sourceCrop[numAppLayers];
@@ -907,6 +908,35 @@
sourceCrop[i] = integerizeSourceCrop(layer->sourceCropf);
}
+ /**
+ * It's possible that 2 PTOR layers might have overlapping.
+ * In such case, remove the intersection(again if peripheral)
+ * from the lower PTOR layer to avoid overlapping.
+ * If intersection is not on peripheral then compromise
+ * by reducing number of PTOR layers.
+ **/
+ hwc_rect_t commonRect = getIntersection(overlapRect[0], overlapRect[1]);
+ if(isValidRect(commonRect)) {
+ overlapRect[1] = deductRect(overlapRect[1], commonRect);
+ list->hwLayers[minLayerIndex[1]].displayFrame = overlapRect[1];
+ }
+
+ ctx->mPtorInfo.count = numPTORLayersFound;
+ for(int i = 0; i < MAX_PTOR_LAYERS; i++) {
+ ctx->mPtorInfo.layerIndex[i] = minLayerIndex[i];
+ }
+
+ if (!ctx->mCopyBit[mDpy]->prepareOverlap(ctx, list)) {
+ // reset PTOR
+ ctx->mPtorInfo.count = 0;
+ if(isValidRect(commonRect)) {
+ // If PTORs are intersecting restore displayframe of PTOR[1]
+ // before returning, as we have modified it above.
+ list->hwLayers[minLayerIndex[1]].displayFrame =
+ displayFrame[minLayerIndex[1]];
+ }
+ return false;
+ }
private_handle_t *renderBuf = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
Whf layerWhf[numPTORLayersFound]; // To store w,h,f of PTOR layers
@@ -1771,13 +1801,15 @@
}
const int numLayers = ctx->listStats[mDpy].numAppLayers;
-
- if(property_get("debug.hwc.simulate", property, NULL) > 0) {
- int currentFlags = atoi(property);
- if(currentFlags != sSimulationFlags) {
- sSimulationFlags = currentFlags;
- ALOGE("%s: Simulation Flag read: 0x%x (%d)", __FUNCTION__,
- sSimulationFlags, sSimulationFlags);
+ if(mDpy == HWC_DISPLAY_PRIMARY) {
+ sSimulationFlags = 0;
+ if(property_get("debug.hwc.simulate", property, NULL) > 0) {
+ int currentFlags = atoi(property);
+ if(currentFlags != sSimulationFlags) {
+ sSimulationFlags = currentFlags;
+ ALOGI("%s: Simulation Flag read: 0x%x (%d)", __FUNCTION__,
+ sSimulationFlags, sSimulationFlags);
+ }
}
}
// reset PTOR
@@ -1829,6 +1861,8 @@
memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
mCurrentFrame.dropCount = 0;
ret = -1;
+ ALOGE_IF(sSimulationFlags && (mDpy == HWC_DISPLAY_PRIMARY),
+ "MDP Composition Strategies Failed");
}
} else {
ALOGD_IF( isDebug(),"%s: MDP Comp not possible for this frame",
@@ -2477,6 +2511,9 @@
else if (hnd->format == HAL_PIXEL_FORMAT_RGBX_8888)
whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
}
+ /* Calculate the external display position based on MDP downscale,
+ ActionSafe, and extorientation features. */
+ calcExtDisplayPosition(ctx, hnd, mDpy, crop, dst, transform, orient);
int downscale = getRotDownscale(ctx, layer);
eMdpFlags mdpFlags = OV_MDP_BACKEND_COMPOSITION;
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index dcd9cf3..b339cb7 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -620,6 +620,10 @@
displayFrame.top = int(hRatio*(float)displayFrame.top);
displayFrame.right = int(wRatio*(float)displayFrame.right);
displayFrame.bottom = int(hRatio*(float)displayFrame.bottom);
+ ALOGD_IF(DEBUG_MDPDOWNSCALE, "Calculated external display frame"
+ " for MDPDownscale feature [%d %d %d %d]",
+ displayFrame.left, displayFrame.top,
+ displayFrame.right, displayFrame.bottom);
}
}else {
if(extOrient || ctx->dpyAttr[dpy].mDownScaleMode) {
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 51742be..4858b3a 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -21,7 +21,9 @@
#ifndef HWC_UTILS_H
#define HWC_UTILS_H
+#define DEBUG_MDPDOWNSCALE 0
#define HWC_REMOVE_DEPRECATED_VERSIONS 1
+
#include <fcntl.h>
#include <math.h>
#include <hardware/hwcomposer.h>
diff --git a/libqdutils/mdp_version.cpp b/libqdutils/mdp_version.cpp
index 0b53a47..575a97c 100644
--- a/libqdutils/mdp_version.cpp
+++ b/libqdutils/mdp_version.cpp
@@ -183,6 +183,7 @@
size_t len = PAGE_SIZE;
ssize_t read;
char *readLine = (char *) malloc (len);
+ char property[PROPERTY_VALUE_MAX];
while((read = getline((char **)&readLine, &len,
panelInfoNodeFP)) != -1) {
int token_ct=0;
@@ -227,6 +228,12 @@
}
}
}
+ if((property_get("persist.hwc.pubypass", property, 0) > 0) &&
+ (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
+ (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+ mPanelInfo.mPartialUpdateEnable = 0;
+ ALOGI("PartialUpdate disabled by property");
+ }
fclose(panelInfoNodeFP);
} else {
ALOGE("Failed to open msm_fb_panel_info node");