Merge "hwc: Avoid MDP draw if prepare is not successful."
diff --git a/common.mk b/common.mk
index 01cdd3f..774050e 100644
--- a/common.mk
+++ b/common.mk
@@ -28,7 +28,7 @@
endif
ifeq ($(call is-board-platform-in-list, msm8974 msm8226 msm8610 apq8084 \
- mpq8092 msm_bronze msm8916), true)
+ mpq8092 msm_bronze msm8916 msm8994), true)
common_flags += -DVENUS_COLOR_FORMAT
common_flags += -DMDSS_TARGET
endif
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index 77c9922..7255391 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -181,6 +181,7 @@
} else {
switch (format)
{
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
case HAL_PIXEL_FORMAT_RAW_SENSOR:
aligned_w = ALIGN(width, 32);
@@ -189,7 +190,6 @@
aligned_w = ALIGN(width, 128);
break;
case HAL_PIXEL_FORMAT_YCbCr_420_SP:
- case HAL_PIXEL_FORMAT_YCrCb_420_SP:
case HAL_PIXEL_FORMAT_YV12:
case HAL_PIXEL_FORMAT_YCbCr_422_SP:
case HAL_PIXEL_FORMAT_YCrCb_422_SP:
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 1a1bd9e..0331864 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -160,9 +160,10 @@
}
}
- if((property_get("debug.mdpcomp.4k2kSplit", property, "0") > 0) &&
- (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
- (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+ if(!qdutils::MDPVersion::getInstance().isSrcSplit() &&
+ property_get("persist.mdpcomp.4k2kSplit", property, "0") > 0 &&
+ (!strncmp(property, "1", PROPERTY_VALUE_MAX) ||
+ !strncasecmp(property,"true", PROPERTY_VALUE_MAX))) {
sEnable4k2kYUVSplit = true;
}
@@ -1675,22 +1676,29 @@
//=============MDPCompNonSplit==================================================
void MDPCompNonSplit::adjustForSourceSplit(hwc_context_t *ctx,
- hwc_display_contents_1_t*) {
- //As we split 4kx2k yuv layer and program to 2 VG pipes
- //(if available) increase mdpcount accordingly
- mCurrentFrame.mdpCount += ctx->listStats[mDpy].yuv4k2kCount;
-
+ hwc_display_contents_1_t* list) {
//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;
+ for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
+ index++) {
+ if(!mCurrentFrame.isFBComposed[index]) {
+ if(mdpNextZOrder == mCurrentFrame.fbZ) {
+ mdpNextZOrder++;
+ }
+ mdpNextZOrder++;
+ hwc_layer_1_t* layer = &list->hwLayers[index];
+ private_handle_t *hnd = (private_handle_t *)layer->handle;
+ if(is4kx2kYuvBuffer(hnd)) {
+ if(mdpNextZOrder <= mCurrentFrame.fbZ)
+ mCurrentFrame.fbZ += 1;
+ mdpNextZOrder++;
+ //As we split 4kx2k yuv layer and program to 2 VG pipes
+ //(if available) increase mdpcount by 1.
+ mCurrentFrame.mdpCount++;
+ }
}
}
}
@@ -1889,17 +1897,27 @@
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
- int n4k2kYuvCount = ctx->listStats[mDpy].yuv4k2kCount;
const int lSplit = getLeftSplit(ctx, mDpy);
- for(int index = 0; index < n4k2kYuvCount; index++){
- 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)) {
- mCurrentFrame.mdpCount += 1;
- }
- if(mCurrentFrame.fbZ >= n4k2kYuvIndex){
- mCurrentFrame.fbZ += 1;
+ if(mCurrentFrame.fbZ >= 0) {
+ for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
+ index++) {
+ if(!mCurrentFrame.isFBComposed[index]) {
+ if(mdpNextZOrder == mCurrentFrame.fbZ) {
+ mdpNextZOrder++;
+ }
+ mdpNextZOrder++;
+ hwc_layer_1_t* layer = &list->hwLayers[index];
+ private_handle_t *hnd = (private_handle_t *)layer->handle;
+ if(is4kx2kYuvBuffer(hnd)) {
+ hwc_rect_t dst = layer->displayFrame;
+ if((dst.left > lSplit) || (dst.right < lSplit)) {
+ mCurrentFrame.mdpCount += 1;
+ }
+ if(mdpNextZOrder <= mCurrentFrame.fbZ)
+ mCurrentFrame.fbZ += 1;
+ mdpNextZOrder++;
+ }
+ }
}
}
}
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 4708368..94a396c 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -83,7 +83,8 @@
(xres < MIN_DISPLAY_XRES || yres < MIN_DISPLAY_YRES));
}
-void changeResolution(hwc_context_t *ctx, int xres_orig, int yres_orig) {
+void changeResolution(hwc_context_t *ctx, int xres_orig, int yres_orig,
+ int width, int height) {
//Store original display resolution.
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres_new = xres_orig;
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres_new = yres_orig;
@@ -99,6 +100,12 @@
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres_new = xres_new;
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres_new = yres_new;
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].customFBSize = true;
+
+ //Caluculate DPI according to changed resolution.
+ float xdpi = ((float)xres_new * 25.4f) / (float)width;
+ float ydpi = ((float)yres_new * 25.4f) / (float)height;
+ ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xdpi = xdpi;
+ ctx->dpyAttr[HWC_DISPLAY_PRIMARY].ydpi = ydpi;
}
}
}
@@ -168,7 +175,7 @@
(uint32_t)(1000000000l / fps);
//To change resolution of primary display
- changeResolution(ctx, info.xres, info.yres);
+ changeResolution(ctx, info.xres, info.yres, info.width, info.height);
//Unblank primary on first boot
if(ioctl(fb_fd, FBIOBLANK,FB_BLANK_UNBLANK) < 0) {
@@ -2080,6 +2087,24 @@
return true;
}
+void dumpBuffer(private_handle_t *ohnd, char *bufferName) {
+ if (ohnd != NULL && ohnd->base) {
+ char dumpFilename[PATH_MAX];
+ bool bResult = false;
+ snprintf(dumpFilename, sizeof(dumpFilename), "/data/%s.%s.%dx%d.raw",
+ bufferName,
+ overlay::utils::getFormatString(utils::getMdpFormat(ohnd->format)),
+ getWidth(ohnd), getHeight(ohnd));
+ FILE* fp = fopen(dumpFilename, "w+");
+ if (NULL != fp) {
+ bResult = (bool) fwrite((void*)ohnd->base, ohnd->size, 1, fp);
+ fclose(fp);
+ }
+ ALOGD("Buffer[%s] Dump to %s: %s",
+ bufferName, dumpFilename, bResult ? "Success" : "Fail");
+ }
+}
+
bool isGLESComp(hwc_context_t *ctx,
hwc_display_contents_1_t* list) {
int numAppLayers = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index c7b7ded..5086d72 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -257,6 +257,7 @@
bool canUseMDPforVirtualDisplay(hwc_context_t* ctx,
const hwc_display_contents_1_t *list);
+void dumpBuffer(private_handle_t *ohnd, char *bufferName);
//Helper function to dump logs
void dumpsys_log(android::String8& buf, const char* fmt, ...);
diff --git a/libhwcomposer/hwc_virtual.cpp b/libhwcomposer/hwc_virtual.cpp
index adda35b..01c0873 100644
--- a/libhwcomposer/hwc_virtual.cpp
+++ b/libhwcomposer/hwc_virtual.cpp
@@ -29,6 +29,7 @@
#include "hwc_dump_layers.h"
#include "hwc_copybit.h"
#include "hwc_virtual.h"
+#include "sync/sync.h"
#define HWCVIRTUAL_LOG 0
@@ -48,6 +49,16 @@
}
}
+HWCVirtualVDS::HWCVirtualVDS() {
+ char value[PROPERTY_VALUE_MAX];
+ mVDSDumpEnabled = false;
+ if((property_get("debug.hwc.enable_vds_dump", value, NULL) > 0)) {
+ if(atoi(value) != 0) {
+ mVDSDumpEnabled = true;
+ }
+ }
+}
+
void HWCVirtualVDS::init(hwc_context_t *ctx) {
const int dpy = HWC_DISPLAY_VIRTUAL;
ctx->mFBUpdate[dpy] =
@@ -178,6 +189,10 @@
int fd = -1; //FenceFD from the Copybit
hwc_sync(ctx, list, dpy, fd);
+ // Dump the layers for virtual
+ if(ctx->mHwcDebug[dpy])
+ ctx->mHwcDebug[dpy]->dumpLayers(list);
+
if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
ALOGE("%s: MDPComp draw failed", __FUNCTION__);
ret = -1;
@@ -201,6 +216,19 @@
ret = -1;
}
+ if(mVDSDumpEnabled) {
+ char bufferName[128];
+ // Dumping frame buffer
+ sync_wait(fbLayer->acquireFenceFd, 1000);
+ snprintf(bufferName, sizeof(bufferName), "vds.fb");
+ dumpBuffer((private_handle_t *)fbLayer->handle, bufferName);
+ // Dumping WB output for non-secure session
+ if(!isSecureBuffer(ohnd)) {
+ sync_wait(list->retireFenceFd, 1000);
+ snprintf(bufferName, sizeof(bufferName), "vds.wb");
+ dumpBuffer(ohnd, bufferName);
+ }
+ }
} else if(list->outbufAcquireFenceFd >= 0) {
//If we dont handle the frame, set retireFenceFd to outbufFenceFd,
//which will make sure, the framework waits on it and closes it.
diff --git a/libhwcomposer/hwc_virtual.h b/libhwcomposer/hwc_virtual.h
index 87004c3..26d89c9 100644
--- a/libhwcomposer/hwc_virtual.h
+++ b/libhwcomposer/hwc_virtual.h
@@ -46,7 +46,7 @@
class HWCVirtualVDS : public HWCVirtualBase {
public:
- explicit HWCVirtualVDS(){};
+ explicit HWCVirtualVDS();
virtual ~HWCVirtualVDS(){};
// Chooses composition type and configures pipe for each layer in virtual
// display list
@@ -64,6 +64,12 @@
hwc_display_contents_1_t** displays);
virtual void pause(hwc_context_t* ctx, int dpy);
virtual void resume(hwc_context_t* ctx, int dpy);
+private:
+ // If WFD is enabled through VDS solution
+ // we can dump the frame buffer and WB
+ // output buffer by setting the property
+ // debug.hwc.enable_vds_dump
+ bool mVDSDumpEnabled;
};
class HWCVirtualV4L2 : public HWCVirtualBase {
diff --git a/liboverlay/overlayRotator.cpp b/liboverlay/overlayRotator.cpp
index 0e5b0ec..0671b62 100644
--- a/liboverlay/overlayRotator.cpp
+++ b/liboverlay/overlayRotator.cpp
@@ -145,7 +145,7 @@
//Return a rot object, creating one if necessary
overlay::Rotator *rot = NULL;
if(mUseCount >= MAX_ROT_SESS) {
- ALOGE("%s, MAX rotator sessions reached", __func__);
+ ALOGW("%s, MAX rotator sessions reached, request rejected", __func__);
} else {
if(mRot[mUseCount] == NULL)
mRot[mUseCount] = overlay::Rotator::getRotator();
diff --git a/liboverlay/overlayRotator.h b/liboverlay/overlayRotator.h
index 53c54e6..f7b44bd 100644
--- a/liboverlay/overlayRotator.h
+++ b/liboverlay/overlayRotator.h
@@ -210,9 +210,7 @@
// Holder of rotator objects. Manages lifetimes
class RotMgr {
public:
- //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 };
+ enum { MAX_ROT_SESS = 4 };
~RotMgr();
void configBegin();