Merge "libgralloc: correct assigment of HAL_PIXEL_FORMAT_RGBA_8888"
diff --git a/common.mk b/common.mk
index cfe84be..47c455f 100644
--- a/common.mk
+++ b/common.mk
@@ -31,12 +31,12 @@
endif
ifeq ($(call is-board-platform-in-list, msm8974 msm8226 msm8610 apq8084 \
- mpq8092 msm_bronze), true)
+ mpq8092 msm_bronze msm8916), true)
common_flags += -DVENUS_COLOR_FORMAT
common_flags += -DMDSS_TARGET
endif
-ifeq ($(call is-board-platform-in-list, mpq8092 msm_bronze), true)
+ifeq ($(call is-board-platform-in-list, mpq8092 msm_bronze msm8916), true)
#XXX: Replace with check from MDP when available
common_flags += -DVPU_TARGET
endif
diff --git a/libgralloc/gralloc_priv.h b/libgralloc/gralloc_priv.h
index 29c5aa5..f6d244a 100644
--- a/libgralloc/gralloc_priv.h
+++ b/libgralloc/gralloc_priv.h
@@ -108,7 +108,8 @@
HAL_PIXEL_FORMAT_BGRX_8888 = 0x112,
HAL_PIXEL_FORMAT_NV21_ZSL = 0x113,
HAL_PIXEL_FORMAT_INTERLACE = 0x180,
-
+ //v4l2_fourcc('Y', 'U', 'Y', 'L'). 24 bpp YUYV 4:2:2 10 bit per component
+ HAL_PIXEL_FORMAT_YCbCr_422_I_10BIT = 0x4C595559,
};
/* possible formats for 3D content*/
diff --git a/libgralloc/ionalloc.cpp b/libgralloc/ionalloc.cpp
index fd3abbc..311fd8f 100644
--- a/libgralloc/ionalloc.cpp
+++ b/libgralloc/ionalloc.cpp
@@ -177,7 +177,7 @@
struct ion_flush_data flush_data;
struct ion_fd_data fd_data;
struct ion_handle_data handle_data;
- struct ion_handle* handle;
+ ion_user_handle_t handle;
int err = 0;
err = open_device();
diff --git a/libhwcomposer/Android.mk b/libhwcomposer/Android.mk
index 4ef4286..7b2092d 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 msm_bronze), true)
+ifeq ($(call is-board-platform-in-list, mpq8092 msm_bronze msm8916), true)
LOCAL_SRC_FILES += hwc_vpuclient.cpp
endif
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index a805486..eb999f7 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -179,21 +179,15 @@
const int fbZ = 0;
ctx->mFBUpdate[dpy]->prepare(ctx, list, fbZ);
}
-
- if(ctx->listStats[dpy].isDisplayAnimating) {
- // Mark all app layers as HWC_OVERLAY for external during
- // animation, so that SF doesnt draw it on FB
- for(int i = 0 ;i < ctx->listStats[dpy].numAppLayers; i++) {
- hwc_layer_1_t *layer = &list->hwLayers[i];
- layer->compositionType = HWC_OVERLAY;
- }
- }
} else {
- // External Display is in Pause state.
- // ToDo:
- // Mark all application layers as OVERLAY so that
- // GPU will not compose. This is done for power
- // optimization
+ /* External Display is in Pause state.
+ * Mark all application layers as OVERLAY so that
+ * GPU will not compose.
+ */
+ for(size_t i = 0 ;i < (size_t)(list->numHwLayers - 1); i++) {
+ hwc_layer_1_t *layer = &list->hwLayers[i];
+ layer->compositionType = HWC_OVERLAY;
+ }
}
}
return 0;
@@ -217,21 +211,15 @@
const int fbZ = 0;
ctx->mFBUpdate[dpy]->prepare(ctx, list, fbZ);
}
-
- if(ctx->listStats[dpy].isDisplayAnimating) {
- // Mark all app layers as HWC_OVERLAY for virtual during
- // animation, so that SF doesnt draw it on FB
- for(int i = 0 ;i < ctx->listStats[dpy].numAppLayers; i++) {
- hwc_layer_1_t *layer = &list->hwLayers[i];
- layer->compositionType = HWC_OVERLAY;
- }
- }
} else {
- // Virtual Display is in Pause state.
- // ToDo:
- // Mark all application layers as OVERLAY so that
- // GPU will not compose. This is done for power
- // optimization
+ /* Virtual Display is in Pause state.
+ * Mark all application layers as OVERLAY so that
+ * GPU will not compose.
+ */
+ for(size_t i = 0 ;i < (size_t)(list->numHwLayers - 1); i++) {
+ hwc_layer_1_t *layer = &list->hwLayers[i];
+ layer->compositionType = HWC_OVERLAY;
+ }
}
}
return 0;
@@ -303,8 +291,6 @@
if(dpy == HWC_DISPLAY_PRIMARY) {
Locker::Autolock _l(ctx->mDrawLock);
// store the primary display orientation
- // will be used in hwc_video::configure to disable
- // rotation animation on external display
ctx->deviceOrientation = enable;
}
break;
@@ -500,7 +486,7 @@
//TODO We dont check for SKIP flag on this layer because we need PAN
//always. Last layer is always FB
private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
- if(copybitDone) {
+ if(copybitDone && ctx->mMDP.version >= qdutils::MDP_V4_0) {
hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
}
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index 4695a4f..47b9225 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -199,7 +199,8 @@
}
//Allocate render buffers if they're not allocated
- if (useCopybitForYUV || useCopybitForRGB) {
+ if (ctx->mMDP.version != qdutils::MDP_V3_0_4 &&
+ (useCopybitForYUV || useCopybitForRGB)) {
int ret = allocRenderBuffers(mAlignedFBWidth,
mAlignedFBHeight,
HAL_PIXEL_FORMAT_RGBA_8888);
@@ -223,7 +224,10 @@
// Mark all layers to be drawn by copybit
for (int i = ctx->listStats[dpy].numAppLayers-1; i >= 0 ; i--) {
layerProp[i].mFlags |= HWC_COPYBIT;
- list->hwLayers[i].compositionType = HWC_OVERLAY;
+ if (ctx->mMDP.version == qdutils::MDP_V3_0_4)
+ list->hwLayers[i].compositionType = HWC_BLIT;
+ else
+ list->hwLayers[i].compositionType = HWC_OVERLAY;
}
}
@@ -254,13 +258,20 @@
// draw layers marked for COPYBIT
int retVal = true;
int copybitLayerCount = 0;
+ uint32_t last = 0;
LayerProp *layerProp = ctx->layerProp[dpy];
+ private_handle_t *renderBuffer;
if(mCopyBitDraw == false) // there is no layer marked for copybit
return false ;
//render buffer
- private_handle_t *renderBuffer = getCurrentRenderBuffer();
+ if (ctx->mMDP.version == qdutils::MDP_V3_0_4) {
+ last = list->numHwLayers - 1;
+ renderBuffer = (private_handle_t *)list->hwLayers[last].handle;
+ } else {
+ renderBuffer = getCurrentRenderBuffer();
+ }
if (!renderBuffer) {
ALOGE("%s: Render buffer layer handle is NULL", __FUNCTION__);
return false;
@@ -274,9 +285,9 @@
mRelFd[mCurRenderBufferIndex] = -1;
}
} else {
- if(mRelFd[mCurRenderBufferIndex] >=0) {
+ if(list->hwLayers[last].acquireFenceFd >=0) {
copybit_device_t *copybit = getCopyBitDevice();
- copybit->set_sync(copybit, mRelFd[mCurRenderBufferIndex]);
+ copybit->set_sync(copybit, list->hwLayers[last].acquireFenceFd);
}
}
@@ -316,10 +327,10 @@
copybit_device_t *copybit = getCopyBitDevice();
// Async mode
copybit->flush_get_fence(copybit, fd);
- if(mRelFd[mCurRenderBufferIndex] >=0 &&
- ctx->mMDP.version == qdutils::MDP_V3_0_4) {
- close(mRelFd[mCurRenderBufferIndex]);
- mRelFd[mCurRenderBufferIndex] = -1;
+ if(ctx->mMDP.version == qdutils::MDP_V3_0_4 &&
+ list->hwLayers[last].acquireFenceFd >= 0) {
+ close(list->hwLayers[last].acquireFenceFd);
+ list->hwLayers[last].acquireFenceFd = -1;
}
}
return true;
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index bb9adbf..d601f8f 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -78,13 +78,17 @@
if(mDpy && (extOrient & HWC_TRANSFORM_ROT_90)) {
mRot = ctx->mRotMgr->getNext();
if(mRot == NULL) return false;
+ // Composed FB content will have black bars, if the viewFrame of the
+ // external is different from {0, 0, fbWidth, fbHeight}, so intersect
+ // viewFrame with sourceCrop to avoid those black bars
+ sourceCrop = getIntersection(sourceCrop, ctx->mViewFrame[mDpy]);
//Configure rotator for pre-rotation
if(configRotator(mRot, info, sourceCrop, mdpFlags, orient, 0) < 0) {
ALOGE("%s: configRotator Failed!", __FUNCTION__);
mRot = NULL;
return false;
}
- ctx->mLayerRotMap[mDpy]->add(layer, mRot);
+ ctx->mLayerRotMap[mDpy]->add(layer, mRot);
info.format = (mRot)->getDstFormat();
updateSource(orient, info, sourceCrop);
rotFlags |= ovutils::ROT_PREROTATED;
@@ -172,6 +176,8 @@
}
calcExtDisplayPosition(ctx, NULL, mDpy, sourceCrop, displayFrame,
transform, orient);
+ //Store the displayFrame, will be used in getDisplayViewFrame
+ ctx->dpyAttr[mDpy].mDstRect = displayFrame;
setMdpFlags(layer, mdpFlags, 0, transform);
// For External use rotator if there is a rotation value set
ret = preRotateExtDisplay(ctx, layer, info,
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index baef9d2..8048d71 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -157,10 +157,11 @@
return true;
}
-void MDPComp::reset(const int& numLayers, hwc_display_contents_1_t* list) {
+void MDPComp::reset(hwc_context_t *ctx) {
+ const int numLayers = ctx->listStats[mDpy].numAppLayers;
mCurrentFrame.reset(numLayers);
- mCachedFrame.cacheAll(list);
- mCachedFrame.updateCounts(mCurrentFrame);
+ ctx->mOverlay->clear(mDpy);
+ ctx->mLayerRotMap[mDpy]->clear();
}
void MDPComp::timeout_handler(void *udata) {
@@ -200,6 +201,16 @@
}
}
+void MDPComp::setRedraw(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list) {
+ mCurrentFrame.needsRedraw = false;
+ if(!mCachedFrame.isSameFrame(mCurrentFrame, list) ||
+ (list->flags & HWC_GEOMETRY_CHANGED) ||
+ isSkipPresent(ctx, mDpy)) {
+ mCurrentFrame.needsRedraw = true;
+ }
+}
+
MDPComp::FrameInfo::FrameInfo() {
reset(0);
}
@@ -513,7 +524,7 @@
/* Checks for conditions where all the layers marked for MDP comp cannot be
* bypassed. On such conditions we try to bypass atleast YUV layers */
-bool MDPComp::isFullFrameDoable(hwc_context_t *ctx,
+bool MDPComp::tryFullFrame(hwc_context_t *ctx,
hwc_display_contents_1_t* list){
const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
@@ -563,11 +574,6 @@
ret = true;
}
- if(!hwLimitationsCheck(ctx, list)) {
- ALOGD_IF(isDebug(), "%s: HW limitations",__FUNCTION__);
- return false;
- }
-
return ret;
}
@@ -596,6 +602,7 @@
qhwc::needsScaling(layer))
return false;
}
+
mCurrentFrame.fbCount = 0;
mCurrentFrame.fbZ = -1;
memcpy(&mCurrentFrame.isFBComposed, &mCurrentFrame.drop,
@@ -607,8 +614,9 @@
adjustForSourceSplit(ctx, list);
}
- if(!resourceCheck(ctx, list)) {
- ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
+ if(!postHeuristicsHandling(ctx, list)) {
+ ALOGD_IF(isDebug(), "post heuristic handling failed");
+ reset(ctx);
return false;
}
@@ -623,15 +631,16 @@
}
bool ret = false;
- if(isLoadBasedCompDoable(ctx, list)) {
- ret = loadBasedCompPreferGPU(ctx, list) ||
+ if(list->flags & HWC_GEOMETRY_CHANGED) { //Try load based first
+ ret = loadBasedCompPreferGPU(ctx, list) or
+ loadBasedCompPreferMDP(ctx, list) or
+ cacheBasedComp(ctx, list);
+ } else {
+ ret = cacheBasedComp(ctx, list) or
+ loadBasedCompPreferGPU(ctx, list) or
loadBasedCompPreferMDP(ctx, list);
}
- if(!ret) {
- ret = cacheBasedComp(ctx, list);
- }
-
return ret;
}
@@ -648,6 +657,7 @@
if(not isSupportedForMDPComp(ctx, layer)) {
ALOGD_IF(isDebug(), "%s: Unsupported layer in list",
__FUNCTION__);
+ reset(ctx);
return false;
}
}
@@ -657,6 +667,7 @@
bool ret = markLayersForCaching(ctx, list); //sets up fbZ also
if(!ret) {
ALOGD_IF(isDebug(),"%s: batching failed, dpy %d",__FUNCTION__, mDpy);
+ reset(ctx);
return false;
}
@@ -670,11 +681,13 @@
if((mDpy > HWC_DISPLAY_PRIMARY) and
(mdpCount > MAX_SEC_LAYERS)) {
ALOGD_IF(isDebug(), "%s: Exceeds max secondary pipes",__FUNCTION__);
+ reset(ctx);
return false;
}
- if(!resourceCheck(ctx, list)) {
- ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
+ if(!postHeuristicsHandling(ctx, list)) {
+ ALOGD_IF(isDebug(), "post heuristic handling failed");
+ reset(ctx);
return false;
}
@@ -683,6 +696,10 @@
bool MDPComp::loadBasedCompPreferGPU(hwc_context_t *ctx,
hwc_display_contents_1_t* list) {
+ if(not isLoadBasedCompDoable(ctx, list)) {
+ return false;
+ }
+
int numAppLayers = ctx->listStats[mDpy].numAppLayers;
mCurrentFrame.reset(numAppLayers);
@@ -726,6 +743,7 @@
if(not isSupportedForMDPComp(ctx, layer)) {
ALOGD_IF(isDebug(), "%s: MDP unsupported layer found at %d",
__FUNCTION__, i);
+ reset(ctx);
return false;
}
mCurrentFrame.isFBComposed[i] = false;
@@ -736,24 +754,31 @@
mCurrentFrame.fbCount = batchSize;
mCurrentFrame.mdpCount = mCurrentFrame.layerCount - batchSize;
+ ALOGD_IF(isDebug(), "%s: fbZ %d batchSize %d",
+ __FUNCTION__, mCurrentFrame.fbZ, batchSize);
+
if(sEnable4k2kYUVSplit){
adjustForSourceSplit(ctx, list);
}
- if(!resourceCheck(ctx, list)) {
- ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
+ if(!postHeuristicsHandling(ctx, list)) {
+ ALOGD_IF(isDebug(), "post heuristic handling failed");
+ reset(ctx);
return false;
}
- ALOGD_IF(isDebug(), "%s: fbZ %d batchSize %d",
- __FUNCTION__, mCurrentFrame.fbZ, batchSize);
return true;
}
bool MDPComp::loadBasedCompPreferMDP(hwc_context_t *ctx,
hwc_display_contents_1_t* list) {
+ if(not isLoadBasedCompDoable(ctx, list)) {
+ return false;
+ }
+
const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
- //TODO get the ib from sysfs node.
+ mCurrentFrame.reset(numAppLayers);
+
//Full screen is from ib perspective, not actual full screen
const int bpp = 4;
double panelRefRate =
@@ -782,6 +807,7 @@
if(not isSupportedForMDPComp(ctx, layer)) {
ALOGD_IF(isDebug(), "%s: MDP unsupported layer found at %d",
__FUNCTION__, i);
+ reset(ctx);
return false;
}
mCurrentFrame.isFBComposed[i] = false;
@@ -791,32 +817,39 @@
mCurrentFrame.fbCount = fbBatchSize;
mCurrentFrame.mdpCount = mCurrentFrame.layerCount - fbBatchSize;
+ ALOGD_IF(isDebug(), "%s: FB Z %d, num app layers %d, MDP Batch Size %d",
+ __FUNCTION__, mCurrentFrame.fbZ, numAppLayers,
+ numAppLayers - fbBatchSize);
+
if(sEnable4k2kYUVSplit){
adjustForSourceSplit(ctx, list);
}
- if(!resourceCheck(ctx, list)) {
- ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
+ if(!postHeuristicsHandling(ctx, list)) {
+ ALOGD_IF(isDebug(), "post heuristic handling failed");
+ reset(ctx);
return false;
}
- ALOGD_IF(isDebug(), "%s: FB Z %d, num app layers %d, MDP Batch Size %d",
- __FUNCTION__, mCurrentFrame.fbZ, numAppLayers,
- numAppLayers - fbBatchSize);
-
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)) {
+ if(mDpy or isSecurePresent(ctx, mDpy)) {
return false;
}
return true;
}
-bool MDPComp::isOnlyVideoDoable(hwc_context_t *ctx,
+bool MDPComp::tryVideoOnly(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list) {
+ const bool secureOnly = true;
+ return videoOnlyComp(ctx, list, not secureOnly) or
+ videoOnlyComp(ctx, list, secureOnly);
+}
+
+bool MDPComp::videoOnlyComp(hwc_context_t *ctx,
hwc_display_contents_1_t* list, bool secureOnly) {
int numAppLayers = ctx->listStats[mDpy].numAppLayers;
@@ -824,21 +857,28 @@
updateYUV(ctx, list, secureOnly);
int mdpCount = mCurrentFrame.mdpCount;
- if(!isYuvPresent(ctx, mDpy)) {
+ if(!isYuvPresent(ctx, mDpy) or (mdpCount == 0)) {
+ reset(ctx);
return false;
}
/* Bail out if we are processing only secured video layers
* and we dont have any */
if(!isSecurePresent(ctx, mDpy) && secureOnly){
+ reset(ctx);
return false;
}
- if(!mdpCount)
- return false;
+ if(mCurrentFrame.fbCount)
+ mCurrentFrame.fbZ = mCurrentFrame.mdpCount;
- if(!resourceCheck(ctx, list)) {
- ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
+ if(sEnable4k2kYUVSplit){
+ adjustForSourceSplit(ctx, list);
+ }
+
+ if(!postHeuristicsHandling(ctx, list)) {
+ ALOGD_IF(isDebug(), "post heuristic handling failed");
+ reset(ctx);
return false;
}
@@ -847,9 +887,7 @@
/* Checks for conditions where YUV layers cannot be bypassed */
bool MDPComp::isYUVDoable(hwc_context_t* ctx, hwc_layer_1_t* layer) {
- bool extAnimBlockFeature = mDpy && ctx->listStats[mDpy].isDisplayAnimating;
-
- if(isSkipLayer(layer) && !extAnimBlockFeature) {
+ if(isSkipLayer(layer)) {
ALOGD_IF(isDebug(), "%s: Video marked SKIP dpy %d", __FUNCTION__, mDpy);
return false;
}
@@ -1069,15 +1107,6 @@
void MDPComp::updateYUV(hwc_context_t* ctx, hwc_display_contents_1_t* list,
bool secureOnly) {
int nYuvCount = ctx->listStats[mDpy].yuvCount;
- if(!nYuvCount && mDpy) {
- //Reset "No animation on external display" related parameters.
- ctx->mPrevCropVideo.left = ctx->mPrevCropVideo.top =
- ctx->mPrevCropVideo.right = ctx->mPrevCropVideo.bottom = 0;
- ctx->mPrevDestVideo.left = ctx->mPrevDestVideo.top =
- ctx->mPrevDestVideo.right = ctx->mPrevDestVideo.bottom = 0;
- ctx->mPrevTransformVideo = 0;
- return;
- }
for(int index = 0;index < nYuvCount; index++){
int nYuvIndex = ctx->listStats[mDpy].yuvIndices[index];
hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
@@ -1104,7 +1133,21 @@
mCurrentFrame.fbCount);
}
-bool MDPComp::programMDP(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
+bool MDPComp::postHeuristicsHandling(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list) {
+
+ //Capability checks
+ if(!resourceCheck(ctx, list)) {
+ ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
+ return false;
+ }
+
+ //Limitations checks
+ if(!hwLimitationsCheck(ctx, list)) {
+ ALOGD_IF(isDebug(), "%s: HW limitations",__FUNCTION__);
+ return false;
+ }
+
//Configure framebuffer first if applicable
if(mCurrentFrame.fbZ >= 0) {
if(!ctx->mFBUpdate[mDpy]->prepare(ctx, list, mCurrentFrame.fbZ)) {
@@ -1114,6 +1157,8 @@
}
}
+ mCurrentFrame.map();
+
if(!allocLayerPipes(ctx, list)) {
ALOGD_IF(isDebug(), "%s: Unable to allocate MDP pipes", __FUNCTION__);
return false;
@@ -1154,6 +1199,7 @@
}
}
+ setRedraw(ctx, list);
return true;
}
@@ -1278,100 +1324,71 @@
const int numLayers = ctx->listStats[mDpy].numAppLayers;
MDPVersion& mdpVersion = qdutils::MDPVersion::getInstance();
+ //number of app layers exceeds MAX_NUM_APP_LAYERS fall back to GPU
+ //do not cache the information for next draw cycle.
+ if(numLayers > MAX_NUM_APP_LAYERS) {
+ ALOGI("%s: Number of App layers exceeded the limit ",
+ __FUNCTION__);
+ mCachedFrame.reset();
+ return -1;
+ }
+
//reset old data
mCurrentFrame.reset(numLayers);
memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
mCurrentFrame.dropCount = 0;
- //number of app layers exceeds MAX_NUM_APP_LAYERS fall back to GPU
- //do not cache the information for next draw cycle.
- if(numLayers > MAX_NUM_APP_LAYERS) {
+ // Detect the start of animation and fall back to GPU only once to cache
+ // all the layers in FB and display FB content untill animation completes.
+ if(ctx->listStats[mDpy].isDisplayAnimating) {
+ mCurrentFrame.needsRedraw = false;
+ if(ctx->mAnimationState[mDpy] == ANIMATION_STOPPED) {
+ mCurrentFrame.needsRedraw = true;
+ ctx->mAnimationState[mDpy] = ANIMATION_STARTED;
+ }
+ setMDPCompLayerFlags(ctx, list);
mCachedFrame.updateCounts(mCurrentFrame);
- ALOGI("%s: Number of App layers exceeded the limit ",
- __FUNCTION__);
ret = -1;
return ret;
+ } else {
+ ctx->mAnimationState[mDpy] = ANIMATION_STOPPED;
}
//Hard conditions, if not met, cannot do MDP comp
- if(!isFrameDoable(ctx)) {
- ALOGD_IF( isDebug(),"%s: MDP Comp not possible for this frame",
- __FUNCTION__);
- reset(numLayers, list);
- ret = -1;
- goto exit;
- }
+ if(isFrameDoable(ctx)) {
+ generateROI(ctx, list);
- generateROI(ctx, list);
-
- //Convert from kbps to gbps
- sMaxBw = mdpVersion.getHighBw() / 1000000.0;
- if (ctx->mExtDisplay->isConnected() || ctx->mMDP.panel != MIPI_CMD_PANEL) {
- sMaxBw = mdpVersion.getLowBw() / 1000000.0;
- }
-
- //Check whether layers marked for MDP Composition is actually doable.
- if(isFullFrameDoable(ctx, list)) {
- mCurrentFrame.map();
- //Acquire and Program MDP pipes
- if(!programMDP(ctx, list)) {
- reset(numLayers, list);
- ctx->mOverlay->clear(mDpy);
- ret = -1;
- goto exit;
- } else { //Success
- //Any change in composition types needs an FB refresh
- mCurrentFrame.needsRedraw = false;
- if(!mCachedFrame.isSameFrame(mCurrentFrame, list) ||
- (list->flags & HWC_GEOMETRY_CHANGED) ||
- isSkipPresent(ctx, mDpy)) {
- mCurrentFrame.needsRedraw = true;
- }
- }
- } else if(isOnlyVideoDoable(ctx, list, false /*secure only*/) ||
- isOnlyVideoDoable(ctx, list, true /*secure only*/)) {
- //All layers marked for MDP comp cannot be bypassed.
- //Try to compose atleast YUV layers through MDP comp and let
- //all the RGB layers compose in FB
- //Destination over
-
- mCurrentFrame.fbZ = -1;
- if(mCurrentFrame.fbCount)
- mCurrentFrame.fbZ = mCurrentFrame.mdpCount;
-
- if(sEnable4k2kYUVSplit){
- adjustForSourceSplit(ctx, list);
+ //Convert from kbps to gbps
+ sMaxBw = mdpVersion.getHighBw() / 1000000.0;
+ if (ctx->mExtDisplay->isConnected() ||
+ ctx->mMDP.panel != MIPI_CMD_PANEL) {
+ sMaxBw = mdpVersion.getLowBw() / 1000000.0;
}
- mCurrentFrame.map();
-
- if(!programMDP(ctx, list)) {
- reset(numLayers, list);
- ctx->mOverlay->clear(mDpy);
+ if(tryFullFrame(ctx, list) || tryVideoOnly(ctx, list)) {
+ setMDPCompLayerFlags(ctx, list);
+ } else {
+ reset(ctx);
+ memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
+ mCurrentFrame.dropCount = 0;
ret = -1;
- goto exit;
}
} else {
- reset(numLayers, list);
- memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
- mCurrentFrame.dropCount = 0;
+ ALOGD_IF( isDebug(),"%s: MDP Comp not possible for this frame",
+ __FUNCTION__);
ret = -1;
- goto exit;
}
- //UpdateLayerFlags
- setMDPCompLayerFlags(ctx, list);
- mCachedFrame.cacheAll(list);
- mCachedFrame.updateCounts(mCurrentFrame);
- // unlock it before calling dump function to avoid deadlock
if(isDebug()) {
- ALOGD("GEOMETRY change: %d", (list->flags & HWC_GEOMETRY_CHANGED));
+ ALOGD("GEOMETRY change: %d",
+ (list->flags & HWC_GEOMETRY_CHANGED));
android::String8 sDump("");
dump(sDump);
- ALOGE("%s",sDump.string());
+ ALOGD("%s",sDump.string());
}
-exit:
+ mCachedFrame.cacheAll(list);
+ mCachedFrame.updateCounts(mCurrentFrame);
double panelRefRate =
1000000000.0 / ctx->dpyAttr[mDpy].vsync_period;
sBwClaimed += calcMDPBytesRead(ctx, list) * panelRefRate;
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index 7e52679..05a560b 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -149,10 +149,12 @@
/* set/reset flags for MDPComp */
void setMDPCompLayerFlags(hwc_context_t *ctx,
hwc_display_contents_1_t* list);
+ void setRedraw(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list);
/* checks for conditions where mdpcomp is not possible */
bool isFrameDoable(hwc_context_t *ctx);
/* checks for conditions where RGB layers cannot be bypassed */
- bool isFullFrameDoable(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+ bool tryFullFrame(hwc_context_t *ctx, hwc_display_contents_1_t* list);
/* checks if full MDP comp can be done */
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 */
@@ -173,7 +175,8 @@
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 tryVideoOnly(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+ bool videoOnlyComp(hwc_context_t *ctx, hwc_display_contents_1_t* list,
bool secureOnly);
/* checks for conditions where YUV layers cannot be bypassed */
bool isYUVDoable(hwc_context_t* ctx, hwc_layer_1_t* layer);
@@ -212,8 +215,16 @@
/* updates cache map with YUV info */
void updateYUV(hwc_context_t* ctx, hwc_display_contents_1_t* list,
bool secureOnly);
- bool programMDP(hwc_context_t *ctx, hwc_display_contents_1_t* list);
- void reset(const int& numAppLayers, hwc_display_contents_1_t* list);
+ /* Validates if the GPU/MDP layer split chosen by a strategy is supported
+ * by MDP.
+ * Sets up MDP comp data structures to reflect covnversion from layers to
+ * overlay pipes.
+ * Configures overlay.
+ * Configures if GPU should redraw.
+ */
+ bool postHeuristicsHandling(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list);
+ void reset(hwc_context_t *ctx);
bool isSupportedForMDPComp(hwc_context_t *ctx, hwc_layer_1_t* layer);
bool resourceCheck(hwc_context_t *ctx, hwc_display_contents_1_t *list);
diff --git a/libhwcomposer/hwc_qclient.cpp b/libhwcomposer/hwc_qclient.cpp
index a3f6b5b..50e94c9 100644
--- a/libhwcomposer/hwc_qclient.cpp
+++ b/libhwcomposer/hwc_qclient.cpp
@@ -140,8 +140,34 @@
ctx->mBufferMirrorMode = enable;
}
+static status_t getDisplayVisibleRegion(hwc_context_t* ctx, int dpy,
+ Parcel* outParcel) {
+ // Get the info only if the dpy is valid
+ if(dpy >= HWC_DISPLAY_PRIMARY && dpy <= HWC_DISPLAY_VIRTUAL) {
+ Locker::Autolock _sl(ctx->mDrawLock);
+ if(dpy && (ctx->mExtOrientation || ctx->mBufferMirrorMode)) {
+ // Return the destRect on external, if external orienation
+ // is enabled
+ outParcel->writeInt32(ctx->dpyAttr[dpy].mDstRect.left);
+ outParcel->writeInt32(ctx->dpyAttr[dpy].mDstRect.top);
+ outParcel->writeInt32(ctx->dpyAttr[dpy].mDstRect.right);
+ outParcel->writeInt32(ctx->dpyAttr[dpy].mDstRect.bottom);
+ } else {
+ outParcel->writeInt32(ctx->mViewFrame[dpy].left);
+ outParcel->writeInt32(ctx->mViewFrame[dpy].top);
+ outParcel->writeInt32(ctx->mViewFrame[dpy].right);
+ outParcel->writeInt32(ctx->mViewFrame[dpy].bottom);
+ }
+ return NO_ERROR;
+ } else {
+ ALOGE("In %s: invalid dpy index %d", __FUNCTION__, dpy);
+ return BAD_VALUE;
+ }
+}
+
status_t QClient::notifyCallback(uint32_t command, const Parcel* inParcel,
Parcel* outParcel) {
+ status_t ret = NO_ERROR;
if (command > IQService::VPU_COMMAND_LIST_START &&
command < IQService::VPU_COMMAND_LIST_END) {
@@ -164,6 +190,10 @@
case IQService::BUFFER_MIRRORMODE:
setBufferMirrorMode(mHwcContext, inParcel->readInt32());
break;
+ case IQService::GET_DISPLAY_VISIBLE_REGION:
+ ret = getDisplayVisibleRegion(mHwcContext, inParcel->readInt32(),
+ outParcel);
+ break;
case IQService::CHECK_EXTERNAL_STATUS:
isExternalConnected(mHwcContext, outParcel);
break;
@@ -174,9 +204,9 @@
setHSIC(mHwcContext, inParcel);
break;
default:
- return NO_ERROR;
+ ret = NO_ERROR;
}
- return NO_ERROR;
+ return ret;
}
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index e632843..57a7554 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -134,7 +134,7 @@
ctx->mMDP.panel = qdutils::MDPVersion::getInstance().getPanelType();
overlay::Overlay::initOverlay();
ctx->mOverlay = overlay::Overlay::getInstance();
- ctx->mRotMgr = new RotMgr();
+ ctx->mRotMgr = RotMgr::getInstance();
//Is created and destroyed only once for primary
//For external it could get created and destroyed multiple times depending
@@ -172,6 +172,7 @@
for (uint32_t i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
ctx->mHwcDebug[i] = new HwcDebug(i);
ctx->mLayerRotMap[i] = new LayerRotMap();
+ ctx->mAnimationState[i] = ANIMATION_STOPPED;
}
MDPComp::init(ctx);
@@ -189,13 +190,8 @@
defaultServiceManager()->getService(
String16("display.qservice")))->connect(client);
- // Initialize "No animation on external display" related parameters.
+ // Initialize device orientation to its default orientation
ctx->deviceOrientation = 0;
- ctx->mPrevCropVideo.left = ctx->mPrevCropVideo.top =
- ctx->mPrevCropVideo.right = ctx->mPrevCropVideo.bottom = 0;
- ctx->mPrevDestVideo.left = ctx->mPrevDestVideo.top =
- ctx->mPrevDestVideo.right = ctx->mPrevDestVideo.bottom = 0;
- ctx->mPrevTransformVideo = 0;
ctx->mBufferMirrorMode = false;
#ifdef VPU_TARGET
ctx->mVPUClient = new VPUClient();
@@ -390,6 +386,7 @@
// based on the position and aspect ratio with orientation
void getAspectRatioPosition(hwc_context_t* ctx, int dpy, int extOrientation,
hwc_rect_t& inRect, hwc_rect_t& outRect) {
+ hwc_rect_t viewFrame = ctx->mViewFrame[dpy];
// Physical display resolution
float fbWidth = ctx->dpyAttr[dpy].xres;
float fbHeight = ctx->dpyAttr[dpy].yres;
@@ -427,14 +424,20 @@
yPos = rect.top;
width = rect.right - rect.left;
height = rect.bottom - rect.top;
+ // swap viewframe coordinates for 90 degree rotation.
+ swap(viewFrame.left, viewFrame.top);
+ swap(viewFrame.right, viewFrame.bottom);
}
+ // if viewframe left and top coordinates are non zero value then exclude it
+ // during the computation of xRatio and yRatio
+ xRatio = (inPos.x - viewFrame.left)/actualWidth;
+ yRatio = (inPos.y - viewFrame.top)/actualHeight;
+ // Use viewframe width and height to compute wRatio and hRatio.
+ wRatio = inPos.w/(viewFrame.right - viewFrame.left);
+ hRatio = inPos.h/(viewFrame.bottom - viewFrame.top);
+
//Calculate the position...
- xRatio = inPos.x/actualWidth;
- yRatio = inPos.y/actualHeight;
- wRatio = inPos.w/actualWidth;
- hRatio = inPos.h/actualHeight;
-
outPos.x = (xRatio * width) + xPos;
outPos.y = (yRatio * height) + yPos;
outPos.w = wRatio * width;
@@ -657,11 +660,13 @@
cropL = sourceCrop;
dstL = displayFrame;
hwc_rect_t scissorL = { 0, 0, lSplit, hw_h };
+ scissorL = getIntersection(ctx->mViewFrame[dpy], scissorL);
qhwc::calculate_crop_rects(cropL, dstL, scissorL, 0);
cropR = sourceCrop;
dstR = displayFrame;
hwc_rect_t scissorR = { lSplit, 0, hw_w, hw_h };
+ scissorR = getIntersection(ctx->mViewFrame[dpy], scissorR);
qhwc::calculate_crop_rects(cropR, dstR, scissorR, 0);
// Sanitize Crop to stitch
@@ -719,6 +724,7 @@
if(dst.left < 0 || dst.top < 0 ||
dst.right > hw_w || dst.bottom > hw_h) {
hwc_rect_t scissor = {0, 0, hw_w, hw_h };
+ scissor = getIntersection(ctx->mViewFrame[dpy], scissor);
qhwc::calculate_crop_rects(crop, dst, scissor, transform);
}
}
@@ -1182,7 +1188,8 @@
//Accumulate acquireFenceFds for MDP
for(uint32_t i = 0; i < list->numHwLayers; i++) {
- if(list->hwLayers[i].compositionType == HWC_OVERLAY &&
+ if((list->hwLayers[i].compositionType == HWC_OVERLAY ||
+ list->hwLayers[i].compositionType == HWC_BLIT) &&
list->hwLayers[i].acquireFenceFd >= 0) {
if(UNLIKELY(swapzero))
acquireFd[count++] = -1;
@@ -1224,6 +1231,7 @@
for(uint32_t i = 0; i < list->numHwLayers; i++) {
if(list->hwLayers[i].compositionType == HWC_OVERLAY ||
+ list->hwLayers[i].compositionType == HWC_BLIT ||
list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
//Populate releaseFenceFds.
if(UNLIKELY(swapzero)) {
@@ -1231,12 +1239,7 @@
} else if(isExtAnimating) {
// Release all the app layer fds immediately,
// if animation is in progress.
- hwc_layer_1_t const* layer = &list->hwLayers[i];
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- if(isYuvBuffer(hnd)) {
- list->hwLayers[i].releaseFenceFd = dup(releaseFd);
- } else
- list->hwLayers[i].releaseFenceFd = -1;
+ list->hwLayers[i].releaseFenceFd = -1;
} else if(list->hwLayers[i].releaseFenceFd < 0) {
//If rotator has not already populated this field.
list->hwLayers[i].releaseFenceFd = dup(releaseFd);
@@ -1483,29 +1486,7 @@
whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
}
- if(dpy && isYuvBuffer(hnd)) {
- if(!ctx->listStats[dpy].isDisplayAnimating) {
- ctx->mPrevCropVideo = crop;
- ctx->mPrevDestVideo = dst;
- ctx->mPrevTransformVideo = transform;
- } else {
- // Restore the previous crop, dest rect and transform values, during
- // animation to avoid displaying videos at random coordinates.
- crop = ctx->mPrevCropVideo;
- dst = ctx->mPrevDestVideo;
- transform = ctx->mPrevTransformVideo;
- orient = static_cast<eTransform>(transform);
- //In you tube use case when a device rotated from landscape to
- // portrait, set the isFg flag and zOrder to avoid displaying UI on
- // hdmi during animation
- if(ctx->deviceOrientation) {
- isFg = ovutils::IS_FG_SET;
- z = ZORDER_1;
- }
- }
- calcExtDisplayPosition(ctx, hnd, dpy, crop, dst,
- transform, orient);
- }
+ calcExtDisplayPosition(ctx, hnd, dpy, crop, dst, transform, orient);
if(isYuvBuffer(hnd) && ctx->mMDP.version >= qdutils::MDP_V4_2 &&
ctx->mMDP.version < qdutils::MDSS_V5) {
@@ -1530,8 +1511,6 @@
//Configure rotator for pre-rotation
if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale) < 0) {
ALOGE("%s: configRotator failed!", __FUNCTION__);
- ctx->mOverlay->clear(dpy);
- ctx->mLayerRotMap[dpy]->clear();
return -1;
}
ctx->mLayerRotMap[dpy]->add(layer, *rot);
@@ -1549,7 +1528,6 @@
if(configMdp(ctx->mOverlay, parg, orient, crop, dst, metadata, dest) < 0) {
ALOGE("%s: commit failed for low res panel", __FUNCTION__);
- ctx->mLayerRotMap[dpy]->clear();
return -1;
}
return 0;
@@ -1616,28 +1594,6 @@
whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
}
- if(dpy && isYuvBuffer(hnd)) {
- if(!ctx->listStats[dpy].isDisplayAnimating) {
- ctx->mPrevCropVideo = crop;
- ctx->mPrevDestVideo = dst;
- ctx->mPrevTransformVideo = transform;
- } else {
- // Restore the previous crop, dest rect and transform values, during
- // animation to avoid displaying videos at random coordinates.
- crop = ctx->mPrevCropVideo;
- dst = ctx->mPrevDestVideo;
- transform = ctx->mPrevTransformVideo;
- orient = static_cast<eTransform>(transform);
- //In you tube use case when a device rotated from landscape to
- // portrait, set the isFg flag and zOrder to avoid displaying UI on
- // hdmi during animation
- if(ctx->deviceOrientation) {
- isFg = ovutils::IS_FG_SET;
- z = ZORDER_1;
- }
- }
- }
-
setMdpFlags(layer, mdpFlagsL, 0, transform);
if(lDest != OV_INVALID && rDest != OV_INVALID) {
@@ -1658,8 +1614,6 @@
//Configure rotator for pre-rotation
if(configRotator(*rot, whf, crop, mdpFlagsL, orient, downscale) < 0) {
ALOGE("%s: configRotator failed!", __FUNCTION__);
- ctx->mOverlay->clear(dpy);
- ctx->mLayerRotMap[dpy]->clear();
return -1;
}
ctx->mLayerRotMap[dpy]->add(layer, *rot);
@@ -1680,12 +1634,14 @@
tmp_cropL = crop;
tmp_dstL = dst;
hwc_rect_t scissor = {0, 0, lSplit, hw_h };
+ scissor = getIntersection(ctx->mViewFrame[dpy], scissor);
qhwc::calculate_crop_rects(tmp_cropL, tmp_dstL, scissor, 0);
}
if(rDest != OV_INVALID) {
tmp_cropR = crop;
tmp_dstR = dst;
hwc_rect_t scissor = {lSplit, 0, hw_w, hw_h };
+ scissor = getIntersection(ctx->mViewFrame[dpy], scissor);
qhwc::calculate_crop_rects(tmp_cropR, tmp_dstR, scissor, 0);
}
@@ -1725,7 +1681,6 @@
if(configMdp(ctx->mOverlay, pargL, orient,
tmp_cropL, tmp_dstL, metadata, lDest) < 0) {
ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
- ctx->mLayerRotMap[dpy]->clear();
return -1;
}
}
@@ -1741,7 +1696,6 @@
if(configMdp(ctx->mOverlay, pargR, orient,
tmp_cropR, tmp_dstR, metadata, rDest) < 0) {
ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
- ctx->mLayerRotMap[dpy]->clear();
return -1;
}
}
@@ -1788,7 +1742,6 @@
//Configure rotator for pre-rotation
if(configRotator(*rot, whf, crop, mdpFlagsL, orient, downscale) < 0) {
ALOGE("%s: configRotator failed!", __FUNCTION__);
- ctx->mOverlay->clear(dpy);
return -1;
}
ctx->mLayerRotMap[dpy]->add(layer, *rot);
@@ -1967,17 +1920,7 @@
}
void LayerRotMap::clear() {
- for (uint32_t i = 0; i < mCount; i++) {
- //mCount represents rotator objects for just this display.
- //We could have popped mCount topmost objects from mRotMgr, but if each
- //round has the same failure, typical of stability runs, it would lead
- //to unnecessary memory allocation, deallocation each time. So we let
- //the rotator objects be around, but just knock off the fences they
- //hold. Ultimately the rotator objects will be GCed when not required.
- //Also resetting fences is required if at least one rotation round has
- //succeeded before. It'll be a NOP otherwise.
- mRot[i]->resetReleaseFd();
- }
+ RotMgr::getInstance()->markUnusedTop(mCount);
reset();
}
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 7db0f36..cd84f73 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -87,6 +87,8 @@
bool isConfiguring;
// External Display is in MDP Downscale mode indicator
bool mDownScaleMode;
+ // Ext dst Rect
+ hwc_rect_t mDstRect;
};
struct ListStats {
@@ -410,6 +412,11 @@
}; //qhwc namespace
+enum eAnimationState{
+ ANIMATION_STOPPED,
+ ANIMATION_STARTED,
+};
+
// -----------------------------------------------------------------------------
// HWC context
// This structure contains overall state
@@ -440,14 +447,10 @@
hwc_rect_t mViewFrame[HWC_NUM_DISPLAY_TYPES];
qhwc::AssertiveDisplay *mAD;
qhwc::VPUClient *mVPUClient;
+ eAnimationState mAnimationState[HWC_NUM_DISPLAY_TYPES];
- // No animation on External display feature
- // Notifies hwcomposer about the device orientation before animation.
+ // stores the primary device orientation
int deviceOrientation;
- // Stores the crop, dest rect and transform value of video before animation.
- hwc_rect_t mPrevCropVideo;
- hwc_rect_t mPrevDestVideo;
- int mPrevTransformVideo;
//Securing in progress indicator
bool mSecuring;
//WFD on proprietary stack
diff --git a/libmemtrack/kgsl.c b/libmemtrack/kgsl.c
index 4843742..6dd4e27 100644
--- a/libmemtrack/kgsl.c
+++ b/libmemtrack/kgsl.c
@@ -47,7 +47,7 @@
size_t allocated_records = min(*num_records, ARRAY_SIZE(record_templates));
int i;
FILE *fp;
- FILE *smaps_fp;
+ FILE *smaps_fp = NULL;
char line[1024];
char tmp[128];
size_t accounted_size = 0;
@@ -74,6 +74,7 @@
snprintf(tmp, sizeof(tmp), "/proc/%d/smaps", pid);
smaps_fp = fopen(tmp, "r");
if (smaps_fp == NULL) {
+ fclose(fp);
return -errno;
}
}
@@ -145,6 +146,8 @@
records[1].size_in_bytes = unaccounted_size;
}
+ if (smaps_fp)
+ fclose(smaps_fp);
fclose(fp);
return 0;
diff --git a/liboverlay/overlayRotator.cpp b/liboverlay/overlayRotator.cpp
index 4b6a8bc..d912dc7 100644
--- a/liboverlay/overlayRotator.cpp
+++ b/liboverlay/overlayRotator.cpp
@@ -107,13 +107,15 @@
mRelFence[mCurrOffset] = fence;
}
-void RotMem::Mem::resetReleaseFd() {
- //Will wait for previous offline rotation to finish, close fence fd
- //and reset
- setReleaseFd(-1);
-}
-
//============RotMgr=========================
+RotMgr * RotMgr::sRotMgr = NULL;
+
+RotMgr* RotMgr::getInstance() {
+ if(sRotMgr == NULL) {
+ sRotMgr = new RotMgr();
+ }
+ return sRotMgr;
+}
RotMgr::RotMgr() {
for(int i = 0; i < MAX_ROT_SESS; i++) {
diff --git a/liboverlay/overlayRotator.h b/liboverlay/overlayRotator.h
index 6bb94a6..2bbfb91 100644
--- a/liboverlay/overlayRotator.h
+++ b/liboverlay/overlayRotator.h
@@ -56,7 +56,6 @@
bool close() { return m.close(); }
uint32_t size() const { return m.bufSz(); }
void setReleaseFd(const int& fence);
- void resetReleaseFd();
// Max rotator buffers
enum { ROT_NUM_BUFS = 2 };
// rotator data info dst offset
@@ -73,7 +72,6 @@
Mem& prev() { return m[(_curr+1) % MAX_ROT_MEM]; }
RotMem& operator++() { ++_curr; return *this; }
void setReleaseFd(const int& fence) { curr().setReleaseFd(fence); }
- void resetReleaseFd() { curr().resetReleaseFd(); }
bool close();
uint32_t _curr;
Mem m[MAX_ROT_MEM];
@@ -98,7 +96,6 @@
virtual void dump() const = 0;
virtual void getDump(char *buf, size_t len) const = 0;
void setReleaseFd(const int& fence) { mMem.setReleaseFd(fence); }
- void resetReleaseFd() { mMem.resetReleaseFd(); }
static Rotator *getRotator();
protected:
@@ -230,21 +227,29 @@
//Maximum sessions based on VG pipes, since rotator is used only for videos.
//Even though we can have 4 mixer stages, that much may be unnecessary.
enum { MAX_ROT_SESS = 3 };
- RotMgr();
+
~RotMgr();
void configBegin();
void configDone();
overlay::Rotator *getNext();
void clear(); //Removes all instances
+ //Resets the usage of top count objects, making them available for reuse
+ void markUnusedTop(const uint32_t& count) { mUseCount -= count; }
/* Returns rot dump.
* Expects a NULL terminated buffer of big enough size.
*/
void getDump(char *buf, size_t len);
int getRotDevFd();
int getNumActiveSessions() { return mUseCount; }
+
+ static RotMgr *getInstance();
+
private:
+ RotMgr();
+ static RotMgr *sRotMgr;
+
overlay::Rotator *mRot[MAX_ROT_SESS];
- int mUseCount;
+ uint32_t mUseCount;
int mRotDevFd;
};
diff --git a/libqdutils/display_config.cpp b/libqdutils/display_config.cpp
index eaf5384..45b0211 100644
--- a/libqdutils/display_config.cpp
+++ b/libqdutils/display_config.cpp
@@ -91,4 +91,26 @@
ALOGE("%s: Failed to get external status err=%d", __FUNCTION__, err);
return err;
}
+
+int getDisplayVisibleRegion(int dpy, hwc_rect_t &rect) {
+ status_t err = FAILED_TRANSACTION;
+ sp<IQService> binder = getBinder();
+ Parcel inParcel, outParcel;
+ inParcel.writeInt32(dpy);
+ if(binder != NULL) {
+ err = binder->dispatch(IQService::GET_DISPLAY_VISIBLE_REGION,
+ &inParcel, &outParcel);
+ }
+ if(!err) {
+ rect.left = outParcel.readInt32();
+ rect.top = outParcel.readInt32();
+ rect.right = outParcel.readInt32();
+ rect.bottom = outParcel.readInt32();
+ } else {
+ ALOGE("%s: Failed to getVisibleRegion for dpy =%d: err = %d",
+ __FUNCTION__, dpy, err);
+ }
+ return err;
+}
+
}; //namespace
diff --git a/libqdutils/display_config.h b/libqdutils/display_config.h
index c7d8ce9..29edbef 100644
--- a/libqdutils/display_config.h
+++ b/libqdutils/display_config.h
@@ -29,6 +29,7 @@
#include <gralloc_priv.h>
#include <qdMetaData.h>
#include <mdp_version.h>
+#include <hardware/hwcomposer.h>
// This header is for clients to use to set/get global display configuration
// The functions in this header run in the client process and wherever necessary
@@ -69,4 +70,7 @@
// Returns 0 on success, negative values on errors
int setHSIC(int dpy, const HSICData_t& hsic_data);
+// get the active visible region for the display
+// Returns 0 on success, negative values on errors
+int getDisplayVisibleRegion(int dpy, hwc_rect_t &rect);
}; //namespace
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index d6e525a..f8e58ab 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -48,6 +48,7 @@
CHECK_EXTERNAL_STATUS, // Check status of external display
GET_DISPLAY_ATTRIBUTES, // Get display attributes
SET_HSIC_DATA, // Set HSIC on dspp
+ GET_DISPLAY_VISIBLE_REGION, // Get the visibleRegion for dpy
VPU_COMMAND_LIST_START = 100, //Reserved block for VPU commands
VPU_COMMAND_LIST_END = 200,
COMMAND_LIST_END = 400,