Merge "display: Add display HAL support for msm8916."
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index a805486..3e94d74 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -189,11 +189,14 @@
}
}
} 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;
@@ -227,11 +230,14 @@
}
}
} 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;
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index ba8b9d2..4695a4f 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -427,8 +427,7 @@
float copybitsMinScale =
(float)copybit->get(copybit,COPYBIT_MINIFICATION_LIMIT);
- if((layer->transform == HWC_TRANSFORM_ROT_90) ||
- (layer->transform == HWC_TRANSFORM_ROT_270)) {
+ if (layer->transform & HWC_TRANSFORM_ROT_90) {
//swap screen width and height
int tmp = screen_w;
screen_w = screen_h;
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index bb9adbf..0ca5ad9 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;
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index b4192b6..a290225 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -604,7 +604,7 @@
mCurrentFrame.dropCount;
if(sEnable4k2kYUVSplit){
- modifymdpCountfor4k2k(ctx, list);
+ adjustForSourceSplit(ctx, list);
}
if(!resourceCheck(ctx, list)) {
@@ -663,7 +663,7 @@
int mdpCount = mCurrentFrame.mdpCount;
if(sEnable4k2kYUVSplit){
- modifymdpCountfor4k2k(ctx, list);
+ adjustForSourceSplit(ctx, list);
}
//Will benefit cases where a video has non-updating background.
@@ -737,7 +737,7 @@
mCurrentFrame.mdpCount = mCurrentFrame.layerCount - batchSize;
if(sEnable4k2kYUVSplit){
- modifymdpCountfor4k2k(ctx, list);
+ adjustForSourceSplit(ctx, list);
}
if(!resourceCheck(ctx, list)) {
@@ -792,7 +792,7 @@
mCurrentFrame.mdpCount = mCurrentFrame.layerCount - fbBatchSize;
if(sEnable4k2kYUVSplit){
- modifymdpCountfor4k2k(ctx, list);
+ adjustForSourceSplit(ctx, list);
}
if(!resourceCheck(ctx, list)) {
@@ -915,7 +915,6 @@
int& maxBatchStart, int& maxBatchEnd,
int& maxBatchCount) {
int i = 0;
- int updatingLayersAbove = 0;//Updating layer count in middle of batch
int fbZOrder =-1;
while (i < mCurrentFrame.layerCount) {
int batchCount = 0;
@@ -923,6 +922,7 @@
int batchEnd = i;
int fbZ = batchStart;
int firstZReverseIndex = -1;
+ int updatingLayersAbove = 0;//Updating layer count in middle of batch
while(i < mCurrentFrame.layerCount) {
if(!mCurrentFrame.isFBComposed[i]) {
if(!batchCount) {
@@ -1105,6 +1105,15 @@
}
bool MDPComp::programMDP(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
+ //Configure framebuffer first if applicable
+ if(mCurrentFrame.fbZ >= 0) {
+ if(!ctx->mFBUpdate[mDpy]->prepare(ctx, list, mCurrentFrame.fbZ)) {
+ ALOGD_IF(isDebug(), "%s configure framebuffer failed",
+ __FUNCTION__);
+ return false;
+ }
+ }
+
if(!allocLayerPipes(ctx, list)) {
ALOGD_IF(isDebug(), "%s: Unable to allocate MDP pipes", __FUNCTION__);
return false;
@@ -1304,35 +1313,11 @@
//Check whether layers marked for MDP Composition is actually doable.
if(isFullFrameDoable(ctx, list)) {
mCurrentFrame.map();
- //Configure framebuffer first if applicable
- if(mCurrentFrame.fbZ >= 0) {
- //If 4k2k Yuv layer split is possible, and if
- //fbz is above 4k2k layer, increment fb zorder by 1
- //as we split 4k2k layer and increment zorder for right half
- //of the layer
- if(sEnable4k2kYUVSplit){
- int n4k2kYuvCount = ctx->listStats[mDpy].yuv4k2kCount;
- for(int index = 0; index < n4k2kYuvCount; index++){
- int n4k2kYuvIndex =
- ctx->listStats[mDpy].yuv4k2kIndices[index];
- if(mCurrentFrame.fbZ > n4k2kYuvIndex){
- mCurrentFrame.fbZ += 1;
- }
- }
- }
- if(!ctx->mFBUpdate[mDpy]->prepare(ctx, list,
- mCurrentFrame.fbZ)) {
- ALOGE("%s configure framebuffer failed", __func__);
- reset(numLayers, list);
- ctx->mOverlay->clear(mDpy);
- ret = -1;
- goto exit;
- }
- }
//Acquire and Program MDP pipes
if(!programMDP(ctx, list)) {
reset(numLayers, list);
ctx->mOverlay->clear(mDpy);
+ ctx->mLayerRotMap[mDpy]->clear();
ret = -1;
goto exit;
} else { //Success
@@ -1351,29 +1336,20 @@
//all the RGB layers compose in FB
//Destination over
- if(sEnable4k2kYUVSplit){
- modifymdpCountfor4k2k(ctx, list);
- }
-
mCurrentFrame.fbZ = -1;
if(mCurrentFrame.fbCount)
mCurrentFrame.fbZ = mCurrentFrame.mdpCount;
+ if(sEnable4k2kYUVSplit){
+ adjustForSourceSplit(ctx, list);
+ }
+
mCurrentFrame.map();
- //Configure framebuffer first if applicable
- if(mCurrentFrame.fbZ >= 0) {
- if(!ctx->mFBUpdate[mDpy]->prepare(ctx, list, mCurrentFrame.fbZ)) {
- ALOGE("%s configure framebuffer failed", __func__);
- reset(numLayers, list);
- ctx->mOverlay->clear(mDpy);
- ret = -1;
- goto exit;
- }
- }
if(!programMDP(ctx, list)) {
reset(numLayers, list);
ctx->mOverlay->clear(mDpy);
+ ctx->mLayerRotMap[mDpy]->clear();
ret = -1;
goto exit;
}
@@ -1436,11 +1412,26 @@
}
//=============MDPCompNonSplit===================================================
-void MDPCompNonSplit::modifymdpCountfor4k2k(hwc_context_t *ctx,
+void MDPCompNonSplit::adjustForSourceSplit(hwc_context_t *ctx,
hwc_display_contents_1_t* list){
//As we split 4kx2k yuv layer and program to 2 VG pipes
//(if available) increase mdpcount accordingly
mCurrentFrame.mdpCount += ctx->listStats[mDpy].yuv4k2kCount;
+
+ //If 4k2k Yuv layer split is possible, and if
+ //fbz is above 4k2k layer, increment fb zorder by 1
+ //as we split 4k2k layer and increment zorder for right half
+ //of the layer
+ if(mCurrentFrame.fbZ >= 0) {
+ int n4k2kYuvCount = ctx->listStats[mDpy].yuv4k2kCount;
+ for(int index = 0; index < n4k2kYuvCount; index++){
+ int n4k2kYuvIndex =
+ ctx->listStats[mDpy].yuv4k2kIndices[index];
+ if(mCurrentFrame.fbZ > n4k2kYuvIndex){
+ mCurrentFrame.fbZ += 1;
+ }
+ }
+ }
}
/*
@@ -1688,7 +1679,7 @@
//=============MDPCompSplit===================================================
-void MDPCompSplit::modifymdpCountfor4k2k(hwc_context_t *ctx,
+void MDPCompSplit::adjustForSourceSplit(hwc_context_t *ctx,
hwc_display_contents_1_t* list){
//if 4kx2k yuv layer is totally present in either in left half
//or right half then try splitting the yuv layer to avoid decimation
@@ -1698,10 +1689,12 @@
int n4k2kYuvIndex = ctx->listStats[mDpy].yuv4k2kIndices[index];
hwc_layer_1_t* layer = &list->hwLayers[n4k2kYuvIndex];
hwc_rect_t dst = layer->displayFrame;
-
- if((dst.left > lSplit)||(dst.right < lSplit)){
+ if((dst.left > lSplit) || (dst.right < lSplit)) {
mCurrentFrame.mdpCount += 1;
}
+ if(mCurrentFrame.fbZ > n4k2kYuvIndex){
+ mCurrentFrame.fbZ += 1;
+ }
}
}
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index 8e9b1be..7e52679 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -139,8 +139,9 @@
/* Checks for pipes needed versus pipes available */
virtual bool arePipesAvailable(hwc_context_t *ctx,
hwc_display_contents_1_t* list) = 0;
- /* increments mdpCount if 4k2k yuv layer split is enabled*/
- virtual void modifymdpCountfor4k2k(hwc_context_t *ctx,
+ /* Increments mdpCount if 4k2k yuv layer split is enabled.
+ * updates framebuffer z order if fb lies above source-split layer */
+ virtual void adjustForSourceSplit(hwc_context_t *ctx,
hwc_display_contents_1_t* list) = 0;
/* configures 4kx2k yuv layer*/
virtual int configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
@@ -266,8 +267,9 @@
virtual bool areVGPipesAvailable(hwc_context_t *ctx,
hwc_display_contents_1_t* list);
- /* increments mdpCount if 4k2k yuv layer split is enabled*/
- virtual void modifymdpCountfor4k2k(hwc_context_t *ctx,
+ /* Increments mdpCount if 4k2k yuv layer split is enabled.
+ * updates framebuffer z order if fb lies above source-split layer */
+ virtual void adjustForSourceSplit(hwc_context_t *ctx,
hwc_display_contents_1_t* list);
/* configures 4kx2k yuv layer to 2 VG pipes*/
@@ -306,8 +308,9 @@
virtual bool areVGPipesAvailable(hwc_context_t *ctx,
hwc_display_contents_1_t* list);
- /* increments mdpCount if 4k2k yuv layer split is enabled*/
- virtual void modifymdpCountfor4k2k(hwc_context_t *ctx,
+ /* Increments mdpCount if 4k2k yuv layer split is enabled.
+ * updates framebuffer z order if fb lies above source-split layer */
+ virtual void adjustForSourceSplit(hwc_context_t *ctx,
hwc_display_contents_1_t* list);
/* configures 4kx2k yuv layer*/
diff --git a/libhwcomposer/hwc_qclient.cpp b/libhwcomposer/hwc_qclient.cpp
index 3b98788..a3f6b5b 100644
--- a/libhwcomposer/hwc_qclient.cpp
+++ b/libhwcomposer/hwc_qclient.cpp
@@ -86,12 +86,10 @@
static android::status_t screenRefresh(hwc_context_t *ctx) {
status_t result = NO_INIT;
-#ifdef QCOM_BSP
if(ctx->proc) {
ctx->proc->invalidate(ctx->proc);
result = NO_ERROR;
}
-#endif
return result;
}
@@ -100,11 +98,9 @@
const Parcel* inParcel,
Parcel* outParcel) {
status_t result = NO_INIT;
-#ifdef QCOM_BSP
#ifdef VPU_TARGET
result = ctx->mVPUClient->processCommand(command, inParcel, outParcel);
#endif
-#endif
return result;
}
@@ -112,6 +108,34 @@
ctx->mExtOrientation = orientation;
}
+static void isExternalConnected(hwc_context_t* ctx, Parcel* outParcel) {
+ int connected;
+ connected = ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected ? 1 : 0;
+ outParcel->writeInt32(connected);
+}
+
+static void getDisplayAttributes(hwc_context_t* ctx, const Parcel* inParcel,
+ Parcel* outParcel) {
+ int dpy = inParcel->readInt32();
+ outParcel->writeInt32(ctx->dpyAttr[dpy].vsync_period);
+ outParcel->writeInt32(ctx->dpyAttr[dpy].xres);
+ outParcel->writeInt32(ctx->dpyAttr[dpy].yres);
+ outParcel->writeFloat(ctx->dpyAttr[dpy].xdpi);
+ outParcel->writeFloat(ctx->dpyAttr[dpy].ydpi);
+ //XXX: Need to check what to return for HDMI
+ outParcel->writeInt32(ctx->mMDP.panel);
+}
+static void setHSIC(hwc_context_t* ctx, const Parcel* inParcel) {
+ int dpy = inParcel->readInt32();
+ HSICData_t hsic_data;
+ hsic_data.hue = inParcel->readInt32();
+ hsic_data.saturation = inParcel->readFloat();
+ hsic_data.intensity = inParcel->readInt32();
+ hsic_data.contrast = inParcel->readFloat();
+ //XXX: Actually set the HSIC data through ABL lib
+}
+
+
static void setBufferMirrorMode(hwc_context_t *ctx, uint32_t enable) {
ctx->mBufferMirrorMode = enable;
}
@@ -140,6 +164,15 @@
case IQService::BUFFER_MIRRORMODE:
setBufferMirrorMode(mHwcContext, inParcel->readInt32());
break;
+ case IQService::CHECK_EXTERNAL_STATUS:
+ isExternalConnected(mHwcContext, outParcel);
+ break;
+ case IQService::GET_DISPLAY_ATTRIBUTES:
+ getDisplayAttributes(mHwcContext, inParcel, outParcel);
+ break;
+ case IQService::SET_HSIC_DATA:
+ setHSIC(mHwcContext, inParcel);
+ break;
default:
return NO_ERROR;
}
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index e5358f9..472fe59 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
@@ -311,12 +311,12 @@
float xRatio = 1.0;
float yRatio = 1.0;
- float fbWidth = ctx->dpyAttr[dpy].xres;
- float fbHeight = ctx->dpyAttr[dpy].yres;
+ int fbWidth = ctx->dpyAttr[dpy].xres;
+ int 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);
+ ctx->mExtDisplay->getAttributes(fbWidth, fbHeight);
}
@@ -329,7 +329,7 @@
float asX = 0;
float asY = 0;
float asW = fbWidth;
- float asH= fbHeight;
+ float asH = fbHeight;
// based on the action safe ratio, get the Action safe rectangle
asW = fbWidth * (1.0f - asWidthRatio / 100.0f);
@@ -390,6 +390,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 +428,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 +664,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 +728,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);
}
}
@@ -756,6 +766,7 @@
(int)ctx->dpyAttr[dpy].xres, (int)ctx->dpyAttr[dpy].yres);
ctx->listStats[dpy].secureUI = false;
ctx->listStats[dpy].yuv4k2kCount = 0;
+ ctx->mViewFrame[dpy] = (hwc_rect_t){0, 0, 0, 0};
trimList(ctx, list, dpy);
optimizeLayerRects(ctx, list, dpy);
@@ -764,6 +775,9 @@
hwc_layer_1_t const* layer = &list->hwLayers[i];
private_handle_t *hnd = (private_handle_t *)layer->handle;
+ // Calculate view frame of each display from the layer displayframe
+ ctx->mViewFrame[dpy] = getUnion(ctx->mViewFrame[dpy],
+ layer->displayFrame);
#ifdef QCOM_BSP
if (layer->flags & HWC_SCREENSHOT_ANIMATOR_LAYER) {
ctx->listStats[dpy].isDisplayAnimating = true;
@@ -1526,8 +1540,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);
@@ -1545,7 +1557,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;
@@ -1654,8 +1665,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);
@@ -1676,12 +1685,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);
}
@@ -1721,7 +1732,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;
}
}
@@ -1737,7 +1747,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;
}
}
@@ -1784,7 +1793,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);
@@ -1963,17 +1971,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 9751199..7db0f36 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -437,6 +437,7 @@
qhwc::LayerProp *layerProp[HWC_NUM_DISPLAY_TYPES];
qhwc::MDPComp *mMDPComp[HWC_NUM_DISPLAY_TYPES];
qhwc::HwcDebug *mHwcDebug[HWC_NUM_DISPLAY_TYPES];
+ hwc_rect_t mViewFrame[HWC_NUM_DISPLAY_TYPES];
qhwc::AssertiveDisplay *mAD;
qhwc::VPUClient *mVPUClient;
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/Android.mk b/libqdutils/Android.mk
index d514405..06f4f00 100644
--- a/libqdutils/Android.mk
+++ b/libqdutils/Android.mk
@@ -4,14 +4,16 @@
LOCAL_MODULE := libqdutils
LOCAL_MODULE_TAGS := optional
-LOCAL_SHARED_LIBRARIES := $(common_libs) libui
+LOCAL_SHARED_LIBRARIES := $(common_libs) libui libbinder libqservice
LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes)
LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdutils\"
LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
+LOCAL_COPY_HEADERS_TO := $(common_header_export_path)
+LOCAL_COPY_HEADERS := display_config.h mdp_version.h
LOCAL_SRC_FILES := profiler.cpp mdp_version.cpp \
idle_invalidator.cpp \
comptype.cpp qd_utils.cpp \
- cb_utils.cpp
+ cb_utils.cpp display_config.cpp
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
diff --git a/libqdutils/display_config.cpp b/libqdutils/display_config.cpp
new file mode 100644
index 0000000..eaf5384
--- /dev/null
+++ b/libqdutils/display_config.cpp
@@ -0,0 +1,94 @@
+/*
+* Copyright (c) 2013 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
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation. nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <display_config.h>
+#include <QServiceUtils.h>
+
+using namespace android;
+using namespace qService;
+
+namespace qdutils {
+
+int isExternalConnected(void) {
+ int ret;
+ status_t err = FAILED_TRANSACTION;
+ sp<IQService> binder = getBinder();
+ Parcel inParcel, outParcel;
+ if(binder != NULL) {
+ err = binder->dispatch(IQService::CHECK_EXTERNAL_STATUS,
+ &inParcel , &outParcel);
+ }
+ if(err) {
+ ALOGE("%s: Failed to get external status err=%d", __FUNCTION__, err);
+ ret = err;
+ } else {
+ ret = outParcel.readInt32();
+ }
+ return ret;
+}
+
+int getDisplayAttributes(int dpy, DisplayAttributes_t& dpyattr) {
+ status_t err = FAILED_TRANSACTION;
+ sp<IQService> binder = getBinder();
+ Parcel inParcel, outParcel;
+ inParcel.writeInt32(dpy);
+ if(binder != NULL) {
+ err = binder->dispatch(IQService::GET_DISPLAY_ATTRIBUTES,
+ &inParcel, &outParcel);
+ }
+ if(!err) {
+ dpyattr.vsync_period = outParcel.readInt32();
+ dpyattr.xres = outParcel.readInt32();
+ dpyattr.yres = outParcel.readInt32();
+ dpyattr.xdpi = outParcel.readFloat();
+ dpyattr.ydpi = outParcel.readFloat();
+ dpyattr.panel_type = (char) outParcel.readInt32();
+ } else {
+ ALOGE("%s: Failed to get display attributes err=%d", __FUNCTION__, err);
+ }
+ return err;
+}
+
+int setHSIC(int dpy, const HSICData_t& hsic_data) {
+ status_t err = FAILED_TRANSACTION;
+ sp<IQService> binder = getBinder();
+ Parcel inParcel, outParcel;
+ inParcel.writeInt32(dpy);
+ inParcel.writeInt32(hsic_data.hue);
+ inParcel.writeFloat(hsic_data.saturation);
+ inParcel.writeInt32(hsic_data.intensity);
+ inParcel.writeFloat(hsic_data.contrast);
+ if(binder != NULL) {
+ err = binder->dispatch(IQService::SET_HSIC_DATA, &inParcel, &outParcel);
+ }
+ if(err)
+ ALOGE("%s: Failed to get external status err=%d", __FUNCTION__, err);
+ return err;
+}
+}; //namespace
diff --git a/libqdutils/display_config.h b/libqdutils/display_config.h
new file mode 100644
index 0000000..c7d8ce9
--- /dev/null
+++ b/libqdutils/display_config.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2013 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
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <gralloc_priv.h>
+#include <qdMetaData.h>
+#include <mdp_version.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
+// do a binder call to HWC to get/set data.
+// Only primary and external displays are supported here.
+// WiFi/virtual displays are not supported.
+
+namespace qdutils {
+
+// Use this enum to specify the dpy parameters where needed
+enum {
+ DISPLAY_PRIMARY = 0,
+ DISPLAY_EXTERNAL,
+};
+
+// Display Attributes that are available to clients of this library
+// Not to be confused with a similar struct in hwc_utils (in the hwc namespace)
+struct DisplayAttributes_t {
+ uint32_t vsync_period; //nanoseconds
+ uint32_t xres;
+ uint32_t yres;
+ float xdpi;
+ float ydpi;
+ char panel_type;
+};
+
+// Check if external display is connected. Useful to check before making
+// calls for external displays
+// Returns 1 if connected, 0 if disconnected, negative values on errors
+int isExternalConnected(void);
+
+// Get display vsync period which is in nanoseconds
+// i.e vsync_period = 1000000000l / fps
+// Returns 0 on success, negative values on errors
+int getDisplayAttributes(int dpy, DisplayAttributes_t& dpyattr);
+
+// Set HSIC data on a given display ID
+// Returns 0 on success, negative values on errors
+int setHSIC(int dpy, const HSICData_t& hsic_data);
+
+}; //namespace
diff --git a/libqservice/Android.mk b/libqservice/Android.mk
index 17b2eda..0c6123b 100644
--- a/libqservice/Android.mk
+++ b/libqservice/Android.mk
@@ -6,7 +6,7 @@
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes)
-LOCAL_SHARED_LIBRARIES := $(common_libs) libexternal libbinder
+LOCAL_SHARED_LIBRARIES := $(common_libs) libbinder
LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdqservice\"
LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
LOCAL_SRC_FILES := QService.cpp \
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index 7ad443d..d6e525a 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -45,6 +45,9 @@
SCREEN_REFRESH, // Refresh screen through SF invalidate
EXTERNAL_ORIENTATION, // Set external orientation
BUFFER_MIRRORMODE, // Buffer mirrormode
+ CHECK_EXTERNAL_STATUS, // Check status of external display
+ GET_DISPLAY_ATTRIBUTES, // Get display attributes
+ SET_HSIC_DATA, // Set HSIC on dspp
VPU_COMMAND_LIST_START = 100, //Reserved block for VPU commands
VPU_COMMAND_LIST_END = 200,
COMMAND_LIST_END = 400,