Merge "display: Add support for dynamic refresh rate"
diff --git a/libexternal/external.cpp b/libexternal/external.cpp
index b0dbf2e..42e469c 100644
--- a/libexternal/external.cpp
+++ b/libexternal/external.cpp
@@ -581,14 +581,14 @@
// Always set dpyAttr res to mVInfo res
mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].xres = width;
mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].yres = height;
- mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].mDownScaleMode = false;
+ mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].mMDPScalingMode = false;
if(mHwcContext->mOverlay->isUIScalingOnExternalSupported()
&& mHwcContext->mMDPDownscaleEnabled) {
int priW = mHwcContext->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
int priH = mHwcContext->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
// if primary resolution is more than the hdmi resolution
- // configure dpy attr to primary resolution and set
- // downscale mode
+ // configure dpy attr to primary resolution and set MDP
+ // scaling mode.
// Restrict this upto 1080p resolution max, if target does not
// support source split feature.
if((priW * priH) > (width * height) &&
@@ -632,16 +632,17 @@
mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].xres = alignedExtW;
mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].yres = alignedExtH;
// Set External Display MDP Downscale mode indicator
- mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].mDownScaleMode =true;
+ mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].mMDPScalingMode
+ = true;
}
}
ALOGD_IF(DEBUG_MDPDOWNSCALE, "Selected external resolution [%d X %d] "
- "maxMDPDownScale %d MDPDownScaleMode %d srcSplitEnabled %d "
+ "maxMDPDownScale %d mMDPScalingMode %d srcSplitEnabled %d "
"MDPDownscale feature %d",
mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].xres,
mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].yres,
qdutils::MDPVersion::getInstance().getMaxMDPDownscale(),
- mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].mDownScaleMode,
+ mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].mMDPScalingMode,
qdutils::MDPVersion::getInstance().isSrcSplit(),
mHwcContext->mMDPDownscaleEnabled);
//Initialize the display viewFrame info
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index 099a82e..ae1389d 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -44,7 +44,7 @@
using namespace overlay;
#define VSYNC_DEBUG 0
-#define BLANK_DEBUG 1
+#define POWER_MODE_DEBUG 1
static int hwc_device_open(const struct hw_module_t* module,
const char* name,
@@ -138,7 +138,8 @@
if (canUseRotator(ctx, dpy) &&
(has90Transform(layer) || getRotDownscale(ctx, layer))
&& isRotationDoable(ctx, hnd)) {
- if(not ctx->mOverlay->isDMAMultiplexingSupported()) {
+ if(not (ctx->mOverlay->isDMAMultiplexingSupported() &&
+ dpy)) {
if(ctx->mOverlay->isPipeTypeAttached(
overlay::utils::OV_MDP_PIPE_DMA))
ctx->isPaddingRound = true;
@@ -395,80 +396,86 @@
return ret;
}
-static int hwc_blank(struct hwc_composer_device_1* dev, int dpy, int blank)
+static int hwc_setPowerMode(struct hwc_composer_device_1* dev, int dpy,
+ int mode)
{
ATRACE_CALL();
hwc_context_t* ctx = (hwc_context_t*)(dev);
-
- Locker::Autolock _l(ctx->mDrawLock);
int ret = 0, value = 0;
- ALOGD_IF(BLANK_DEBUG, "%s: %s display: %d", __FUNCTION__,
- blank==1 ? "Blanking":"Unblanking", dpy);
- if(blank) {
- // free up all the overlay pipes in use
- // when we get a blank for either display
- // makes sure that all pipes are freed
- ctx->mOverlay->configBegin();
- ctx->mOverlay->configDone();
- ctx->mRotMgr->clear();
- // If VDS is connected, do not clear WB object as it
- // will end up detaching IOMMU. This is required
- // to send black frame to WFD sink on power suspend.
- // Note: With this change, we keep the WriteBack object
- // alive on power suspend for AD use case.
+ Locker::Autolock _l(ctx->mDrawLock);
+ ALOGD_IF(POWER_MODE_DEBUG, "%s: Setting mode %d on display: %d",
+ __FUNCTION__, mode, dpy);
+
+ switch(mode) {
+ case HWC_POWER_MODE_OFF:
+ // free up all the overlay pipes in use
+ // when we get a blank for either display
+ // makes sure that all pipes are freed
+ ctx->mOverlay->configBegin();
+ ctx->mOverlay->configDone();
+ ctx->mRotMgr->clear();
+ // If VDS is connected, do not clear WB object as it
+ // will end up detaching IOMMU. This is required
+ // to send black frame to WFD sink on power suspend.
+ // Note: With this change, we keep the WriteBack object
+ // alive on power suspend for AD use case.
+ value = FB_BLANK_POWERDOWN;
+ break;
+ case HWC_POWER_MODE_DOZE:
+ case HWC_POWER_MODE_DOZE_SUSPEND:
+ value = FB_BLANK_VSYNC_SUSPEND;
+ break;
+ case HWC_POWER_MODE_NORMAL:
+ value = FB_BLANK_UNBLANK;
+ break;
}
+
switch(dpy) {
case HWC_DISPLAY_PRIMARY:
- value = blank ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK;
if(ioctl(ctx->dpyAttr[dpy].fd, FBIOBLANK, value) < 0 ) {
- ALOGE("%s: Failed to handle blank event(%d) for Primary!!",
- __FUNCTION__, blank );
- return -1;
+ ALOGE("%s: ioctl FBIOBLANK failed for Primary with error %s"
+ " value %d", __FUNCTION__, strerror(errno), value);
+ return -errno;
}
- if(!blank) {
- // Enable HPD here, as during bootup unblank is called
+ if(mode == HWC_POWER_MODE_NORMAL) {
+ // Enable HPD here, as during bootup POWER_MODE_NORMAL is set
// when SF is completely initialized
ctx->mExtDisplay->setHPD(1);
}
- ctx->dpyAttr[dpy].isActive = !blank;
-
+ ctx->dpyAttr[dpy].isActive = not(mode == HWC_POWER_MODE_OFF);
+ //Deliberate fall through since there is no explicit power mode for
+ //virtual displays.
case HWC_DISPLAY_VIRTUAL:
- /* Display hal has received unblank call on HWC_DISPLAY_PRIMARY
- and since SF is not aware of VIRTUAL DISPLAY being handle by HWC,
- it wont send blank / unblank events for it. We piggyback on
- PRIMARY DISPLAY events to release mdp pipes and
- activate/deactivate VIRTUAL DISPLAY.
- */
-
if(ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected) {
- if(blank and (!ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isPause)) {
- int dpy = HWC_DISPLAY_VIRTUAL;
+ const int dpy = HWC_DISPLAY_VIRTUAL;
+ if(mode == HWC_POWER_MODE_OFF and
+ (not ctx->dpyAttr[dpy].isPause)) {
if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
- ALOGE("%s: display commit fail for virtual!", __FUNCTION__);
+ ALOGE("%s: displayCommit failed for virtual", __FUNCTION__);
ret = -1;
}
}
- ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isActive = !blank;
+ ctx->dpyAttr[dpy].isActive = not(mode == HWC_POWER_MODE_OFF);
}
break;
case HWC_DISPLAY_EXTERNAL:
- if(blank) {
+ if(mode == HWC_POWER_MODE_OFF) {
if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
- ALOGE("%s: display commit fail for external!", __FUNCTION__);
+ ALOGE("%s: displayCommit failed for external", __FUNCTION__);
ret = -1;
}
}
- ctx->dpyAttr[dpy].isActive = !blank;
+ ctx->dpyAttr[dpy].isActive = not(mode == HWC_POWER_MODE_OFF);
break;
default:
return -EINVAL;
}
- ALOGD_IF(BLANK_DEBUG, "%s: Done %s display: %d", __FUNCTION__,
- blank ? "blanking":"unblanking", dpy);
+ ALOGD_IF(POWER_MODE_DEBUG, "%s: Done setting mode %d on display %d",
+ __FUNCTION__, mode, dpy);
return ret;
}
@@ -483,18 +490,18 @@
return;
}
- ALOGD("%s: calling BLANK DISPLAY", __FUNCTION__);
- ret = hwc_blank(dev, HWC_DISPLAY_PRIMARY, 1);
+ ALOGD("%s: setting power mode off", __FUNCTION__);
+ ret = hwc_setPowerMode(dev, HWC_DISPLAY_PRIMARY, HWC_POWER_MODE_OFF);
if (ret < 0) {
ALOGE("%s: FBIOBLANK failed to BLANK: %s", __FUNCTION__,
- strerror(errno));
+ strerror(errno));
}
- ALOGD("%s: calling UNBLANK DISPLAY and enabling vsync", __FUNCTION__);
- ret = hwc_blank(dev, HWC_DISPLAY_PRIMARY, 0);
+ ALOGD("%s: setting power mode normal and enabling vsync", __FUNCTION__);
+ ret = hwc_setPowerMode(dev, HWC_DISPLAY_PRIMARY, HWC_POWER_MODE_NORMAL);
if (ret < 0) {
ALOGE("%s: FBIOBLANK failed to UNBLANK : %s", __FUNCTION__,
- strerror(errno));
+ strerror(errno));
}
hwc_vsync_control(ctx, HWC_DISPLAY_PRIMARY, 1);
@@ -700,8 +707,8 @@
uint32_t* configs, size_t* numConfigs) {
int ret = 0;
hwc_context_t* ctx = (hwc_context_t*)(dev);
- //in 1.1 there is no way to choose a config, report as config id # 0
- //This config is passed to getDisplayAttributes. Ignore for now.
+ //Currently we allow only 1 config, reported as config id # 0
+ //This config is passed in to getDisplayAttributes. Ignored for now.
switch(disp) {
case HWC_DISPLAY_PRIMARY:
if(*numConfigs > 0) {
@@ -812,6 +819,17 @@
strlcpy(buff, aBuf.string(), buff_len);
}
+int hwc_getActiveConfig(struct hwc_composer_device_1* /*dev*/, int /*disp*/) {
+ //Supports only the default config (0th index) for now
+ return 0;
+}
+
+int hwc_setActiveConfig(struct hwc_composer_device_1* /*dev*/, int /*disp*/,
+ int index) {
+ //Supports only the default config (0th index) for now
+ return (index == 0) ? index : -EINVAL;
+}
+
static int hwc_device_close(struct hw_device_t *dev)
{
if(!dev) {
@@ -841,18 +859,20 @@
//Setup HWC methods
dev->device.common.tag = HARDWARE_DEVICE_TAG;
- dev->device.common.version = HWC_DEVICE_API_VERSION_1_3;
+ dev->device.common.version = HWC_DEVICE_API_VERSION_1_4;
dev->device.common.module = const_cast<hw_module_t*>(module);
dev->device.common.close = hwc_device_close;
dev->device.prepare = hwc_prepare;
dev->device.set = hwc_set;
dev->device.eventControl = hwc_eventControl;
- dev->device.blank = hwc_blank;
+ dev->device.setPowerMode = hwc_setPowerMode;
dev->device.query = hwc_query;
dev->device.registerProcs = hwc_registerProcs;
dev->device.dump = hwc_dump;
dev->device.getDisplayConfigs = hwc_getDisplayConfigs;
dev->device.getDisplayAttributes = hwc_getDisplayAttributes;
+ dev->device.getActiveConfig = hwc_getActiveConfig;
+ dev->device.setActiveConfig = hwc_setActiveConfig;
*device = &dev->device.common;
status = 0;
}
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index d5139f4..7839139 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -182,11 +182,11 @@
// Do not use getNonWormholeRegion() function to calculate the
// sourceCrop during animation on external display and
// Dont do wormhole calculation when extorientation is set on External
- // Dont do wormhole calculation when extDownscale is enabled on External
+ // Dont do wormhole calculation when scaling mode is set on External
if(ctx->listStats[mDpy].isDisplayAnimating && mDpy) {
sourceCrop = layer->displayFrame;
} else if((mDpy && !extOrient
- && !ctx->dpyAttr[mDpy].mDownScaleMode)) {
+ && !ctx->dpyAttr[mDpy].mMDPScalingMode)) {
if(ctx->mOverlay->isUIScalingOnExternalSupported() &&
!ctx->dpyAttr[mDpy].customFBSize) {
getNonWormholeRegion(list, sourceCrop);
@@ -307,11 +307,11 @@
// Do not use getNonWormholeRegion() function to calculate the
// sourceCrop during animation on external display and
// Dont do wormhole calculation when extorientation is set on External
- // Dont do wormhole calculation when extDownscale is enabled on External
+ // Dont do wormhole calculation when scaling mode is set on External
if(ctx->listStats[mDpy].isDisplayAnimating && mDpy) {
sourceCrop = layer->displayFrame;
} else if((mDpy && !extOrient
- && !ctx->dpyAttr[mDpy].mDownScaleMode)) {
+ && !ctx->dpyAttr[mDpy].mMDPScalingMode)) {
if(!qdutils::MDPVersion::getInstance().is8x26() &&
!ctx->dpyAttr[mDpy].customFBSize) {
getNonWormholeRegion(list, sourceCrop);
@@ -473,11 +473,11 @@
// Do not use getNonWormholeRegion() function to calculate the
// sourceCrop during animation on external display and
// Dont do wormhole calculation when extorientation is set on External
- // Dont do wormhole calculation when extDownscale is enabled on External
+ // Dont do wormhole calculation when scaling mode is set on External
if(ctx->listStats[mDpy].isDisplayAnimating && mDpy) {
sourceCrop = layer->displayFrame;
} else if((mDpy && !extOrient
- && !ctx->dpyAttr[mDpy].mDownScaleMode)) {
+ && !ctx->dpyAttr[mDpy].mMDPScalingMode)) {
if(!qdutils::MDPVersion::getInstance().is8x26() &&
!ctx->dpyAttr[mDpy].customFBSize) {
getNonWormholeRegion(list, sourceCrop);
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 552beae..08cfbde 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -723,9 +723,9 @@
return false;
}
- // check for action safe flag and downscale mode which requires scaling.
+ // check for action safe flag and MDP scaling mode which requires scaling.
if(ctx->dpyAttr[mDpy].mActionSafePresent
- || ctx->dpyAttr[mDpy].mDownScaleMode) {
+ || ctx->dpyAttr[mDpy].mMDPScalingMode) {
ALOGD_IF(isDebug(), "%s: Scaling needed for this frame",__FUNCTION__);
return false;
}
diff --git a/libhwcomposer/hwc_uevents.cpp b/libhwcomposer/hwc_uevents.cpp
index 7061991..c535c5e 100644
--- a/libhwcomposer/hwc_uevents.cpp
+++ b/libhwcomposer/hwc_uevents.cpp
@@ -129,6 +129,8 @@
clear(ctx, dpy);
ctx->dpyAttr[dpy].connected = false;
ctx->dpyAttr[dpy].isActive = false;
+ /* If disconnect comes before any composition cycle */
+ ctx->dpyAttr[dpy].isConfiguring = false;
ctx->mExtDisplay->teardown();
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index d0b3567..a11baa9 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -228,9 +228,9 @@
ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected = false;
ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isActive = false;
ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected = false;
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].mDownScaleMode= false;
- ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].mDownScaleMode = false;
- ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].mDownScaleMode = false;
+ ctx->dpyAttr[HWC_DISPLAY_PRIMARY].mMDPScalingMode= false;
+ ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].mMDPScalingMode = false;
+ ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].mMDPScalingMode = false;
ctx->mMDPComp[HWC_DISPLAY_PRIMARY] =
MDPComp::getObject(ctx, HWC_DISPLAY_PRIMARY);
@@ -447,8 +447,8 @@
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
+ if(ctx->dpyAttr[dpy].mMDPScalingMode) {
+ // if MDP scaling mode is enabled for external, need to query
// the actual width and height, as that is the physical w & h
ctx->mExtDisplay->getAttributes(fbWidth, fbHeight);
}
@@ -579,9 +579,17 @@
outPos.x, outPos.y,
outPos.w, outPos.h);
}
- if(ctx->dpyAttr[dpy].mDownScaleMode) {
- int extW, extH;
- ctx->mExtDisplay->getAttributes(extW, extH);
+ if(ctx->dpyAttr[dpy].mMDPScalingMode) {
+ int extW = 0, extH = 0;
+ if(dpy == HWC_DISPLAY_EXTERNAL) {
+ ctx->mExtDisplay->getAttributes(extW, extH);
+ } else if(dpy == HWC_DISPLAY_VIRTUAL) {
+ extW = ctx->mHWCVirtual->getScalingWidth();
+ extH = ctx->mHWCVirtual->getScalingHeight();
+ }
+ ALOGD_IF(HWC_UTILS_DEBUG, "%s: Scaling mode extW=%d extH=%d",
+ __FUNCTION__, extW, extH);
+
fbWidth = (float)ctx->dpyAttr[dpy].xres;
fbHeight = (float)ctx->dpyAttr[dpy].yres;
//Calculate the position...
@@ -652,14 +660,22 @@
displayFrame.bottom = dstHeight;
}
}
- if(ctx->dpyAttr[dpy].mDownScaleMode) {
- int extW, extH;
- // if downscale is enabled, map the co-ordinates to new
+ if(ctx->dpyAttr[dpy].mMDPScalingMode) {
+ int extW = 0, extH = 0;
+ // if MDP scaling mode is enabled, map the co-ordinates to new
// domain(downscaled)
float fbWidth = (float)ctx->dpyAttr[dpy].xres;
float fbHeight = (float)ctx->dpyAttr[dpy].yres;
// query MDP configured attributes
- ctx->mExtDisplay->getAttributes(extW, extH);
+ if(dpy == HWC_DISPLAY_EXTERNAL) {
+ ctx->mExtDisplay->getAttributes(extW, extH);
+ } else if(dpy == HWC_DISPLAY_VIRTUAL) {
+ extW = ctx->mHWCVirtual->getScalingWidth();
+ extH = ctx->mHWCVirtual->getScalingHeight();
+ }
+ ALOGD_IF(HWC_UTILS_DEBUG, "%s: Scaling mode extW=%d extH=%d",
+ __FUNCTION__, extW, extH);
+
//Calculate the ratio...
float wRatio = ((float)extW)/fbWidth;
float hRatio = ((float)extH)/fbHeight;
@@ -675,7 +691,7 @@
displayFrame.right, displayFrame.bottom);
}
}else {
- if(extOrient || ctx->dpyAttr[dpy].mDownScaleMode) {
+ if(extOrient || ctx->dpyAttr[dpy].mMDPScalingMode) {
getAspectRatioPosition(ctx, dpy, extOrient,
displayFrame, displayFrame);
}
@@ -1867,7 +1883,7 @@
whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
}
- /* Calculate the external display position based on MDP downscale,
+ /* Calculate the external display position based on MDP scaling mode,
ActionSafe, and extorientation features. */
calcExtDisplayPosition(ctx, hnd, dpy, crop, dst, transform, orient);
int downscale = getRotDownscale(ctx, layer);
@@ -2161,13 +2177,19 @@
if (ohnd != NULL && ohnd->base) {
char dumpFilename[PATH_MAX];
bool bResult = false;
+ int width = getWidth(ohnd);
+ int height = getHeight(ohnd);
+ int format = ohnd->format;
+ //dummy aligned w & h.
+ int alW = 0, alH = 0;
+ int size = getBufferSizeAndDimensions(width, height, format, alW, alH);
snprintf(dumpFilename, sizeof(dumpFilename), "/data/%s.%s.%dx%d.raw",
bufferName,
- overlay::utils::getFormatString(utils::getMdpFormat(ohnd->format)),
- getWidth(ohnd), getHeight(ohnd));
+ overlay::utils::getFormatString(utils::getMdpFormat(format)),
+ width, height);
FILE* fp = fopen(dumpFilename, "w+");
if (NULL != fp) {
- bResult = (bool) fwrite((void*)ohnd->base, ohnd->size, 1, fp);
+ bResult = (bool) fwrite((void*)ohnd->base, size, 1, fp);
fclose(fp);
}
ALOGD("Buffer[%s] Dump to %s: %s",
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 9d1e7c0..f7885b8 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -99,8 +99,8 @@
// To trigger padding round to clean up mdp
// pipes
bool isConfiguring;
- // External Display is in MDP Downscale mode indicator
- bool mDownScaleMode;
+ // Indicates whether external/virtual display is in MDP scaling mode
+ bool mMDPScalingMode;
// Ext dst Rect
hwc_rect_t mDstRect;
//Action safe attributes
@@ -451,21 +451,17 @@
}
static inline int getWidth(const private_handle_t* hnd) {
- if(isYuvBuffer(hnd)) {
- MetaData_t *metadata = reinterpret_cast<MetaData_t*>(hnd->base_metadata);
- if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
- return metadata->bufferDim.sliceWidth;
- }
+ MetaData_t *metadata = reinterpret_cast<MetaData_t*>(hnd->base_metadata);
+ if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
+ return metadata->bufferDim.sliceWidth;
}
return hnd->width;
}
static inline int getHeight(const private_handle_t* hnd) {
- if(isYuvBuffer(hnd)) {
- MetaData_t *metadata = reinterpret_cast<MetaData_t*>(hnd->base_metadata);
- if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
- return metadata->bufferDim.sliceHeight;
- }
+ MetaData_t *metadata = reinterpret_cast<MetaData_t*>(hnd->base_metadata);
+ if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
+ return metadata->bufferDim.sliceHeight;
}
return hnd->height;
}
diff --git a/libhwcomposer/hwc_virtual.cpp b/libhwcomposer/hwc_virtual.cpp
index b1dde9d..146d671 100644
--- a/libhwcomposer/hwc_virtual.cpp
+++ b/libhwcomposer/hwc_virtual.cpp
@@ -40,6 +40,7 @@
void HWCVirtualVDS::init(hwc_context_t *ctx) {
const int dpy = HWC_DISPLAY_VIRTUAL;
+ mScalingWidth = 0, mScalingHeight = 0;
ctx->mFBUpdate[dpy] =
IFBUpdate::getObject(ctx, dpy);
ctx->mMDPComp[dpy] = MDPComp::getObject(ctx, dpy);
@@ -106,8 +107,14 @@
ctx->dpyAttr[dpy].isConfiguring = false;
ctx->dpyAttr[dpy].fd = Writeback::getInstance()->getFbFd();
private_handle_t *ohnd = (private_handle_t *)list->outbuf;
- Writeback::getInstance()->configureDpyInfo(ohnd->width,
- ohnd->height);
+
+ setMDPScalingMode(ctx, ohnd, dpy);
+
+ mScalingWidth = getWidth(ohnd);
+ mScalingHeight = getHeight(ohnd);
+
+ Writeback::getInstance()->configureDpyInfo(mScalingWidth,
+ mScalingHeight);
setListStats(ctx, list, dpy);
if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
@@ -258,3 +265,20 @@
}
return;
}
+
+/* We set scaling mode on the VD if the output handle width and height
+ differs from the virtual frame buffer width and height. */
+void HWCVirtualVDS::setMDPScalingMode(hwc_context_t* ctx,
+ private_handle_t* ohnd, int dpy) {
+ bool scalingMode = false;
+ int fbWidth = ctx->dpyAttr[dpy].xres;
+ int fbHeight = ctx->dpyAttr[dpy].yres;
+ if((getWidth(ohnd) != fbWidth) || (getHeight(ohnd) != fbHeight)) {
+ scalingMode = true;
+ }
+ ctx->dpyAttr[dpy].mMDPScalingMode = scalingMode;
+
+ ALOGD_IF(HWCVIRTUAL_LOG, "%s fb(%dx%d) outputBuffer(%dx%d) scalingMode=%d",
+ __FUNCTION__, fbWidth, fbHeight,
+ getWidth(ohnd), getHeight(ohnd), scalingMode);
+}
diff --git a/libhwcomposer/hwc_virtual.h b/libhwcomposer/hwc_virtual.h
index 5ca99f7..525ae2a 100644
--- a/libhwcomposer/hwc_virtual.h
+++ b/libhwcomposer/hwc_virtual.h
@@ -45,12 +45,21 @@
hwc_display_contents_1_t** displays);
void pause(hwc_context_t* ctx, int dpy);
void resume(hwc_context_t* ctx, int dpy);
+ int getScalingHeight() const { return mScalingHeight; };
+ int getScalingWidth() const { return mScalingWidth; };
// We can dump the frame buffer and WB
// output buffer by dynamically enabling
// dumping via a binder call:
// adb shell service call display.qservice 15 i32 3 i32 1
static bool sVDDumpEnabled;
static void dynamicDebug(bool enable) {sVDDumpEnabled = enable;};
+
+private:
+ // These variables store the resolution that WB is being configured to
+ // in the current draw cycle.
+ int mScalingWidth, mScalingHeight;
+ void setMDPScalingMode(hwc_context_t* ctx,
+ private_handle_t* ohnd, int dpy);
};
}; //namespace
diff --git a/libmemtrack/kgsl.c b/libmemtrack/kgsl.c
index b644d73..208b22f 100644
--- a/libmemtrack/kgsl.c
+++ b/libmemtrack/kgsl.c
@@ -49,6 +49,7 @@
FILE *fp;
char line[1024];
char tmp[128];
+ bool is_surfaceflinger = false;
size_t accounted_size = 0;
size_t unaccounted_size = 0;
unsigned long smaps_addr = 0;
@@ -60,6 +61,16 @@
return 0;
}
+ snprintf(tmp, sizeof(tmp), "/proc/%d/cmdline", pid);
+ fp = fopen(tmp, "r");
+ if (fp != NULL) {
+ if (fgets(line, sizeof(line), fp)) {
+ if (strcmp(line, "/system/bin/surfaceflinger") == 0)
+ is_surfaceflinger = true;
+ }
+ fclose(fp);
+ }
+
memcpy(records, record_templates,
sizeof(struct memtrack_record) * allocated_records);
@@ -77,6 +88,7 @@
unsigned long size;
char line_type[7];
char flags[7];
+ char line_usage[19];
int ret;
if (fgets(line, sizeof(line), fp) == NULL) {
@@ -87,9 +99,9 @@
* gpuaddr useraddr size id flags type usage sglen
* 545ba000 545ba000 4096 1 ----pY gpumem arraybuffer 1
*/
- ret = sscanf(line, "%*x %*x %lu %*d %6s %6s %*s %*d\n",
- &size, flags, line_type);
- if (ret != 3) {
+ ret = sscanf(line, "%*x %*lx %lu %*d %6s %6s %18s %*d\n",
+ &size, flags, line_type, line_usage);
+ if (ret != 4) {
continue;
}
@@ -101,7 +113,9 @@
unaccounted_size += size;
} else if (type == MEMTRACK_TYPE_GRAPHICS && strcmp(line_type, "ion") == 0) {
- unaccounted_size += size;
+ if (!is_surfaceflinger || strcmp(line_usage, "egl_image") != 0) {
+ unaccounted_size += size;
+ }
}
}
diff --git a/liboverlay/overlayWriteback.cpp b/liboverlay/overlayWriteback.cpp
index de18e55..ed42a9f 100644
--- a/liboverlay/overlayWriteback.cpp
+++ b/liboverlay/overlayWriteback.cpp
@@ -263,9 +263,12 @@
bool Writeback::getDump(char *buf, size_t len) {
if(sWb) {
utils::getDump(buf, len, "WBData", sWb->mFbData);
- char str[4] = {'\0'};
- snprintf(str, 4, "\n");
- strlcat(buf, str, len);
+ char outputBufferInfo[256];
+ snprintf(outputBufferInfo, sizeof(outputBufferInfo),
+ "OutputBuffer xres=%d yres=%d format=%s\n\n",
+ sWb->getWidth(), sWb->getHeight(),
+ utils::getFormatString(sWb->getOutputFormat()));
+ strlcat(buf, outputBufferInfo, len);
return true;
}
return false;
diff --git a/liboverlay/overlayWriteback.h b/liboverlay/overlayWriteback.h
index ebd319f..21186e6 100644
--- a/liboverlay/overlayWriteback.h
+++ b/liboverlay/overlayWriteback.h
@@ -81,6 +81,8 @@
bool queueBuffer(int opFd, uint32_t opOffset);
uint32_t getOffset() const { return mWbMem.getOffset(); }
int getDstFd() const { return mWbMem.getDstFd(); }
+ int getWidth() const { return mXres; }
+ int getHeight() const { return mYres; }
/* Subject to GC if writeback isnt used for a drawing round.
* Get always if caching the value.
*/