Merge "hwc: Add msm8x09 version checks in HAL."
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index 582b102..67cca88 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -96,7 +96,7 @@
int fbWidth = ctx->dpyAttr[dpy].xres;
int fbHeight = ctx->dpyAttr[dpy].yres;
unsigned int fbArea = (fbWidth * fbHeight);
- unsigned int renderArea = getRGBRenderingArea(list);
+ unsigned int renderArea = getRGBRenderingArea(ctx, list);
ALOGD_IF (DEBUG_COPYBIT, "%s:renderArea %u, fbArea %u",
__FUNCTION__, renderArea, fbArea);
if (renderArea < (mDynThreshold * fbArea)) {
@@ -112,8 +112,8 @@
return false;
}
-unsigned int CopyBit::getRGBRenderingArea
- (const hwc_display_contents_1_t *list) {
+unsigned int CopyBit::getRGBRenderingArea (const hwc_context_t *ctx,
+ const hwc_display_contents_1_t *list) {
//Calculates total rendering area for RGB layers
unsigned int renderArea = 0;
unsigned int w=0, h=0;
@@ -122,7 +122,7 @@
for (unsigned int i=0; i<list->numHwLayers -1; i++) {
private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle;
if (hnd) {
- if (BUFFER_TYPE_UI == hnd->bufferType) {
+ if (BUFFER_TYPE_UI == hnd->bufferType && !ctx->copybitDrop[i]) {
getLayerResolution(&list->hwLayers[i], w, h);
renderArea += (w*h);
}
@@ -316,6 +316,9 @@
for (int i = ctx->listStats[dpy].numAppLayers-1; i >= 0 ; i--) {
int dst_h, dst_w, src_h, src_w;
float dx, dy;
+ if(ctx->copybitDrop[i]) {
+ continue;
+ }
hwc_layer_1_t *layer = (hwc_layer_1_t *) &list->hwLayers[i];
if (layer->planeAlpha != 0xFF)
return true;
@@ -544,6 +547,9 @@
ALOGD_IF(DEBUG_COPYBIT, "%s: Not Marked for copybit", __FUNCTION__);
continue;
}
+ if(ctx->copybitDrop[i]) {
+ continue;
+ }
//skip non updating layers
if((mDirtyLayerIndex != -1) && (mDirtyLayerIndex != i) )
continue;
diff --git a/libhwcomposer/hwc_copybit.h b/libhwcomposer/hwc_copybit.h
index 99a39c8..a7ce43e 100644
--- a/libhwcomposer/hwc_copybit.h
+++ b/libhwcomposer/hwc_copybit.h
@@ -101,8 +101,8 @@
// flag that indicates whether CopyBit composition is enabled for this cycle
bool mCopyBitDraw;
- unsigned int getRGBRenderingArea
- (const hwc_display_contents_1_t *list);
+ unsigned int getRGBRenderingArea (const hwc_context_t *ctx,
+ const hwc_display_contents_1_t *list);
void getLayerResolution(const hwc_layer_1_t* layer,
unsigned int &width, unsigned int& height);
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 82d1f05..e24925a 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -36,7 +36,7 @@
//==============MDPComp========================================================
-IdleInvalidator *MDPComp::idleInvalidator = NULL;
+IdleInvalidator *MDPComp::sIdleInvalidator = NULL;
bool MDPComp::sIdleFallBack = false;
bool MDPComp::sHandleTimeout = false;
bool MDPComp::sDebugLogs = false;
@@ -46,6 +46,7 @@
int MDPComp::sMaxPipesPerMixer = MAX_PIPES_PER_MIXER;
bool MDPComp::sEnableYUVsplit = false;
bool MDPComp::sSrcSplitEnabled = false;
+bool MDPComp::enablePartialUpdateForMDP3 = false;
MDPComp* MDPComp::getObject(hwc_context_t *ctx, const int& dpy) {
if(qdutils::MDPVersion::getInstance().isSrcSplit()) {
sSrcSplitEnabled = true;
@@ -110,7 +111,7 @@
return false;
}
- char property[PROPERTY_VALUE_MAX];
+ char property[PROPERTY_VALUE_MAX] = {0};
sEnabled = false;
if((property_get("persist.hwc.mdpcomp.enable", property, NULL) > 0) &&
@@ -134,23 +135,10 @@
}
if(ctx->mMDP.panel != MIPI_CMD_PANEL) {
- // Idle invalidation is not necessary on command mode panels
- long idle_timeout = DEFAULT_IDLE_TIME;
- if(property_get("debug.mdpcomp.idletime", property, NULL) > 0) {
- if(atoi(property) != 0)
- idle_timeout = atoi(property);
- }
-
- //create Idle Invalidator only when not disabled through property
- if(idle_timeout != -1)
- idleInvalidator = IdleInvalidator::getInstance();
-
- if(idleInvalidator == NULL) {
- ALOGE("%s: failed to instantiate idleInvalidator object",
- __FUNCTION__);
- } else {
- idleInvalidator->init(timeout_handler, ctx,
- (unsigned int)idle_timeout);
+ sIdleInvalidator = IdleInvalidator::getInstance();
+ if(sIdleInvalidator->init(timeout_handler, ctx) < 0) {
+ delete sIdleInvalidator;
+ sIdleInvalidator = NULL;
}
}
@@ -162,13 +150,32 @@
sEnableYUVsplit = true;
}
- if ((property_get("persist.hwc.ptor.enable", property, NULL) > 0) &&
- ((!strncasecmp(property, "true", PROPERTY_VALUE_MAX )) ||
- (!strncmp(property, "1", PROPERTY_VALUE_MAX )))) {
+ bool defaultPTOR = false;
+ //Enable PTOR when "persist.hwc.ptor.enable" is not defined for
+ //8x16 and 8x39 targets by default
+ if((property_get("persist.hwc.ptor.enable", property, NULL) <= 0) &&
+ (qdutils::MDPVersion::getInstance().is8x16() ||
+ qdutils::MDPVersion::getInstance().is8x39())) {
+ defaultPTOR = true;
+ }
+
+ if (defaultPTOR || (!strncasecmp(property, "true", PROPERTY_VALUE_MAX)) ||
+ (!strncmp(property, "1", PROPERTY_VALUE_MAX ))) {
ctx->mCopyBit[HWC_DISPLAY_PRIMARY] = new CopyBit(ctx,
HWC_DISPLAY_PRIMARY);
}
+ if((property_get("persist.mdp3.partialUpdate", property, NULL) <= 0) &&
+ (ctx->mMDP.version == qdutils::MDP_V3_0_5)) {
+ enablePartialUpdateForMDP3 = true;
+ }
+
+ if(!enablePartialUpdateForMDP3 &&
+ (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
+ (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+ enablePartialUpdateForMDP3 = true;
+ }
+
return true;
}
@@ -206,6 +213,25 @@
ctx->proc->invalidate(ctx->proc);
}
+void MDPComp::setIdleTimeout(const uint32_t& timeout) {
+ enum { ONE_REFRESH_PERIOD_MS = 17, ONE_BILLION_MS = 1000000000 };
+
+ if(sIdleInvalidator) {
+ if(timeout <= ONE_REFRESH_PERIOD_MS) {
+ //If the specified timeout is < 1 draw cycle worth, "virtually"
+ //disable idle timeout. The ideal way for clients to disable
+ //timeout is to set it to 0
+ sIdleInvalidator->setIdleTimeout(ONE_BILLION_MS);
+ ALOGI("Disabled idle timeout");
+ return;
+ }
+ sIdleInvalidator->setIdleTimeout(timeout);
+ ALOGI("Idle timeout set to %u", timeout);
+ } else {
+ ALOGW("Cannot set idle timeout, IdleInvalidator not enabled");
+ }
+}
+
void MDPComp::setMDPCompLayerFlags(hwc_context_t *ctx,
hwc_display_contents_1_t* list) {
LayerProp *layerProp = ctx->layerProp[mDpy];
@@ -684,9 +710,11 @@
const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
int priDispW = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
- // No Idle fall back, if secure display or secure RGB layers are present
+ // No Idle fall back, if secure display or secure RGB layers are present or
+ // if there's only a single layer being composed
if(sIdleFallBack && (!ctx->listStats[mDpy].secureUI &&
- !ctx->listStats[mDpy].secureRGBCount)) {
+ !ctx->listStats[mDpy].secureRGBCount) &&
+ (ctx->listStats[mDpy].numAppLayers != 1)) {
ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
return false;
}
@@ -1862,6 +1890,13 @@
"MDP Composition Strategies Failed");
}
} else {
+ if ((ctx->mMDP.version == qdutils::MDP_V3_0_5) && ctx->mCopyBit[mDpy] &&
+ enablePartialUpdateForMDP3) {
+ generateROI(ctx, list);
+ for(int i = 0; i < ctx->listStats[mDpy].numAppLayers; i++) {
+ ctx->copybitDrop[i] = mCurrentFrame.drop[i];
+ }
+ }
ALOGD_IF( isDebug(),"%s: MDP Comp not possible for this frame",
__FUNCTION__);
ret = -1;
@@ -2055,7 +2090,7 @@
}
// Set the Handle timeout to true for MDP or MIXED composition.
- if(idleInvalidator && !sIdleFallBack && mCurrentFrame.mdpCount) {
+ if(sIdleInvalidator && !sIdleFallBack && mCurrentFrame.mdpCount) {
sHandleTimeout = true;
}
@@ -2310,7 +2345,7 @@
}
// Set the Handle timeout to true for MDP or MIXED composition.
- if(idleInvalidator && !sIdleFallBack && mCurrentFrame.mdpCount) {
+ if(sIdleInvalidator && !sIdleFallBack && mCurrentFrame.mdpCount) {
sHandleTimeout = true;
}
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index e43c4f4..3ed9186 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -25,7 +25,6 @@
#include <cutils/properties.h>
#include <overlay.h>
-#define DEFAULT_IDLE_TIME 70
#define MAX_PIPES_PER_MIXER 4
namespace overlay {
@@ -57,6 +56,7 @@
static void resetIdleFallBack() { sIdleFallBack = false; }
static bool isIdleFallback() { return sIdleFallBack; }
static void dynamicDebug(bool enable){ sDebugLogs = enable; }
+ static void setIdleTimeout(const uint32_t& timeout);
protected:
enum { MAX_SEC_LAYERS = 1 }; //TODO add property support
@@ -255,13 +255,15 @@
static bool sHandleTimeout;
static int sMaxPipesPerMixer;
static bool sSrcSplitEnabled;
- static IdleInvalidator *idleInvalidator;
+ static IdleInvalidator *sIdleInvalidator;
struct FrameInfo mCurrentFrame;
struct LayerCache mCachedFrame;
//Enable 4kx2k yuv layer split
static bool sEnableYUVsplit;
bool mModeOn; // if prepare happened
bool allocSplitVGPipesfor4k2k(hwc_context_t *ctx, int index);
+ //Enable Partial Update for MDP3 targets
+ static bool enablePartialUpdateForMDP3;
};
class MDPCompNonSplit : public MDPComp {
diff --git a/libhwcomposer/hwc_qclient.cpp b/libhwcomposer/hwc_qclient.cpp
index 8490058..6bde3d2 100644
--- a/libhwcomposer/hwc_qclient.cpp
+++ b/libhwcomposer/hwc_qclient.cpp
@@ -245,6 +245,13 @@
}
}
+static void setIdleTimeout(hwc_context_t* ctx, const Parcel* inParcel) {
+ uint32_t timeout = (uint32_t)inParcel->readInt32();
+ ALOGD("%s :%u ms", __FUNCTION__, timeout);
+ Locker::Autolock _sl(ctx->mDrawLock);
+ MDPComp::setIdleTimeout(timeout);
+}
+
status_t QClient::notifyCallback(uint32_t command, const Parcel* inParcel,
Parcel* outParcel) {
status_t ret = NO_ERROR;
@@ -290,6 +297,9 @@
case IQService::DYNAMIC_DEBUG:
toggleDynamicDebug(mHwcContext, inParcel);
break;
+ case IQService::SET_IDLE_TIMEOUT:
+ setIdleTimeout(mHwcContext, inParcel);
+ break;
default:
ret = NO_ERROR;
}
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 52572b0..c409db4 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -43,6 +43,7 @@
#include "comptype.h"
#include "hwc_virtual.h"
#include "qd_utils.h"
+#include <sys/sysinfo.h>
using namespace qClient;
using namespace qService;
@@ -73,6 +74,11 @@
#endif
#endif
+#define PROP_DEFAULT_APPBUFFER "ro.sf.default_app_buffer"
+#define MAX_RAM_SIZE 512*1024*1024
+#define qHD_WIDTH 540
+
+
namespace qhwc {
//Std refresh rates for digital videos- 24p, 30p and 48p
@@ -232,6 +238,25 @@
return 0;
}
+static void changeDefaultAppBufferCount() {
+ struct sysinfo info;
+ unsigned long int ramSize = 0;
+ if (!sysinfo(&info)) {
+ ramSize = info.totalram ;
+ }
+ int fb_fd = -1;
+ struct fb_var_screeninfo sInfo ={0};
+ fb_fd = open("/dev/graphics/fb0", O_RDONLY);
+ if (fb_fd >=0) {
+ ioctl(fb_fd, FBIOGET_VSCREENINFO, &sInfo);
+ close(fb_fd);
+ }
+ if ((ramSize && ramSize < MAX_RAM_SIZE) &&
+ (sInfo.xres && sInfo.xres <= qHD_WIDTH )) {
+ property_set(PROP_DEFAULT_APPBUFFER, "2");
+ }
+}
+
void initContext(hwc_context_t *ctx)
{
openFramebufferDevice(ctx);
@@ -243,6 +268,10 @@
ctx->mOverlay = overlay::Overlay::getInstance();
ctx->mRotMgr = RotMgr::getInstance();
+ //default_app_buffer for ferrum
+ if (ctx->mMDP.version == qdutils::MDP_V3_0_5) {
+ changeDefaultAppBufferCount();
+ }
// Initialize composition objects for the primary display
initCompositionResources(ctx, HWC_DISPLAY_PRIMARY);
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index cae22f1..3d97319 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -596,6 +596,8 @@
qhwc::PtorInfo mPtorInfo;
//Running in Thermal burst mode
bool mThermalBurstMode;
+ //Layers out of ROI
+ bool copybitDrop[MAX_NUM_APP_LAYERS];
};
namespace qhwc {
diff --git a/libqdutils/idle_invalidator.cpp b/libqdutils/idle_invalidator.cpp
index 86191e9..5850ce5 100644
--- a/libqdutils/idle_invalidator.cpp
+++ b/libqdutils/idle_invalidator.cpp
@@ -47,10 +47,13 @@
ALOGD_IF(II_DEBUG, "IdleInvalidator::%s", __FUNCTION__);
}
-int IdleInvalidator::init(InvalidatorHandler reg_handler, void* user_data,
- unsigned int idleSleepTime) {
- ALOGD_IF(II_DEBUG, "IdleInvalidator::%s idleSleepTime %d",
- __FUNCTION__, idleSleepTime);
+IdleInvalidator::~IdleInvalidator() {
+ if(mTimeoutEventFd >= 0) {
+ close(mTimeoutEventFd);
+ }
+}
+
+int IdleInvalidator::init(InvalidatorHandler reg_handler, void* user_data) {
mHandler = reg_handler;
mHwcContext = user_data;
@@ -62,34 +65,47 @@
return -1;
}
- // Open a sysfs node to send the timeout value to driver.
- int fd = open(IDLE_TIME_PATH, O_WRONLY);
- if (fd < 0) {
- ALOGE ("%s:not able to open %s node %s",
- __FUNCTION__, IDLE_TIME_PATH, strerror(errno));
+ enum {DEFAULT_IDLE_TIME = 70}; //ms
+ if(not setIdleTimeout(DEFAULT_IDLE_TIME)) {
close(mTimeoutEventFd);
mTimeoutEventFd = -1;
return -1;
}
- char strSleepTime[64];
- snprintf(strSleepTime, sizeof(strSleepTime), "%d", idleSleepTime);
- // Notify driver about the timeout value
- ssize_t len = pwrite(fd, strSleepTime, strlen(strSleepTime), 0);
- if(len < -1) {
- ALOGE ("%s:not able to write into %s node %s",
- __FUNCTION__, IDLE_TIME_PATH, strerror(errno));
- close(mTimeoutEventFd);
- mTimeoutEventFd = -1;
- close(fd);
- return -1;
- }
- close(fd);
//Triggers the threadLoop to run, if not already running.
run(threadName, android::PRIORITY_LOWEST);
return 0;
}
+bool IdleInvalidator::setIdleTimeout(const uint32_t& timeout) {
+ ALOGD_IF(II_DEBUG, "IdleInvalidator::%s timeout %d",
+ __FUNCTION__, timeout);
+
+ // Open a sysfs node to send the timeout value to driver.
+ int fd = open(IDLE_TIME_PATH, O_WRONLY);
+
+ if (fd < 0) {
+ ALOGE ("%s:Unable to open %s node %s",
+ __FUNCTION__, IDLE_TIME_PATH, strerror(errno));
+ return false;
+ }
+
+ char strSleepTime[64];
+ snprintf(strSleepTime, sizeof(strSleepTime), "%d", timeout);
+
+ // Notify driver about the timeout value
+ ssize_t len = pwrite(fd, strSleepTime, strlen(strSleepTime), 0);
+ if(len < -1) {
+ ALOGE ("%s:Unable to write into %s node %s",
+ __FUNCTION__, IDLE_TIME_PATH, strerror(errno));
+ close(fd);
+ return false;
+ }
+
+ close(fd);
+ return true;
+}
+
bool IdleInvalidator::threadLoop() {
ALOGD_IF(II_DEBUG, "IdleInvalidator::%s", __FUNCTION__);
struct pollfd pFd;
diff --git a/libqdutils/idle_invalidator.h b/libqdutils/idle_invalidator.h
index a881c4b..52334a0 100644
--- a/libqdutils/idle_invalidator.h
+++ b/libqdutils/idle_invalidator.h
@@ -37,16 +37,18 @@
typedef void (*InvalidatorHandler)(void*);
class IdleInvalidator : public android::Thread {
+ IdleInvalidator();
void *mHwcContext;
int mTimeoutEventFd;
static InvalidatorHandler mHandler;
static android::sp<IdleInvalidator> sInstance;
- public:
- IdleInvalidator();
+public:
+ ~IdleInvalidator();
/* init timer obj */
- int init(InvalidatorHandler reg_handler, void* user_data, unsigned int
- idleSleepTime);
+ int init(InvalidatorHandler reg_handler, void* user_data);
+ bool setIdleTimeout(const uint32_t& timeout);
+
/*Overrides*/
virtual bool threadLoop();
virtual int readyToRun();
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index 30c064e..3be20f1 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -53,6 +53,7 @@
SET_WFD_STATUS, // Set if wfd connection is on/off
SET_VIEW_FRAME, // Set view frame of display
DYNAMIC_DEBUG, // Enable more logging on the fly
+ SET_IDLE_TIMEOUT, // Set idle timeout for GPU fallback
COMMAND_LIST_END = 400,
};