Merge "hwc: On downscale check swap on 90 transform"
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index b1d7616..59f6245 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -474,9 +474,18 @@
ovutils::eDest destR = ovutils::OV_INVALID;
- //Request right pipe (2 pipes needed only if dim > 2048)
- if((fbUpdatingRect.right - fbUpdatingRect.left) >
- qdutils::MAX_DISPLAY_DIM) {
+ /* Use 2 pipes IF
+ a) FB's width is > 2048 or
+ b) On primary, driver has indicated with caps to split always. This is
+ based on an empirically derived value of panel height.
+ */
+
+ bool primarySplitAlways = (mDpy == HWC_DISPLAY_PRIMARY) and
+ qdutils::MDPVersion::getInstance().isSrcSplitAlways();
+
+ if(((fbUpdatingRect.right - fbUpdatingRect.left) >
+ qdutils::MAX_DISPLAY_DIM) or
+ primarySplitAlways) {
destR = ov.getPipe(pipeSpecs);
if(destR == ovutils::OV_INVALID) {
ALOGE("%s: No pipes available to configure fb for dpy %d's right"
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index b80046e..b0953da 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -2185,9 +2185,23 @@
return false;
}
- //If layer's crop width or dest width > 2048, use 2 pipes
- if((dst.right - dst.left) > qdutils::MAX_DISPLAY_DIM or
- (crop.right - crop.left) > qdutils::MAX_DISPLAY_DIM) {
+ /* Use 2 pipes IF
+ a) Layer's crop width is > 2048 or
+ b) Layer's dest width > 2048 or
+ c) On primary, driver has indicated with caps to split always. This is
+ based on an empirically derived value of panel height. Applied only
+ if the layer's width is > mixer's width
+ */
+
+ bool primarySplitAlways = (mDpy == HWC_DISPLAY_PRIMARY) and
+ qdutils::MDPVersion::getInstance().isSrcSplitAlways();
+ int lSplit = getLeftSplit(ctx, mDpy);
+ int dstWidth = dst.right - dst.left;
+ int cropWidth = crop.right - crop.left;
+
+ if(dstWidth > qdutils::MAX_DISPLAY_DIM or
+ cropWidth > qdutils::MAX_DISPLAY_DIM or
+ (primarySplitAlways and (cropWidth > lSplit))) {
pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
if(pipe_info.rIndex == ovutils::OV_INVALID) {
return false;
diff --git a/libhwcomposer/hwc_qclient.cpp b/libhwcomposer/hwc_qclient.cpp
index 0bb71f0..77215ca 100644
--- a/libhwcomposer/hwc_qclient.cpp
+++ b/libhwcomposer/hwc_qclient.cpp
@@ -193,6 +193,26 @@
}
}
+
+static status_t setViewFrame(hwc_context_t* ctx, const Parcel* inParcel) {
+ int dpy = inParcel->readInt32();
+ if(dpy >= HWC_DISPLAY_PRIMARY && dpy <= HWC_DISPLAY_VIRTUAL) {
+ Locker::Autolock _sl(ctx->mDrawLock);
+ ctx->mViewFrame[dpy].left = inParcel->readInt32();
+ ctx->mViewFrame[dpy].top = inParcel->readInt32();
+ ctx->mViewFrame[dpy].right = inParcel->readInt32();
+ ctx->mViewFrame[dpy].bottom = inParcel->readInt32();
+ ALOGD_IF(QCLIENT_DEBUG, "%s: mViewFrame[%d] = [%d %d %d %d]",
+ __FUNCTION__, dpy,
+ ctx->mViewFrame[dpy].left, ctx->mViewFrame[dpy].top,
+ ctx->mViewFrame[dpy].right, 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;
@@ -232,6 +252,9 @@
case IQService::SET_WFD_STATUS:
setWfdStatus(mHwcContext,inParcel->readInt32());
break;
+ case IQService::SET_VIEW_FRAME:
+ setViewFrame(mHwcContext, inParcel);
+ break;
default:
ret = NO_ERROR;
}
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 94a396c..671388b 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -292,7 +292,7 @@
ctx->mGPUHintInfo.mEGLDisplay = NULL;
ctx->mGPUHintInfo.mEGLContext = NULL;
- ctx->mGPUHintInfo.mPrevCompositionGLES = false;
+ ctx->mGPUHintInfo.mCompositionState = COMPOSITION_STATE_MDP;
ctx->mGPUHintInfo.mCurrGPUPerfMode = EGL_GPU_LEVEL_0;
#endif
ALOGI("Initializing Qualcomm Hardware Composer");
@@ -810,28 +810,6 @@
}
}
-hwc_rect_t calculateDisplayViewFrame(hwc_context_t *ctx, int dpy) {
- int dstWidth = ctx->dpyAttr[dpy].xres;
- int dstHeight = ctx->dpyAttr[dpy].yres;
- int srcWidth = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
- int srcHeight = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
- // default we assume viewframe as a full frame for primary display
- hwc_rect outRect = {0, 0, dstWidth, dstHeight};
- if(dpy) {
- // swap srcWidth and srcHeight, if the device orientation is 90 or 270.
- if(ctx->deviceOrientation & 0x1) {
- swap(srcWidth, srcHeight);
- }
- // Get Aspect Ratio for external
- getAspectRatioPosition(dstWidth, dstHeight, srcWidth,
- srcHeight, outRect);
- }
- ALOGD_IF(HWC_UTILS_DEBUG, "%s: view frame for dpy %d is [%d %d %d %d]",
- __FUNCTION__, dpy, outRect.left, outRect.top,
- outRect.right, outRect.bottom);
- return outRect;
-}
-
void setListStats(hwc_context_t *ctx,
hwc_display_contents_1_t *list, int dpy) {
const int prevYuvCount = ctx->listStats[dpy].yuvCount;
@@ -847,19 +825,13 @@
ctx->listStats[dpy].isDisplayAnimating = false;
ctx->listStats[dpy].secureUI = false;
ctx->listStats[dpy].yuv4k2kCount = 0;
- ctx->mViewFrame[dpy] = (hwc_rect_t){0, 0, 0, 0};
ctx->dpyAttr[dpy].mActionSafePresent = isActionSafePresent(ctx, dpy);
ctx->listStats[dpy].renderBufIndexforABC = -1;
resetROI(ctx, dpy);
- // Calculate view frame of ext display from primary resolution
- // and primary device orientation.
- ctx->mViewFrame[dpy] = calculateDisplayViewFrame(ctx, dpy);
-
trimList(ctx, list, dpy);
optimizeLayerRects(list);
-
for (size_t i = 0; i < (size_t)ctx->listStats[dpy].numAppLayers; i++) {
hwc_layer_1_t const* layer = &list->hwLayers[i];
private_handle_t *hnd = (private_handle_t *)layer->handle;
@@ -2139,7 +2111,8 @@
}
}
if(isGLESComp(ctx, list)) {
- if(!gpuHint->mPrevCompositionGLES && !MDPComp::isIdleFallback()) {
+ if(gpuHint->mCompositionState != COMPOSITION_STATE_GPU
+ && !MDPComp::isIdleFallback()) {
EGLint attr_list[] = {EGL_GPU_HINT_1,
EGL_GPU_LEVEL_3,
EGL_NONE };
@@ -2149,7 +2122,7 @@
ALOGW("eglGpuPerfHintQCOM failed for Built in display");
} else {
gpuHint->mCurrGPUPerfMode = EGL_GPU_LEVEL_3;
- gpuHint->mPrevCompositionGLES = true;
+ gpuHint->mCompositionState = COMPOSITION_STATE_GPU;
}
} else {
EGLint attr_list[] = {EGL_GPU_HINT_1,
@@ -2162,6 +2135,9 @@
} else {
gpuHint->mCurrGPUPerfMode = EGL_GPU_LEVEL_0;
}
+ if(MDPComp::isIdleFallback()) {
+ gpuHint->mCompositionState = COMPOSITION_STATE_IDLE_FALLBACK;
+ }
}
} else {
/* set the GPU hint flag to default for MDP composition */
@@ -2175,7 +2151,7 @@
} else {
gpuHint->mCurrGPUPerfMode = EGL_GPU_LEVEL_0;
}
- gpuHint->mPrevCompositionGLES = false;
+ gpuHint->mCompositionState = COMPOSITION_STATE_MDP;
}
#endif
}
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 5086d72..06f7f9f 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -224,11 +224,6 @@
// -----------------------------------------------------------------------------
// Utility functions - implemented in hwc_utils.cpp
void dumpLayer(hwc_layer_1_t const* l);
-
-// Calculate viewframe for external/primary display from primary resolution and
-// primary device orientation
-hwc_rect_t calculateDisplayViewFrame(hwc_context_t *ctx, int dpy);
-
void setListStats(hwc_context_t *ctx, hwc_display_contents_1_t *list,
int dpy);
void initContext(hwc_context_t *ctx);
@@ -478,14 +473,20 @@
ANIMATION_STARTED,
};
+enum eCompositionState {
+ COMPOSITION_STATE_MDP = 0, // Set if composition type is MDP
+ COMPOSITION_STATE_GPU, // Set if composition type is GPU or MIXED
+ COMPOSITION_STATE_IDLE_FALLBACK, // Set if it is idlefallback
+};
+
// Structure holds the information about the GPU hint.
struct gpu_hint_info {
// system level flag to enable gpu_perf_mode
bool mGpuPerfModeEnable;
// Stores the current GPU performance mode DEFAULT/HIGH
bool mCurrGPUPerfMode;
- // true if previous composition used GPU
- bool mPrevCompositionGLES;
+ // Stores the compositon state GPU, MDP or IDLE_FALLBACK
+ bool mCompositionState;
// Stores the EGLContext of current process
EGLContext mEGLContext;
// Stores the EGLDisplay of current process
diff --git a/libqdutils/display_config.cpp b/libqdutils/display_config.cpp
index 60f1f68..7ff106f 100644
--- a/libqdutils/display_config.cpp
+++ b/libqdutils/display_config.cpp
@@ -113,4 +113,25 @@
return err;
}
+int setViewFrame(int dpy, int l, int t, int r, int b) {
+ status_t err = (status_t) FAILED_TRANSACTION;
+ sp<IQService> binder = getBinder();
+ Parcel inParcel, outParcel;
+ inParcel.writeInt32(dpy);
+ inParcel.writeInt32(l);
+ inParcel.writeInt32(t);
+ inParcel.writeInt32(r);
+ inParcel.writeInt32(b);
+
+ if(binder != NULL) {
+ err = binder->dispatch(IQService::SET_VIEW_FRAME,
+ &inParcel, &outParcel);
+ }
+ if(err)
+ ALOGE("%s: Failed to set view frame for dpy %d err=%d",
+ __FUNCTION__, dpy, err);
+
+ return err;
+}
+
}; //namespace
diff --git a/libqdutils/display_config.h b/libqdutils/display_config.h
index 29edbef..a69265b 100644
--- a/libqdutils/display_config.h
+++ b/libqdutils/display_config.h
@@ -73,4 +73,7 @@
// get the active visible region for the display
// Returns 0 on success, negative values on errors
int getDisplayVisibleRegion(int dpy, hwc_rect_t &rect);
+
+// set the view frame information in hwc context from surfaceflinger
+int setViewFrame(int dpy, int l, int t, int r, int b);
}; //namespace
diff --git a/libqdutils/mdp_version.cpp b/libqdutils/mdp_version.cpp
index 96ed4d2..bc63ddf 100644
--- a/libqdutils/mdp_version.cpp
+++ b/libqdutils/mdp_version.cpp
@@ -88,6 +88,7 @@
mLowBw = 0;
mHighBw = 0;
mSourceSplit = false;
+ mSourceSplitAlways = false;
mRGBHasNoScalar = false;
updatePanelInfo();
@@ -306,6 +307,30 @@
free(line);
fclose(sysfsFd);
}
+
+ if(mSourceSplit) {
+ memset(sysfsPath, 0, sizeof(sysfsPath));
+ snprintf(sysfsPath , sizeof(sysfsPath),
+ "/sys/class/graphics/fb0/msm_fb_src_split_info");
+
+ sysfsFd = fopen(sysfsPath, "rb");
+ if (sysfsFd == NULL) {
+ ALOGE("%s: Opening file %s failed with error %s", __FUNCTION__,
+ sysfsPath, strerror(errno));
+ return false;
+ } else {
+ line = (char *) malloc(len);
+ if((read = getline(&line, &len, sysfsFd)) != -1) {
+ if(!strncmp(line, "src_split_always",
+ strlen("src_split_always"))) {
+ mSourceSplitAlways = true;
+ }
+ }
+ free(line);
+ fclose(sysfsFd);
+ }
+ }
+
ALOGD_IF(DEBUG, "%s: mMDPVersion: %d mMdpRev: %x mRGBPipes:%d,"
"mVGPipes:%d", __FUNCTION__, mMDPVersion, mMdpRev,
mRGBPipes, mVGPipes);
@@ -371,6 +396,10 @@
return mSourceSplit;
}
+bool MDPVersion::isSrcSplitAlways() const {
+ return mSourceSplitAlways;
+}
+
bool MDPVersion::isRGBScalarSupported() const {
return (!mRGBHasNoScalar);
}
diff --git a/libqdutils/mdp_version.h b/libqdutils/mdp_version.h
index e862d2d..8bb9c39 100644
--- a/libqdutils/mdp_version.h
+++ b/libqdutils/mdp_version.h
@@ -140,6 +140,7 @@
unsigned long getLowBw() { return mLowBw; }
unsigned long getHighBw() { return mHighBw; }
bool isSrcSplit() const;
+ bool isSrcSplitAlways() const;
bool isRGBScalarSupported() const;
bool is8x26();
bool is8x74v2();
@@ -170,6 +171,8 @@
unsigned long mLowBw; //kbps
unsigned long mHighBw; //kbps
bool mSourceSplit;
+ //Additional property on top of source split
+ bool mSourceSplitAlways;
bool mRGBHasNoScalar;
};
}; //namespace qdutils
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index 02f7341..5c9acf7 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -51,6 +51,7 @@
GET_DISPLAY_VISIBLE_REGION, // Get the visibleRegion for dpy
PAUSE_WFD, // Pause/Resume WFD
SET_WFD_STATUS, // Set if wfd connection is on/off
+ SET_VIEW_FRAME, // Set view frame of display
COMMAND_LIST_END = 400,
};