Merge "hwc: always enable BWC for primary"
diff --git a/common.mk b/common.mk
index 4aa56b2..cfe84be 100644
--- a/common.mk
+++ b/common.mk
@@ -31,12 +31,12 @@
endif
ifeq ($(call is-board-platform-in-list, msm8974 msm8226 msm8610 apq8084 \
- mpq8092), true)
+ mpq8092 msm_bronze), true)
common_flags += -DVENUS_COLOR_FORMAT
common_flags += -DMDSS_TARGET
endif
-ifeq ($(call is-board-platform-in-list, mpq8092), true)
+ifeq ($(call is-board-platform-in-list, mpq8092 msm_bronze), true)
#XXX: Replace with check from MDP when available
common_flags += -DVPU_TARGET
endif
diff --git a/libexternal/external.cpp b/libexternal/external.cpp
index 609f9c1..045edd8 100644
--- a/libexternal/external.cpp
+++ b/libexternal/external.cpp
@@ -588,7 +588,9 @@
// if primary resolution is more than the hdmi resolution
// configure dpy attr to primary resolution and set
// downscale mode
- if((priW * priH) > (width * height)) {
+ // Restrict this upto 1080p resolution max
+ if(((priW * priH) > (width * height)) &&
+ (priW <= qdutils::MAX_DISPLAY_DIM )) {
mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].xres = priW;
mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].yres = priH;
// HDMI is always in landscape, so always assign the higher
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index 9af45e2..98047e4 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -184,12 +184,6 @@
IonController::IonController()
{
mIonAlloc = new IonAlloc();
- mUseTZProtection = false;
- char property[PROPERTY_VALUE_MAX];
- if ((property_get("persist.gralloc.cp.level3", property, NULL) <= 0) ||
- (atoi(property) != 1)) {
- mUseTZProtection = true;
- }
}
int IonController::allocate(alloc_data& data, int usage)
@@ -210,7 +204,7 @@
ionFlags |= ION_HEAP(ION_IOMMU_HEAP_ID);
if(usage & GRALLOC_USAGE_PROTECTED) {
- if ((mUseTZProtection) && (usage & GRALLOC_USAGE_PRIVATE_MM_HEAP)) {
+ if (usage & GRALLOC_USAGE_PRIVATE_MM_HEAP) {
ionFlags |= ION_HEAP(ION_CP_MM_HEAP_ID);
ionFlags |= ION_SECURE;
} else {
diff --git a/libgralloc/alloc_controller.h b/libgralloc/alloc_controller.h
index 8954d39..5fe81fa 100644
--- a/libgralloc/alloc_controller.h
+++ b/libgralloc/alloc_controller.h
@@ -65,7 +65,6 @@
private:
IonAlloc* mIonAlloc;
- bool mUseTZProtection;
};
} //end namespace gralloc
diff --git a/libhwcomposer/Android.mk b/libhwcomposer/Android.mk
index 12b822a..4ef4286 100644
--- a/libhwcomposer/Android.mk
+++ b/libhwcomposer/Android.mk
@@ -25,7 +25,7 @@
hwc_dump_layers.cpp \
hwc_ad.cpp
-ifeq ($(call is-board-platform-in-list, mpq8092), true)
+ifeq ($(call is-board-platform-in-list, mpq8092 msm_bronze), true)
LOCAL_SRC_FILES += hwc_vpuclient.cpp
endif
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index 5038025..fb23470 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -54,6 +54,8 @@
open: hwc_device_open
};
+static void reset_panel(struct hwc_composer_device_1* dev);
+
hwc_module_t HAL_MODULE_INFO_SYM = {
common: {
tag: HARDWARE_MODULE_TAG,
@@ -138,7 +140,9 @@
static void handleGeomChange(hwc_context_t *ctx, int dpy,
hwc_display_contents_1_t *list) {
- if(list->flags & HWC_GEOMETRY_CHANGED) {
+ /* No point to calling overlay_set on MDP3 */
+ if(list->flags & HWC_GEOMETRY_CHANGED &&
+ ctx->mMDP.version >= qdutils::MDP_V4_0) {
ctx->mOverlay->forceSet(dpy);
}
}
@@ -263,6 +267,12 @@
{
int ret = 0;
hwc_context_t* ctx = (hwc_context_t*)(dev);
+
+ if (ctx->mPanelResetStatus) {
+ ALOGW("%s: panel is in bad state. reset the panel", __FUNCTION__);
+ reset_panel(dev);
+ }
+
//Will be unlocked at the end of set
ctx->mDrawLock.lock();
reset(ctx, numDisplays, displays);
@@ -271,8 +281,6 @@
ctx->mRotMgr->configBegin();
overlay::Writeback::configBegin();
- Overlay::setDMAMode(Overlay::DMA_LINE_MODE);
-
for (int32_t i = numDisplays; i >= 0; i--) {
hwc_display_contents_1_t *list = displays[i];
int dpy = getDpyforExternalDisplay(ctx, i);
@@ -430,6 +438,33 @@
return ret;
}
+static void reset_panel(struct hwc_composer_device_1* dev)
+{
+ int ret = 0;
+ hwc_context_t* ctx = (hwc_context_t*)(dev);
+
+ if (!ctx->mPanelResetStatus)
+ return;
+
+ ALOGD("%s: calling BLANK DISPLAY", __FUNCTION__);
+ ret = hwc_blank(dev, HWC_DISPLAY_PRIMARY, 1);
+ if (ret < 0) {
+ ALOGE("%s: FBIOBLANK failed to BLANK: %s", __FUNCTION__,
+ strerror(errno));
+ }
+
+ ALOGD("%s: calling UNBLANK DISPLAY and enabling vsync", __FUNCTION__);
+ ret = hwc_blank(dev, HWC_DISPLAY_PRIMARY, 0);
+ if (ret < 0) {
+ ALOGE("%s: FBIOBLANK failed to UNBLANK : %s", __FUNCTION__,
+ strerror(errno));
+ }
+ hwc_vsync_control(ctx, HWC_DISPLAY_PRIMARY, 1);
+
+ ctx->mPanelResetStatus = false;
+}
+
+
static int hwc_query(struct hwc_composer_device_1* dev,
int param, int* value)
{
@@ -664,6 +699,8 @@
CALC_FPS();
MDPComp::resetIdleFallBack();
ctx->mVideoTransFlag = false;
+ if(ctx->mRotMgr->getNumActiveSessions() == 0)
+ Overlay::setDMAMode(Overlay::DMA_LINE_MODE);
//Was locked at the beginning of prepare
ctx->mDrawLock.unlock();
return ret;
@@ -770,6 +807,11 @@
ovDump[0] = '\0';
ctx->mRotMgr->getDump(ovDump, 1024);
dumpsys_log(aBuf, ovDump);
+ ovDump[0] = '\0';
+ if(Writeback::getDump(ovDump, 1024)) {
+ dumpsys_log(aBuf, ovDump);
+ ovDump[0] = '\0';
+ }
strlcpy(buff, aBuf.string(), buff_len);
}
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index ba40db5..d54a5f2 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -182,16 +182,10 @@
// Following are MDP3 limitations for which we
// need to fallback to GPU composition:
- // 1. HW issues with mdp3 and rotation.
- // 2. Plane alpha is not supported by MDP3.
+ // 1. Plane alpha is not supported by MDP3.
if (qdutils::MDPVersion::getInstance().getMDPVersion() < 400) {
for (int i = ctx->listStats[dpy].numAppLayers-1; i >= 0 ; i--) {
hwc_layer_1_t *layer = (hwc_layer_1_t *) &list->hwLayers[i];
- if ((layer->transform & (HAL_TRANSFORM_FLIP_H |
- HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90)) &&
- ((layer->displayFrame.bottom - layer->displayFrame.top) % 16 ||
- (layer->displayFrame.right - layer->displayFrame.left) % 16))
- return true;
if (layer->planeAlpha != 0xFF)
return true;
}
@@ -246,8 +240,8 @@
rect.bottom};
copybit_image_t buf;
- buf.w = ALIGN(hnd->width,32);
- buf.h = hnd->height;
+ buf.w = ALIGN(getWidth(hnd),32);
+ buf.h = getHeight(hnd);
buf.format = hnd->format;
buf.base = (void *)hnd->base;
buf.handle = (native_handle_t *)hnd;
@@ -274,19 +268,24 @@
return false;
}
- //Wait for the previous frame to complete before rendering onto it
- if(mRelFd[0] >=0) {
- sync_wait(mRelFd[0], 1000);
- close(mRelFd[0]);
- mRelFd[0] = -1;
- }
-
if (ctx->mMDP.version >= qdutils::MDP_V4_0) {
+ //Wait for the previous frame to complete before rendering onto it
+ if(mRelFd[0] >=0) {
+ sync_wait(mRelFd[0], 1000);
+ close(mRelFd[0]);
+ mRelFd[0] = -1;
+ }
+
//Clear the visible region on the render buffer
//XXX: Do this only when needed.
hwc_rect_t clearRegion;
getNonWormholeRegion(list, clearRegion);
clear(renderBuffer, clearRegion);
+ } else {
+ if(mRelFd[0] >=0) {
+ copybit_device_t *copybit = getCopyBitDevice();
+ copybit->set_sync(copybit, mRelFd[0]);
+ }
}
// numAppLayers-1, as we iterate from 0th layer index with HWC_COPYBIT flag
for (int i = 0; i <= (ctx->listStats[dpy].numAppLayers-1); i++) {
@@ -319,6 +318,10 @@
copybit_device_t *copybit = getCopyBitDevice();
// Async mode
copybit->flush_get_fence(copybit, fd);
+ if(mRelFd[0] >=0 && ctx->mMDP.version == qdutils::MDP_V3_0_4) {
+ close(mRelFd[0]);
+ mRelFd[0] = -1;
+ }
}
return true;
}
@@ -347,8 +350,8 @@
// Set the copybit source:
copybit_image_t src;
- src.w = hnd->width;
- src.h = hnd->height;
+ src.w = getWidth(hnd);
+ src.h = getHeight(hnd);
src.format = hnd->format;
// Handle R/B swap
@@ -362,7 +365,7 @@
src.base = (void *)hnd->base;
src.handle = (native_handle_t *)layer->handle;
- src.horiz_padding = src.w - hnd->width;
+ src.horiz_padding = src.w - getWidth(hnd);
// Initialize vertical padding to zero for now,
// this needs to change to accomodate vertical stride
// if needed in the future
diff --git a/libhwcomposer/hwc_dump_layers.cpp b/libhwcomposer/hwc_dump_layers.cpp
index b9c09b6..1b3d097 100644
--- a/libhwcomposer/hwc_dump_layers.cpp
+++ b/libhwcomposer/hwc_dump_layers.cpp
@@ -236,7 +236,7 @@
// Log Line 1
ALOGI("Display[%s] Layer[%d] SrcBuff[%dx%d] SrcCrop[%dl, %dt, %dr, %db] "
"DispFrame[%dl, %dt, %dr, %db] VisRegsScr%s", mDisplayName, layerIndex,
- (hnd)? hnd->width : -1, (hnd)? hnd->height : -1,
+ (hnd)? getWidth(hnd) : -1, (hnd)? getHeight(hnd) : -1,
sourceCrop.left, sourceCrop.top,
sourceCrop.right, sourceCrop.bottom,
displayFrame.left, displayFrame.top,
@@ -328,7 +328,7 @@
break;
}
if (SkBitmap::kNo_Config != tempSkBmpConfig) {
- tempSkBmp->setConfig(tempSkBmpConfig, hnd->width, hnd->height);
+ tempSkBmp->setConfig(tempSkBmpConfig, getWidth(hnd), getHeight(hnd));
tempSkBmp->setPixels((void*)hnd->base);
bResult = SkImageEncoder::EncodeFile(dumpFilename,
*tempSkBmp, SkImageEncoder::kPNG_Type, 100);
@@ -348,7 +348,7 @@
bool bResult = false;
sprintf(dumpFilename, "%s/sfdump%03d.layer%d.%dx%d.%s.%s.raw",
mDumpDirRaw, mDumpCntrRaw,
- layerIndex, hnd->width, hnd->height,
+ layerIndex, getWidth(hnd), getHeight(hnd),
pixFormatStr, mDisplayName);
FILE* fp = fopen(dumpFilename, "w+");
if (NULL != fp) {
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index 53b3d18..391b150 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -58,6 +58,7 @@
}
bool FBUpdateNonSplit::preRotateExtDisplay(hwc_context_t *ctx,
+ hwc_layer_1_t *layer,
ovutils::Whf &info,
hwc_rect_t& sourceCrop,
ovutils::eMdpFlags& mdpFlags,
@@ -74,6 +75,7 @@
mRot = NULL;
return false;
}
+ ctx->mLayerRotMap[mDpy]->add(layer, mRot);
info.format = (mRot)->getDstFormat();
updateSource(orient, info, sourceCrop);
rotFlags |= ovutils::ROT_PREROTATED;
@@ -106,7 +108,7 @@
}
overlay::Overlay& ov = *(ctx->mOverlay);
private_handle_t *hnd = (private_handle_t *)layer->handle;
- ovutils::Whf info(hnd->width, hnd->height,
+ ovutils::Whf info(getWidth(hnd), getHeight(hnd),
ovutils::getMdpFormat(hnd->format), hnd->size);
//Request a pipe
@@ -162,7 +164,8 @@
transform, orient);
setMdpFlags(layer, mdpFlags, 0, transform);
// For External use rotator if there is a rotation value set
- ret = preRotateExtDisplay(ctx, info, sourceCrop, mdpFlags, rotFlags);
+ ret = preRotateExtDisplay(ctx, layer, info,
+ sourceCrop, mdpFlags, rotFlags);
if(!ret) {
ALOGE("%s: preRotate for external Failed!", __FUNCTION__);
return false;
@@ -244,7 +247,7 @@
}
overlay::Overlay& ov = *(ctx->mOverlay);
private_handle_t *hnd = (private_handle_t *)layer->handle;
- ovutils::Whf info(hnd->width, hnd->height,
+ ovutils::Whf info(getWidth(hnd), getHeight(hnd),
ovutils::getMdpFormat(hnd->format), hnd->size);
//Request left pipe
diff --git a/libhwcomposer/hwc_fbupdate.h b/libhwcomposer/hwc_fbupdate.h
index 0e3f29e..ce6af63 100644
--- a/libhwcomposer/hwc_fbupdate.h
+++ b/libhwcomposer/hwc_fbupdate.h
@@ -66,6 +66,7 @@
bool configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
int fbZorder);
bool preRotateExtDisplay(hwc_context_t *ctx,
+ hwc_layer_1_t *layer,
ovutils::Whf &info,
hwc_rect_t& sourceCrop,
ovutils::eMdpFlags& mdpFlags,
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index ff33e94..bb52728 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -242,10 +242,9 @@
void MDPComp::LayerCache::reset() {
memset(&hnd, 0, sizeof(hnd));
- mdpCount = 0;
- fbCount = 0;
+ memset(&isFBComposed, true, sizeof(isFBComposed));
+ memset(&drop, false, sizeof(drop));
layerCount = 0;
- fbZ = -1;
}
void MDPComp::LayerCache::cacheAll(hwc_display_contents_1_t* list) {
@@ -256,10 +255,21 @@
}
void MDPComp::LayerCache::updateCounts(const FrameInfo& curFrame) {
- mdpCount = curFrame.mdpCount;
- fbCount = curFrame.fbCount;
layerCount = curFrame.layerCount;
- fbZ = curFrame.fbZ;
+ memcpy(&isFBComposed, &curFrame.isFBComposed, sizeof(isFBComposed));
+ memcpy(&drop, &curFrame.drop, sizeof(drop));
+}
+
+bool MDPComp::LayerCache::isSameFrame(const FrameInfo& curFrame) {
+ if(layerCount != curFrame.layerCount)
+ return false;
+ for(int i = 0; i < curFrame.layerCount; i++) {
+ if((curFrame.isFBComposed[i] != isFBComposed[i]) ||
+ (curFrame.drop[i] != drop[i])) {
+ return false;
+ }
+ }
+ return true;
}
bool MDPComp::isSupportedForMDPComp(hwc_context_t *ctx, hwc_layer_1_t* layer) {
@@ -576,14 +586,26 @@
bool MDPComp::partialMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list)
{
- int numAppLayers = ctx->listStats[mDpy].numAppLayers;
-
if(!sEnableMixedMode) {
//Mixed mode is disabled. No need to even try caching.
return false;
}
- //Setup mCurrentFrame
+ bool ret = false;
+ if(isLoadBasedCompDoable(ctx, list)) {
+ ret = loadBasedComp(ctx, list);
+ }
+
+ if(!ret) {
+ ret = cacheBasedComp(ctx, list);
+ }
+
+ return ret;
+}
+
+bool MDPComp::cacheBasedComp(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list) {
+ int numAppLayers = ctx->listStats[mDpy].numAppLayers;
mCurrentFrame.reset(numAppLayers);
updateLayerCache(ctx, list);
@@ -633,6 +655,77 @@
return true;
}
+bool MDPComp::loadBasedComp(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list) {
+ int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+ mCurrentFrame.reset(numAppLayers);
+
+ //TODO BatchSize could be optimized further based on available pipes, split
+ //displays etc.
+ const int batchSize = numAppLayers - (sMaxPipesPerMixer - 1);
+ if(batchSize <= 0) {
+ ALOGD_IF(isDebug(), "%s: Not attempting", __FUNCTION__);
+ return false;
+ }
+
+ int minBatchStart = -1;
+ size_t minBatchPixelCount = SIZE_MAX;
+
+ for(int i = 0; i <= numAppLayers - batchSize; i++) {
+ uint32_t batchPixelCount = 0;
+ for(int j = i; j < i + batchSize; j++) {
+ hwc_layer_1_t* layer = &list->hwLayers[j];
+ hwc_rect_t crop = layer->sourceCrop;
+ batchPixelCount += (crop.right - crop.left) *
+ (crop.bottom - crop.top);
+ }
+
+ if(batchPixelCount < minBatchPixelCount) {
+ minBatchPixelCount = batchPixelCount;
+ minBatchStart = i;
+ }
+ }
+
+ if(minBatchStart < 0) {
+ ALOGD_IF(isDebug(), "%s: No batch found batchSize %d numAppLayers %d",
+ __FUNCTION__, batchSize, numAppLayers);
+ return false;
+ }
+
+ for(int i = 0; i < numAppLayers; i++) {
+ if(i < minBatchStart || i >= minBatchStart + batchSize) {
+ hwc_layer_1_t* layer = &list->hwLayers[i];
+ if(not isSupportedForMDPComp(ctx, layer)) {
+ ALOGD_IF(isDebug(), "%s: MDP unsupported layer found at %d",
+ __FUNCTION__, i);
+ return false;
+ }
+ mCurrentFrame.isFBComposed[i] = false;
+ }
+ }
+
+ mCurrentFrame.fbZ = minBatchStart;
+ mCurrentFrame.fbCount = batchSize;
+ mCurrentFrame.mdpCount = mCurrentFrame.layerCount - batchSize;
+
+ if(!arePipesAvailable(ctx, list)) {
+ return false;
+ }
+
+ ALOGD_IF(isDebug(), "%s: fbZ %d batchSize %d",
+ __FUNCTION__, mCurrentFrame.fbZ, batchSize);
+ return true;
+}
+
+bool MDPComp::isLoadBasedCompDoable(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list) {
+ if(mDpy or isSecurePresent(ctx, mDpy) or
+ not (list->flags & HWC_GEOMETRY_CHANGED)) {
+ return false;
+ }
+ return true;
+}
+
bool MDPComp::isOnlyVideoDoable(hwc_context_t *ctx,
hwc_display_contents_1_t* list, bool secureOnly) {
int numAppLayers = ctx->listStats[mDpy].numAppLayers;
@@ -1084,13 +1177,9 @@
} else { //Success
//Any change in composition types needs an FB refresh
mCurrentFrame.needsRedraw = false;
- if(mCurrentFrame.fbCount &&
- ((mCurrentFrame.mdpCount != mCachedFrame.mdpCount) ||
- (mCurrentFrame.fbCount != mCachedFrame.fbCount) ||
- (mCurrentFrame.fbZ != mCachedFrame.fbZ) ||
- (!mCurrentFrame.mdpCount) ||
+ if(!mCachedFrame.isSameFrame(mCurrentFrame) ||
(list->flags & HWC_GEOMETRY_CHANGED) ||
- isSkipPresent(ctx, mDpy))) {
+ isSkipPresent(ctx, mDpy)) {
mCurrentFrame.needsRedraw = true;
}
}
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index e1839cd..1d5d715 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -108,10 +108,9 @@
/* cached data */
struct LayerCache {
int layerCount;
- int mdpCount;
- int fbCount;
- int fbZ;
buffer_handle_t hnd[MAX_NUM_APP_LAYERS];
+ bool isFBComposed[MAX_NUM_APP_LAYERS];
+ bool drop[MAX_NUM_APP_LAYERS];
/* c'tor */
LayerCache();
@@ -119,6 +118,7 @@
void reset();
void cacheAll(hwc_display_contents_1_t* list);
void updateCounts(const FrameInfo&);
+ bool isSameFrame(const FrameInfo& curFrame);
};
/* allocates pipe from pipe book */
@@ -144,6 +144,13 @@
bool fullMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list);
/* check if we can use layer cache to do at least partial MDP comp */
bool partialMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+ /* Partial MDP comp that uses caching to save power as primary goal */
+ bool cacheBasedComp(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+ /* Partial MDP comp that uses number of pixels to optimize perf goal */
+ bool loadBasedComp(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+ /* Checks if its worth doing load based partial comp */
+ bool isLoadBasedCompDoable(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list);
/* checks for conditions where only video can be bypassed */
bool isOnlyVideoDoable(hwc_context_t *ctx, hwc_display_contents_1_t* list,
bool secureOnly);
diff --git a/libhwcomposer/hwc_uevents.cpp b/libhwcomposer/hwc_uevents.cpp
index 8c3d00d..926f425 100644
--- a/libhwcomposer/hwc_uevents.cpp
+++ b/libhwcomposer/hwc_uevents.cpp
@@ -85,6 +85,24 @@
return -1;
}
+static bool getPanelResetStatus(hwc_context_t* ctx, const char* strUdata, int len)
+{
+ const char* iter_str = strUdata;
+ if (strcasestr("change@/devices/virtual/graphics/fb0", strUdata)) {
+ while(((iter_str - strUdata) <= len) && (*iter_str)) {
+ char* pstr = strstr(iter_str, "PANEL_ALIVE=0");
+ if (pstr != NULL) {
+ ALOGE("%s: got change event in fb0 with PANEL_ALIVE=0",
+ __FUNCTION__);
+ ctx->mPanelResetStatus = true;
+ return true;
+ }
+ iter_str += strlen(iter_str)+1;
+ }
+ }
+ return false;
+}
+
/* Parse uevent data for action requested for the display */
static int getConnectedState(const char* strUdata, int len)
{
@@ -101,6 +119,11 @@
static void handle_uevent(hwc_context_t* ctx, const char* udata, int len)
{
+ bool bpanelReset = getPanelResetStatus(ctx, udata, len);
+ if (bpanelReset) {
+ return;
+ }
+
int dpy = getConnectedDisplay(udata);
if(dpy < 0) {
ALOGD_IF(UEVENT_DEBUG, "%s: Not disp Event ", __FUNCTION__);
@@ -141,6 +164,7 @@
"event", __FUNCTION__);
ctx->proc->hotplug(ctx->proc, HWC_DISPLAY_EXTERNAL,
EXTERNAL_OFFLINE);
+ ctx->mVirtualonExtActive = false;
}
break;
}
@@ -309,7 +333,10 @@
char thread_name[64] = HWC_UEVENT_THREAD_NAME;
prctl(PR_SET_NAME, (unsigned long) &thread_name, 0, 0, 0);
setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
- uevent_init();
+ if(!uevent_init()) {
+ ALOGE("%s: failed to init uevent ",__FUNCTION__);
+ return NULL;
+ }
while(1) {
len = uevent_next_event(udata, sizeof(udata) - 2);
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 1ca9d6c..61f3f1c 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -312,6 +312,12 @@
float fbWidth = ctx->dpyAttr[dpy].xres;
float fbHeight = ctx->dpyAttr[dpy].yres;
+ if(ctx->dpyAttr[dpy].mDownScaleMode) {
+ // if downscale Mode is enabled for external, need to query
+ // the actual width and height, as that is the physical w & h
+ ctx->mExtDisplay->getAttributes((int&)fbWidth, (int&)fbHeight);
+ }
+
// Since external is rotated 90, need to swap width/height
int extOrient = getExtOrientation(ctx);
@@ -704,6 +710,7 @@
ctx->listStats[dpy].skipCount = 0;
ctx->listStats[dpy].needsAlphaScale = false;
ctx->listStats[dpy].preMultipliedAlpha = false;
+ ctx->listStats[dpy].isSecurePresent = false;
ctx->listStats[dpy].yuvCount = 0;
char property[PROPERTY_VALUE_MAX];
ctx->listStats[dpy].extOnlyLayerIndex = -1;
@@ -733,6 +740,10 @@
//reset yuv indices
ctx->listStats[dpy].yuvIndices[i] = -1;
+ if (isSecureBuffer(hnd)) {
+ ctx->listStats[dpy].isSecurePresent = true;
+ }
+
if (isSkipLayer(&list->hwLayers[i])) {
ctx->listStats[dpy].skipCount++;
}
@@ -1389,7 +1400,7 @@
eTransform orient = static_cast<eTransform>(transform);
int downscale = 0;
int rotFlags = ovutils::ROT_FLAGS_NONE;
- Whf whf(hnd->width, hnd->height,
+ Whf whf(getWidth(hnd), getHeight(hnd),
getMdpFormat(hnd->format), hnd->size);
// Handle R/B swap
@@ -1521,7 +1532,7 @@
const int downscale = 0;
int rotFlags = ROT_FLAGS_NONE;
- Whf whf(hnd->width, hnd->height,
+ Whf whf(getWidth(hnd), getHeight(hnd),
getMdpFormat(hnd->format), hnd->size);
// Handle R/B swap
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 3f1aace..1f1953b 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -103,6 +103,7 @@
bool isDisplayAnimating;
ovutils::Dim roi;
bool secureUI; // Secure display layer
+ bool isSecurePresent;
};
struct LayerProp {
@@ -316,6 +317,26 @@
return (hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY));
}
+static inline int getWidth(const private_handle_t* hnd) {
+ if(isYuvBuffer(hnd)) {
+ MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+ if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
+ return metadata->bufferDim.sliceWidth;
+ }
+ }
+ return hnd->width;
+}
+
+static inline int getHeight(const private_handle_t* hnd) {
+ if(isYuvBuffer(hnd)) {
+ MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+ if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
+ return metadata->bufferDim.sliceHeight;
+ }
+ }
+ return hnd->height;
+}
+
template<typename T> inline T max(T a, T b) { return (a > b) ? a : b; }
template<typename T> inline T min(T a, T b) { return (a < b) ? a : b; }
@@ -406,6 +427,9 @@
bool mBufferMirrorMode;
qhwc::LayerRotMap *mLayerRotMap[HWC_NUM_DISPLAY_TYPES];
+
+ // Panel reset flag will be set if BTA check fails
+ bool mPanelResetStatus;
};
namespace qhwc {
@@ -421,6 +445,10 @@
return (layer->transform & HWC_TRANSFORM_ROT_90);
}
+inline bool isSecurePresent(hwc_context_t *ctx, int dpy) {
+ return ctx->listStats[dpy].isSecurePresent;
+}
+
};
#endif //HWC_UTILS_H
diff --git a/liboverlay/overlayMdssRot.cpp b/liboverlay/overlayMdssRot.cpp
index 95f22c6..c6d5332 100644
--- a/liboverlay/overlayMdssRot.cpp
+++ b/liboverlay/overlayMdssRot.cpp
@@ -32,7 +32,6 @@
#define MDSS_MDP_ROT_ONLY 0x80
#endif
-#define SIZE_1M 0x00100000
#define MDSS_ROT_MASK (MDP_ROT_90 | MDP_FLIP_UD | MDP_FLIP_LR)
namespace ovutils = overlay::utils;
@@ -261,9 +260,6 @@
opBufSize = Rotator::calcOutputBufSize(destWhf);
}
- if (mRotInfo.flags & utils::OV_MDP_SECURE_OVERLAY_SESSION)
- opBufSize = utils::align(opBufSize, SIZE_1M);
-
return opBufSize;
}
diff --git a/liboverlay/overlayMem.h b/liboverlay/overlayMem.h
index 061d197..5e0db6f 100644
--- a/liboverlay/overlayMem.h
+++ b/liboverlay/overlayMem.h
@@ -38,6 +38,7 @@
#include "gralloc_priv.h"
#include "overlayUtils.h"
+#define SIZE_1M 0x00100000
namespace overlay {
@@ -118,24 +119,28 @@
{
alloc_data data;
int allocFlags = GRALLOC_USAGE_PRIVATE_IOMMU_HEAP;
- if(isSecure) {
- allocFlags = GRALLOC_USAGE_PRIVATE_MM_HEAP;
- allocFlags |= GRALLOC_USAGE_PROTECTED;
- }
- // Allocate uncached rotator buffers
- allocFlags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
-
int err = 0;
OVASSERT(numbufs && bufSz, "numbufs=%d bufSz=%d", numbufs, bufSz);
- mBufSz = bufSz;
+ if(isSecure) {
+ allocFlags = GRALLOC_USAGE_PRIVATE_MM_HEAP;
+ allocFlags |= GRALLOC_USAGE_PROTECTED;
+ mBufSz = utils::align(bufSz, SIZE_1M);
+ data.align = SIZE_1M;
+ } else {
+ mBufSz = bufSz;
+ data.align = getpagesize();
+ }
+
+ // Allocate uncached rotator buffers
+ allocFlags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
+
mNumBuffers = numbufs;
data.base = 0;
data.fd = -1;
data.offset = 0;
data.size = mBufSz * mNumBuffers;
- data.align = getpagesize();
data.uncached = true;
err = mAlloc->allocate(data, allocFlags);
diff --git a/liboverlay/overlayRotator.cpp b/liboverlay/overlayRotator.cpp
index 84a9818..7b3dda1 100644
--- a/liboverlay/overlayRotator.cpp
+++ b/liboverlay/overlayRotator.cpp
@@ -168,8 +168,8 @@
mRot[i]->getDump(buf, len);
}
}
- char str[32] = {'\0'};
- snprintf(str, 32, "\n================\n");
+ char str[4] = {'\0'};
+ snprintf(str, 4, "\n");
strncat(buf, str, strlen(str));
}
diff --git a/liboverlay/overlayRotator.h b/liboverlay/overlayRotator.h
index f551f1d..7c1095f 100644
--- a/liboverlay/overlayRotator.h
+++ b/liboverlay/overlayRotator.h
@@ -238,6 +238,7 @@
*/
void getDump(char *buf, size_t len);
int getRotDevFd();
+ int getNumActiveSessions() { return mUseCount; }
private:
overlay::Rotator *mRot[MAX_ROT_SESS];
int mUseCount;
diff --git a/liboverlay/overlayUtils.cpp b/liboverlay/overlayUtils.cpp
index fd8bfe2..1377182 100644
--- a/liboverlay/overlayUtils.cpp
+++ b/liboverlay/overlayUtils.cpp
@@ -427,9 +427,8 @@
const msmfb_data& ov) {
char str_data[256] = {'\0'};
snprintf(str_data, 256,
- "%s offset=%d memid=%d id=%d flags=0x%x priv=%d\n",
- prefix, ov.offset, ov.memory_id, ov.id, ov.flags,
- ov.priv);
+ "%s offset=%d memid=%d id=%d flags=0x%x\n",
+ prefix, ov.offset, ov.memory_id, ov.id, ov.flags);
strncat(buf, str_data, strlen(str_data));
}
diff --git a/liboverlay/overlayWriteback.cpp b/liboverlay/overlayWriteback.cpp
index f1f0eb5..50aa337 100644
--- a/liboverlay/overlayWriteback.cpp
+++ b/liboverlay/overlayWriteback.cpp
@@ -37,9 +37,6 @@
//=========== class WritebackMem ==============================================
bool WritebackMem::manageMem(uint32_t size, bool isSecure) {
- if(isSecure) {
- size = utils::align(size, SIZE_1M);
- }
if(mBuf.bufSz() == size) {
return true;
}
@@ -243,6 +240,17 @@
}
}
+bool Writeback::getDump(char *buf, size_t len) {
+ if(sWb) {
+ utils::getDump(buf, len, "WBData", sWb->mFbData);
+ char str[4] = {'\0'};
+ snprintf(str, 4, "\n");
+ strncat(buf, str, strlen(str));
+ return true;
+ }
+ return false;
+}
+
Writeback *Writeback::sWb = 0;
bool Writeback::sUsed = false;
diff --git a/liboverlay/overlayWriteback.h b/liboverlay/overlayWriteback.h
index 8c0c52a..9785b64 100644
--- a/liboverlay/overlayWriteback.h
+++ b/liboverlay/overlayWriteback.h
@@ -92,6 +92,9 @@
static void configBegin() { sUsed = false; }
static void configDone();
static void clear();
+ //Will take a dump of data structure only if there is an instance existing
+ //Returns true if dump is added to the input buffer, false otherwise
+ static bool getDump(char *buf, size_t len);
private:
explicit Writeback();
diff --git a/libqdutils/mdp_version.cpp b/libqdutils/mdp_version.cpp
index a444920..259d078 100644
--- a/libqdutils/mdp_version.cpp
+++ b/libqdutils/mdp_version.cpp
@@ -33,66 +33,55 @@
#include <linux/msm_mdp.h>
#include "mdp_version.h"
+#define DEBUG 0
+
ANDROID_SINGLETON_STATIC_INSTANCE(qdutils::MDPVersion);
namespace qdutils {
+#define TOKEN_PARAMS_DELIM "="
+
MDPVersion::MDPVersion()
{
int fb_fd = open("/dev/graphics/fb0", O_RDWR);
- int mdp_version = MDP_V_UNKNOWN;
char panel_type = 0;
struct fb_fix_screeninfo fb_finfo;
+ mMDPVersion = MDP_V_UNKNOWN;
mMdpRev = 0;
mRGBPipes = 0;
mVGPipes = 0;
mDMAPipes = 0;
mFeatures = 0;
+ mMDPUpscale = 0;
//TODO get this from driver, default for A-fam to 8
mMDPDownscale = 8;
mFd = fb_fd;
if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &fb_finfo) < 0) {
ALOGE("FBIOGET_FSCREENINFO failed");
- mdp_version = MDP_V_UNKNOWN;
} else {
if(!strncmp(fb_finfo.id, "msmfb", 5)) {
char str_ver[4] = { 0 };
memcpy(str_ver, &fb_finfo.id[5], 3);
str_ver[3] = '\0';
- mdp_version = atoi(str_ver);
-
+ mMDPVersion = atoi(str_ver);
//Normalize MDP version to ease comparison.
//This is needed only because
//MDP 3.0.3 reports value as 303 which
//is more than all the others
- if (mdp_version < 100)
- mdp_version *= 10;
+ if (mMDPVersion < 100)
+ mMDPVersion *= 10;
mRGBPipes = mVGPipes = 2;
} else if (!strncmp(fb_finfo.id, "mdssfb", 6)) {
- mdp_version = MDSS_V5;
-#ifdef MDSS_TARGET
- struct msmfb_metadata metadata;
- memset(&metadata, 0 , sizeof(metadata));
- metadata.op = metadata_op_get_caps;
- if (ioctl(fb_fd, MSMFB_METADATA_GET, &metadata) == -1) {
- ALOGE("Error retrieving MDP revision and pipes info");
- mdp_version = MDP_V_UNKNOWN;
- } else {
- mMdpRev = metadata.data.caps.mdp_rev;
- mRGBPipes = metadata.data.caps.rgb_pipes;
- mVGPipes = metadata.data.caps.vig_pipes;
- mDMAPipes = metadata.data.caps.dma_pipes;
- mFeatures = metadata.data.caps.features;
- if (metadata.data.caps.mdp_rev == MDP_V3_0_4){
- mdp_version = MDP_V3_0_4;
- }
+ mMDPVersion = MDSS_V5;
+ if(!updateSysFsInfo()) {
+ ALOGE("Unable to read updateSysFsInfo");
}
-#endif
- } else {
- mdp_version = MDP_V_UNKNOWN;
+ if (mMdpRev == MDP_V3_0_4){
+ mMDPVersion = MDP_V3_0_4;
+ }
}
/* Assumes panel type is 2nd element in '_' delimited id string */
@@ -104,16 +93,12 @@
panel_type = *ptype;
}
mPanelType = panel_type;
- mMDPVersion = mdp_version;
mHasOverlay = false;
if((mMDPVersion >= MDP_V4_0) ||
(mMDPVersion == MDP_V_UNKNOWN) ||
(mMDPVersion == MDP_V3_0_4))
mHasOverlay = true;
if(mMDPVersion >= MDSS_V5) {
- //TODO get this from driver
- mMDPDownscale = 4;
-
char split[64] = {0};
FILE* fp = fopen("/sys/class/graphics/fb0/msm_fb_split", "r");
if(fp){
@@ -139,6 +124,95 @@
close(mFd);
}
+int MDPVersion::tokenizeParams(char *inputParams, const char *delim,
+ char* tokenStr[], int *idx) {
+ char *tmp_token = NULL;
+ char *temp_ptr;
+ int ret = 0, index = 0;
+ if (!inputParams) {
+ return -1;
+ }
+ tmp_token = strtok_r(inputParams, delim, &temp_ptr);
+ while (tmp_token != NULL) {
+ tokenStr[index++] = tmp_token;
+ tmp_token = strtok_r(NULL, " ", &temp_ptr);
+ }
+ *idx = index;
+ return 0;
+}
+
+
+// This function reads the sysfs node to read MDP capabilities
+// and parses and updates information accordingly.
+bool MDPVersion::updateSysFsInfo() {
+ FILE *sysfsFd;
+ size_t len = 0;
+ ssize_t read;
+ char *line = NULL;
+ char sysfsPath[255];
+ memset(sysfsPath, 0, sizeof(sysfsPath));
+ snprintf(sysfsPath , sizeof(sysfsPath),
+ "/sys/class/graphics/fb0/mdp/caps");
+
+ sysfsFd = fopen(sysfsPath, "rb");
+
+ if (sysfsFd == NULL) {
+ ALOGE("%s: sysFsFile file '%s' not found",
+ __FUNCTION__, sysfsPath);
+ return false;
+ } else {
+ while((read = getline(&line, &len, sysfsFd)) != -1) {
+ int index=0;
+ char *tokens[10];
+ memset(tokens, 0, sizeof(tokens));
+
+ // parse the line and update information accordingly
+ if(!tokenizeParams(line, TOKEN_PARAMS_DELIM, tokens, &index)) {
+ if(!strncmp(tokens[0], "hw_rev", strlen("hw_rev"))) {
+ mMdpRev = atoi(tokens[1]);
+ }
+ else if(!strncmp(tokens[0], "rgb_pipes", strlen("rgb_pipes"))) {
+ mRGBPipes = atoi(tokens[1]);
+ }
+ else if(!strncmp(tokens[0], "vig_pipes", strlen("vig_pipes"))) {
+ mVGPipes = atoi(tokens[1]);
+ }
+ else if(!strncmp(tokens[0], "dma_pipes", strlen("dma_pipes"))) {
+ mDMAPipes = atoi(tokens[1]);
+ }
+ else if(!strncmp(tokens[0], "max_downscale_ratio",
+ strlen("max_downscale_ratio"))) {
+ mMDPDownscale = atoi(tokens[1]);
+ }
+ else if(!strncmp(tokens[0], "max_upscale_ratio",
+ strlen("max_upscale_ratio"))) {
+ mMDPUpscale = atoi(tokens[1]);
+ }
+ else if(!strncmp(tokens[0], "features", strlen("features"))) {
+ for(int i=1; i<index;i++) {
+ if(!strncmp(tokens[i], "bwc", strlen("bwc"))) {
+ mFeatures |= MDP_BWC_EN;
+ }
+ else if(!strncmp(tokens[i], "decimation",
+ strlen("decimation"))) {
+ mFeatures |= MDP_DECIMATION_EN;
+ }
+ }
+ }
+ }
+ free(line);
+ line = NULL;
+ }
+ fclose(sysfsFd);
+ }
+ ALOGD_IF(DEBUG, "%s: mMDPVersion: %d mMdpRev: %x mRGBPipes:%d,"
+ "mVGPipes:%d", __FUNCTION__, mMDPVersion, mMdpRev,
+ mRGBPipes, mVGPipes);
+ ALOGD_IF(DEBUG, "%s:mDMAPipes:%d \t mMDPDownscale:%d, mFeatures:%d",
+ __FUNCTION__, mDMAPipes, mMDPDownscale, mFeatures);
+ return true;
+}
+
bool MDPVersion::supportsDecimation() {
return mFeatures & MDP_DECIMATION_EN;
}
diff --git a/libqdutils/mdp_version.h b/libqdutils/mdp_version.h
index 8d23b2d..a14592b 100644
--- a/libqdutils/mdp_version.h
+++ b/libqdutils/mdp_version.h
@@ -106,6 +106,9 @@
int getLeftSplit() { return mSplit.left(); }
int getRightSplit() { return mSplit.right(); }
private:
+ bool updateSysFsInfo();
+ int tokenizeParams(char *inputParams, const char *delim,
+ char* tokenStr[], int *idx);
int mFd;
int mMDPVersion;
char mPanelType;
@@ -116,6 +119,7 @@
uint8_t mDMAPipes;
uint32_t mFeatures;
uint32_t mMDPDownscale;
+ uint32_t mMDPUpscale;
Split mSplit;
};
}; //namespace qdutils
diff --git a/libqdutils/qdMetaData.cpp b/libqdutils/qdMetaData.cpp
index 1316e59..89ca92e 100644
--- a/libqdutils/qdMetaData.cpp
+++ b/libqdutils/qdMetaData.cpp
@@ -78,6 +78,9 @@
case PP_PARAM_TIMESTAMP:
data->timestamp = *((int64_t *)param);
break;
+ case UPDATE_BUFFER_GEOMETRY:
+ memcpy((void *)&data->bufferDim, param, sizeof(BufferDim_t));
+ break;
default:
ALOGE("Unknown paramType %d", paramType);
break;
diff --git a/libqdutils/qdMetaData.h b/libqdutils/qdMetaData.h
index 9f10cf8..d5354a4 100644
--- a/libqdutils/qdMetaData.h
+++ b/libqdutils/qdMetaData.h
@@ -52,9 +52,15 @@
uint16_t c2[MAX_IGC_LUT_ENTRIES];
};
+struct BufferDim_t {
+ int32_t sliceWidth;
+ int32_t sliceHeight;
+};
+
struct MetaData_t {
int32_t operation;
int32_t interlaced;
+ BufferDim_t bufferDim;
HSICData_t hsicData;
int32_t sharpness;
int32_t video_interface;
@@ -70,7 +76,8 @@
PP_PARAM_VID_INTFC = 0x0008,
PP_PARAM_IGC = 0x0010,
PP_PARAM_SHARP2 = 0x0020,
- PP_PARAM_TIMESTAMP = 0x0040
+ PP_PARAM_TIMESTAMP = 0x0040,
+ UPDATE_BUFFER_GEOMETRY = 0x0080,
} DispParamType;
int setMetaData(private_handle_t *handle, DispParamType paramType, void *param);