Merge "hwc: Dynamic Resolution support on Primary"
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index 8048f32..b45a7cd 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -105,17 +105,27 @@
//Helper
static void reset(hwc_context_t *ctx, int numDisplays,
hwc_display_contents_1_t** displays) {
+
+ ctx->numActiveDisplays = 0;
for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
hwc_display_contents_1_t *list = displays[i];
// XXX:SurfaceFlinger no longer guarantees that this
// value is reset on every prepare. However, for the layer
// cache we need to reset it.
// We can probably rethink that later on
- if (LIKELY(list && list->numHwLayers > 1)) {
+ if (LIKELY(list && list->numHwLayers > 0)) {
for(uint32_t j = 0; j < list->numHwLayers; j++) {
if(list->hwLayers[j].compositionType != HWC_FRAMEBUFFER_TARGET)
list->hwLayers[j].compositionType = HWC_FRAMEBUFFER;
}
+
+ /* For display devices like SSD and screenrecord, we cannot
+ * rely on isActive and connected attributes of dpyAttr to
+ * determine if the displaydevice is active. Hence in case if
+ * the layer-list is non-null and numHwLayers > 0, we assume
+ * the display device to be active.
+ */
+ ctx->numActiveDisplays += 1;
}
if(ctx->mFBUpdate[i])
@@ -124,6 +134,7 @@
ctx->mCopyBit[i]->reset();
if(ctx->mLayerRotMap[i])
ctx->mLayerRotMap[i]->reset();
+
}
ctx->mAD->reset();
@@ -242,7 +253,7 @@
ctx->mRotMgr->configBegin();
overlay::Writeback::configBegin();
- for (int32_t i = numDisplays; i >= 0; i--) {
+ for (int32_t i = (numDisplays-1); i >= 0; i--) {
hwc_display_contents_1_t *list = displays[i];
int dpy = getDpyforExternalDisplay(ctx, i);
switch(dpy) {
@@ -574,7 +585,7 @@
{
int ret = 0;
hwc_context_t* ctx = (hwc_context_t*)(dev);
- for (uint32_t i = 0; i <= numDisplays; i++) {
+ for (uint32_t i = 0; i < numDisplays; i++) {
hwc_display_contents_1_t* list = displays[i];
int dpy = getDpyforExternalDisplay(ctx, i);
switch(dpy) {
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index e84b345..0d89c79 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -451,6 +451,7 @@
if(!isValidRect(visibleRect)) {
mCurrentFrame.drop[i] = true;
mCurrentFrame.dropCount++;
+ continue;
}
const hwc_layer_1_t* layer = &list->hwLayers[i];
@@ -472,17 +473,17 @@
}else {
/* Reset frame ROI when any layer which needs scaling also needs ROI
* cropping */
- if((res_w != dst_w || res_h != dst_h) &&
- needsScaling (layer)) {
+ if((res_w != dst_w || res_h != dst_h) && needsScaling (layer)) {
ALOGI("%s: Resetting ROI due to scaling", __FUNCTION__);
memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
mCurrentFrame.dropCount = 0;
return false;
}
- }
- if (layer->blending == HWC_BLENDING_NONE)
- visibleRect = deductRect(visibleRect, res);
+ /* deduct any opaque region from visibleRect */
+ if (layer->blending == HWC_BLENDING_NONE)
+ visibleRect = deductRect(visibleRect, res);
+ }
}
return true;
}
@@ -1628,7 +1629,7 @@
/* reset Invalidator */
if(idleInvalidator && !sIdleFallBack && mCurrentFrame.mdpCount)
- idleInvalidator->markForSleep();
+ idleInvalidator->handleUpdateEvent();
overlay::Overlay& ov = *ctx->mOverlay;
LayerProp *layerProp = ctx->layerProp[mDpy];
@@ -1975,7 +1976,7 @@
/* reset Invalidator */
if(idleInvalidator && !sIdleFallBack && mCurrentFrame.mdpCount)
- idleInvalidator->markForSleep();
+ idleInvalidator->handleUpdateEvent();
overlay::Overlay& ov = *ctx->mOverlay;
LayerProp *layerProp = ctx->layerProp[mDpy];
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index dce1e0e..ececa70 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -219,6 +219,7 @@
ctx->vstate.enable = false;
ctx->vstate.fakevsync = false;
ctx->mExtOrientation = 0;
+ ctx->numActiveDisplays = 1;
//Right now hwc starts the service but anybody could do it, or it could be
//independent process as well.
@@ -464,8 +465,8 @@
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);
+ wRatio = (float)inPos.w/(float)(viewFrame.right - viewFrame.left);
+ hRatio = (float)inPos.h/(float)(viewFrame.bottom - viewFrame.top);
//Calculate the position...
@@ -1351,6 +1352,10 @@
ovutils::OV_MDP_BLEND_FG_PREMULT);
}
+ if (layer->flags & HWC_VPU_PIPE) {
+ ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_VPU_PIPE);
+ }
+
if(isYuvBuffer(hnd)) {
if(isSecureBuffer(hnd)) {
ovutils::setMdpFlags(mdpFlags,
@@ -1938,6 +1943,32 @@
ctx->layerProp[dpy] = new LayerProp[numAppLayers];
}
+/* Since we fake non-Hybrid WFD solution as external display, this
+ * function helps us in determining the priority between external
+ * (hdmi/non-Hybrid WFD display) and virtual display devices(SSD/
+ * screenrecord). This can be removed once wfd-client migrates to
+ * using virtual-display api's.
+ */
+bool canUseMDPforVirtualDisplay(hwc_context_t* ctx,
+ const hwc_display_contents_1_t *list) {
+
+ /* We rely on the fact that for pure virtual display solution
+ * list->outbuf will be a non-NULL handle.
+ *
+ * If there are three active displays (which means there is one
+ * primary, one external and one virtual active display)
+ * we give mdss/mdp hw resources(pipes,smp,etc) for external
+ * display(hdmi/non-Hybrid WFD display) rather than for virtual
+ * display(SSD/screenrecord)
+ */
+
+ if(list->outbuf and (ctx->numActiveDisplays == HWC_NUM_DISPLAY_TYPES)) {
+ return false;
+ }
+
+ return true;
+}
+
void BwcPM::setBwc(hwc_context_t *ctx, const hwc_rect_t& crop,
const hwc_rect_t& dst, const int& transform,
ovutils::eMdpFlags& mdpFlags) {
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 22debaf..9ccfa1b 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -151,6 +151,7 @@
enum {
HWC_COLOR_FILL = 0x00000008,
HWC_FORMAT_RB_SWAP = 0x00000040,
+ HWC_VPU_PIPE = 0x00000200,
};
class LayerRotMap {
@@ -234,6 +235,9 @@
bool isGLESOnlyComp(hwc_context_t *ctx, const int& dpy);
void reset_layer_prop(hwc_context_t* ctx, int dpy, int numAppLayers);
+bool canUseMDPforVirtualDisplay(hwc_context_t* ctx,
+ const hwc_display_contents_1_t *list);
+
//Helper function to dump logs
void dumpsys_log(android::String8& buf, const char* fmt, ...);
@@ -495,15 +499,14 @@
int mExtOrientation;
//Flags the transition of a video session
bool mVideoTransFlag;
-
//Used for SideSync feature
//which overrides the mExtOrientation
bool mBufferMirrorMode;
-
qhwc::LayerRotMap *mLayerRotMap[HWC_NUM_DISPLAY_TYPES];
-
// Panel reset flag will be set if BTA check fails
bool mPanelResetStatus;
+ // number of active Displays
+ int numActiveDisplays;
};
namespace qhwc {
diff --git a/libhwcomposer/hwc_virtual.cpp b/libhwcomposer/hwc_virtual.cpp
index 51ade32..600ba8d 100644
--- a/libhwcomposer/hwc_virtual.cpp
+++ b/libhwcomposer/hwc_virtual.cpp
@@ -67,9 +67,7 @@
int dpy = HWC_DISPLAY_VIRTUAL;
//Cleanup virtual display objs, since there is no explicit disconnect
- if(ctx->dpyAttr[dpy].connected &&
- (numDisplays <= HWC_NUM_PHYSICAL_DISPLAY_TYPES ||
- displays[dpy] == NULL)) {
+ if(ctx->dpyAttr[dpy].connected && (displays[dpy] == NULL)) {
ctx->dpyAttr[dpy].connected = false;
if(ctx->mFBUpdate[dpy]) {
@@ -132,8 +130,11 @@
if(fbLayer->handle && !isSecondaryConfiguring(ctx) &&
!ctx->mMDPComp[dpy]->isGLESOnlyComp()) {
private_handle_t *ohnd = (private_handle_t *)list->outbuf;
+ int format = ohnd->format;
+ if (format == HAL_PIXEL_FORMAT_RGBA_8888)
+ format = HAL_PIXEL_FORMAT_RGBX_8888;
Writeback::getInstance()->setOutputFormat(
- utils::getMdpFormat(ohnd->format));
+ utils::getMdpFormat(format));
int fd = -1; //FenceFD from the Copybit
hwc_sync(ctx, list, dpy, fd);
@@ -180,7 +181,8 @@
if (LIKELY(list && list->numHwLayers > 1) &&
ctx->dpyAttr[dpy].isActive &&
- ctx->dpyAttr[dpy].connected) {
+ ctx->dpyAttr[dpy].connected &&
+ canUseMDPforVirtualDisplay(ctx,list)) {
reset_layer_prop(ctx, dpy, list->numHwLayers - 1);
if(!ctx->dpyAttr[dpy].isPause) {
ctx->dpyAttr[dpy].isConfiguring = false;
@@ -211,7 +213,8 @@
if (LIKELY(list) && ctx->dpyAttr[dpy].isActive &&
ctx->dpyAttr[dpy].connected &&
- !ctx->dpyAttr[dpy].isPause) {
+ (!ctx->dpyAttr[dpy].isPause) &&
+ canUseMDPforVirtualDisplay(ctx,list)) {
uint32_t last = list->numHwLayers - 1;
hwc_layer_1_t *fbLayer = &list->hwLayers[last];
int fd = -1; //FenceFD from the Copybit(valid in async mode)
diff --git a/libmemtrack/memtrack_msm.c b/libmemtrack/memtrack_msm.c
index 6626b89..ac93f44 100644
--- a/libmemtrack/memtrack_msm.c
+++ b/libmemtrack/memtrack_msm.c
@@ -27,7 +27,7 @@
int msm_memtrack_get_memory(const struct memtrack_module *module,
pid_t pid,
- enum memtrack_type type,
+ int type,
struct memtrack_record *records,
size_t *num_records)
{
diff --git a/liboverlay/overlayUtils.h b/liboverlay/overlayUtils.h
index 33802e5..24fba33 100644
--- a/liboverlay/overlayUtils.h
+++ b/liboverlay/overlayUtils.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+* Copyright (c) 2011-2014, 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
@@ -272,6 +272,7 @@
OV_MDSS_MDP_BWC_EN = MDP_BWC_EN,
OV_MDSS_MDP_DUAL_PIPE = MDSS_MDP_DUAL_PIPE,
OV_MDP_SOLID_FILL = MDP_SOLID_FILL,
+ OV_MDP_VPU_PIPE = MDP_VPU_PIPE,
};
enum eZorder {
diff --git a/libqdutils/idle_invalidator.cpp b/libqdutils/idle_invalidator.cpp
index 97176a4..b53f1a3 100644
--- a/libqdutils/idle_invalidator.cpp
+++ b/libqdutils/idle_invalidator.cpp
@@ -54,16 +54,43 @@
}
bool IdleInvalidator::threadLoop() {
+ struct timeval lastUpdateTime;
ALOGD_IF(II_DEBUG, "%s", __func__);
- usleep(mSleepTime * 500);
+
+ {
+ //If we are here, update(s) happened, i.e mSleepAgain is set
+ Locker::Autolock _l(mLock);
+ mSleepAgain = false;
+ lastUpdateTime = mLastUpdateTime;
+ }
+
+ struct timeval currentTime;
+ gettimeofday(¤tTime, NULL);
+ int timeSinceUpdateUs = (currentTime.tv_sec - lastUpdateTime.tv_sec) *
+ 1000000 + (currentTime.tv_usec - lastUpdateTime.tv_usec);
+ int sleepDurationUs = mSleepTime * 1000 - timeSinceUpdateUs;
+
+ //Sleep only if the duration required is > 1ms, otherwise its not worth it.
+ if(sleepDurationUs > 1000) {
+ usleep(sleepDurationUs);
+ ALOGD_IF(II_DEBUG, "Slept for %d ms", sleepDurationUs / 1000);
+ }
Locker::Autolock _l(mLock);
+ //If an update happened while we were asleep, sleep again
if(mSleepAgain) {
//We need to sleep again!
mSleepAgain = false;
return true;
}
+#if II_DEBUG
+ gettimeofday(¤tTime, NULL);
+ timeSinceUpdateUs = (currentTime.tv_sec - lastUpdateTime.tv_sec) *
+ 1000000 + (currentTime.tv_usec - lastUpdateTime.tv_usec);
+ ALOGD("Idle refresh after %dms", timeSinceUpdateUs / 1000);
+#endif
+
mHandler((void*)mHwcContext);
return false;
}
@@ -77,8 +104,9 @@
ALOGD_IF(II_DEBUG, "%s", __func__);
}
-void IdleInvalidator::markForSleep() {
+void IdleInvalidator::handleUpdateEvent() {
Locker::Autolock _l(mLock);
+ gettimeofday(&mLastUpdateTime, NULL);
mSleepAgain = true;
//Triggers the threadLoop to run, if not already running.
run(threadName, android::PRIORITY_AUDIO);
diff --git a/libqdutils/idle_invalidator.h b/libqdutils/idle_invalidator.h
index abd9b29..f41c15e 100644
--- a/libqdutils/idle_invalidator.h
+++ b/libqdutils/idle_invalidator.h
@@ -38,6 +38,7 @@
class IdleInvalidator : public android::Thread {
void *mHwcContext;
+ struct timeval mLastUpdateTime;
bool mSleepAgain;
unsigned int mSleepTime;
static InvalidatorHandler mHandler;
@@ -49,7 +50,7 @@
/* init timer obj */
int init(InvalidatorHandler reg_handler, void* user_data, unsigned int
idleSleepTime);
- void markForSleep();
+ void handleUpdateEvent();
/*Overrides*/
virtual bool threadLoop();
virtual int readyToRun();
diff --git a/libqdutils/profiler.cpp b/libqdutils/profiler.cpp
index 031fdc3..997c839 100644
--- a/libqdutils/profiler.cpp
+++ b/libqdutils/profiler.cpp
@@ -28,6 +28,9 @@
*/
#define LOG_NDDEBUG 0
+#define __STDC_FORMAT_MACROS 1
+#include <inttypes.h>
+
#include "profiler.h"
#ifdef DEBUG_CALC_FPS
@@ -104,7 +107,7 @@
debug_fps_metadata.curr_frame = 0;
ALOGD("period: %d", debug_fps_metadata.period);
- ALOGD("ignorethresh_us: %lld", debug_fps_metadata.ignorethresh_us);
+ ALOGD("ignorethresh_us: %"PRId64, debug_fps_metadata.ignorethresh_us);
}
void CalcFps::print_fps(float fps)
@@ -124,7 +127,7 @@
for (unsigned int i = 0;
i < ((debug_fps_metadata.framearrival_steps / 6) + 1);
i++) {
- ALOGD("%lld %lld %lld %lld %lld %lld",
+ ALOGD("%"PRId64" %"PRId64" %"PRId64" %"PRId64" %"PRId64" %"PRId64,
debug_fps_metadata.accum_framearrivals[i*6],
debug_fps_metadata.accum_framearrivals[i*6+1],
debug_fps_metadata.accum_framearrivals[i*6+2],
diff --git a/libqdutils/qd_utils.cpp b/libqdutils/qd_utils.cpp
index 5a457d0..0698b33 100644
--- a/libqdutils/qd_utils.cpp
+++ b/libqdutils/qd_utils.cpp
@@ -31,7 +31,6 @@
#define MAX_FRAME_BUFFER_NAME_SIZE (80)
-#define MAX_DISPLAY_DEVICES (3)
int getHDMINode(void)
{
@@ -40,7 +39,7 @@
char msmFbTypePath[MAX_FRAME_BUFFER_NAME_SIZE];
int j = 0;
- for(j = 0; j < MAX_DISPLAY_DEVICES; j++) {
+ for(j = 0; j < HWC_NUM_DISPLAY_TYPES; j++) {
snprintf (msmFbTypePath, sizeof(msmFbTypePath),
"/sys/class/graphics/fb%d/msm_fb_type", j);
displayDeviceFP = fopen(msmFbTypePath, "r");
@@ -58,7 +57,7 @@
}
}
- if (j < MAX_DISPLAY_DEVICES)
+ if (j < HWC_NUM_DISPLAY_TYPES)
return j;
else
ALOGE("%s: Failed to find HDMI node", __func__);
diff --git a/libqdutils/qd_utils.h b/libqdutils/qd_utils.h
index cca55d5..db6d367 100644
--- a/libqdutils/qd_utils.h
+++ b/libqdutils/qd_utils.h
@@ -42,6 +42,7 @@
#include <sys/poll.h>
#include <sys/resource.h>
#include <cutils/properties.h>
+#include <hardware/hwcomposer.h>
#define EDID_RAW_DATA_SIZE 640