Merge "hwc: Handle idle fallback in corner cases"
diff --git a/common.mk b/common.mk
index a2283c4..cdac0fa 100644
--- a/common.mk
+++ b/common.mk
@@ -7,11 +7,6 @@
common_includes += $(LOCAL_PATH)/../libhdmi
common_includes += $(LOCAL_PATH)/../libqservice
-ifeq ($(TARGET_USES_POST_PROCESSING),true)
- common_flags += -DUSES_POST_PROCESSING
- common_includes += $(TARGET_OUT_HEADERS)/pp/inc
-endif
-
common_header_export_path := qcom/display
#Common libraries external to display HAL
@@ -21,6 +16,11 @@
common_flags := -DDEBUG_CALC_FPS -Wno-missing-field-initializers
common_flags += -Wconversion -Wall -Werror
+ifeq ($(TARGET_USES_POST_PROCESSING),true)
+ common_flags += -DUSES_POST_PROCESSING
+ common_includes += $(TARGET_OUT_HEADERS)/pp/inc
+endif
+
ifeq ($(ARCH_ARM_HAVE_NEON),true)
common_flags += -D__ARM_HAVE_NEON
endif
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index 4167ae2..cd6d565 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -292,6 +292,11 @@
if (usage & GRALLOC_USAGE_PRIVATE_MM_HEAP) {
ionFlags |= ION_HEAP(ION_CP_MM_HEAP_ID);
ionFlags |= ION_SECURE;
+#ifdef ION_FLAG_ALLOW_NON_CONTIG
+ if (!(usage & GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY)) {
+ ionFlags |= ION_FLAG_ALLOW_NON_CONTIG;
+ }
+#endif
} else {
// for targets/OEMs which do not need HW level protection
// do not set ion secure flag & MM heap. Fallback to IOMMU heap.
diff --git a/libgralloc/gpu.cpp b/libgralloc/gpu.cpp
index 9b98f1b..551f188 100644
--- a/libgralloc/gpu.cpp
+++ b/libgralloc/gpu.cpp
@@ -141,6 +141,14 @@
flags |= private_handle_t::PRIV_FLAGS_HW_TEXTURE;
}
+ if (usage & GRALLOC_USAGE_HW_RENDER) {
+ flags |= private_handle_t::PRIV_FLAGS_HW_RENDER;
+ }
+
+ if (usage & GRALLOC_USAGE_HW_FB) {
+ flags |= private_handle_t::PRIV_FLAGS_HW_FB;
+ }
+
if(usage & GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY) {
flags |= private_handle_t::PRIV_FLAGS_SECURE_DISPLAY;
}
diff --git a/libgralloc/gralloc_priv.h b/libgralloc/gralloc_priv.h
index d64914e..9e2a6cf 100644
--- a/libgralloc/gralloc_priv.h
+++ b/libgralloc/gralloc_priv.h
@@ -182,10 +182,9 @@
PRIV_FLAGS_NEEDS_FLUSH = 0x00000020,
// Uncached memory or no CPU writers
PRIV_FLAGS_DO_NOT_FLUSH = 0x00000040,
- PRIV_FLAGS_SW_LOCK = 0x00000080,
+ PRIV_FLAGS_HW_RENDER = 0x00000080,
PRIV_FLAGS_NONCONTIGUOUS_MEM = 0x00000100,
- // Set by HWC when storing the handle
- PRIV_FLAGS_HWC_LOCK = 0x00000200,
+ PRIV_FLAGS_HW_FB = 0x00000200,
PRIV_FLAGS_SECURE_BUFFER = 0x00000400,
// For explicit synchronization
PRIV_FLAGS_UNSYNCHRONIZED = 0x00000800,
diff --git a/libgralloc/ionalloc.cpp b/libgralloc/ionalloc.cpp
index 23e225d..91a930c 100644
--- a/libgralloc/ionalloc.cpp
+++ b/libgralloc/ionalloc.cpp
@@ -77,12 +77,18 @@
ionAllocData.len = data.size;
ionAllocData.align = data.align;
ionAllocData.heap_id_mask = data.flags & ~ION_SECURE;
+#ifdef ION_FLAG_ALLOW_NON_CONTIG
+ ionAllocData.heap_id_mask &= (data.flags & ~ION_FLAG_ALLOW_NON_CONTIG);
+#endif
ionAllocData.flags = data.uncached ? 0 : ION_FLAG_CACHED;
// ToDo: replace usage of alloc data structure with
// ionallocdata structure.
if (data.flags & ION_SECURE)
ionAllocData.flags |= ION_SECURE;
-
+#ifdef ION_FLAG_ALLOW_NON_CONTIG
+ if (data.flags & ION_FLAG_ALLOW_NON_CONTIG)
+ ionAllocData.flags |= ION_FLAG_ALLOW_NON_CONTIG;
+#endif
err = open_device();
if (err)
return err;
diff --git a/libgralloc/mapper.cpp b/libgralloc/mapper.cpp
index 943e64f..3053d47 100644
--- a/libgralloc/mapper.cpp
+++ b/libgralloc/mapper.cpp
@@ -238,11 +238,11 @@
}
if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION and
not useUncached(usage)) {
- bool nonCPUWriters = usage & (
- GRALLOC_USAGE_HW_RENDER |
- GRALLOC_USAGE_HW_FB |
- GRALLOC_USAGE_HW_VIDEO_ENCODER |
- GRALLOC_USAGE_HW_CAMERA_WRITE);
+ bool nonCPUWriters = hnd->flags & (
+ private_handle_t::PRIV_FLAGS_HW_RENDER |
+ private_handle_t::PRIV_FLAGS_HW_FB |
+ private_handle_t::PRIV_FLAGS_VIDEO_ENCODER |
+ private_handle_t::PRIV_FLAGS_CAMERA_WRITE);
//Invalidate if CPU reads in software and there are non-CPU
//writers. No need to do this for the metadata buffer as it is
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index c96eb1e..22b576e 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -475,10 +475,11 @@
return -errno;
}
- if(mode == HWC_POWER_MODE_NORMAL) {
+ if(mode == HWC_POWER_MODE_NORMAL && !ctx->mHPDEnabled) {
// Enable HPD here, as during bootup POWER_MODE_NORMAL is set
// when SF is completely initialized
ctx->mHDMIDisplay->setHPD(1);
+ ctx->mHPDEnabled = true;
}
ctx->dpyAttr[dpy].isActive = not(mode == HWC_POWER_MODE_OFF);
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 1c390ef..8e62b61 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -26,6 +26,7 @@
#include "hwc_ad.h"
#include <overlayRotator.h>
#include "hwc_copybit.h"
+#include "qd_utils.h"
using namespace overlay;
using namespace qdutils;
@@ -48,6 +49,7 @@
bool MDPComp::sSrcSplitEnabled = false;
int MDPComp::sMaxSecLayers = 1;
bool MDPComp::enablePartialUpdateForMDP3 = false;
+bool MDPComp::sIsPartialUpdateActive = true;
MDPComp* MDPComp::getObject(hwc_context_t *ctx, const int& dpy) {
if(qdutils::MDPVersion::getInstance().isSrcSplit()) {
sSrcSplitEnabled = true;
@@ -131,9 +133,7 @@
qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
- /* MDSS_MDP_STAGE_UNUSED and MDSS_MDP_STAGE_BASE are not available for MDP
- * composition. */
- sMaxPipesPerMixer = (int)mdpVersion.getBlendStages() - 2;
+ sMaxPipesPerMixer = (int)mdpVersion.getBlendStages();
if(property_get("persist.hwc.mdpcomp.maxpermixer", property, "-1") > 0) {
int val = atoi(property);
if(val >= 0)
@@ -192,6 +192,8 @@
enablePartialUpdateForMDP3 = true;
}
+ sIsPartialUpdateActive = getPartialUpdatePref(ctx);
+
return true;
}
@@ -231,7 +233,7 @@
void MDPComp::setMaxPipesPerMixer(const uint32_t value) {
qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
- uint32_t maxSupported = (int)mdpVersion.getBlendStages() - 2;
+ uint32_t maxSupported = (int)mdpVersion.getBlendStages();
if(value > maxSupported) {
ALOGW("%s: Input exceeds max value supported. Setting to"
"max value: %d", __FUNCTION__, maxSupported);
@@ -1264,7 +1266,7 @@
hwc_display_contents_1_t* list){
if(!qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() ||
isSkipPresent(ctx, mDpy) || (list->flags & HWC_GEOMETRY_CHANGED) ||
- mDpy ) {
+ !sIsPartialUpdateActive || mDpy ) {
return false;
}
if(ctx->listStats[mDpy].secureUI)
@@ -2753,5 +2755,49 @@
return 0;
}
+bool MDPComp::getPartialUpdatePref(hwc_context_t *ctx) {
+ Locker::Autolock _l(ctx->mDrawLock);
+ const int fbNum = Overlay::getFbForDpy(Overlay::DPY_PRIMARY);
+ char path[MAX_SYSFS_FILE_PATH];
+ snprintf (path, sizeof(path), "sys/class/graphics/fb%d/dyn_pu", fbNum);
+ int fd = open(path, O_RDONLY);
+ if(fd < 0) {
+ ALOGE("%s: Failed to open sysfd node: %s", __FUNCTION__, path);
+ return -1;
+ }
+ char value[4];
+ ssize_t size_read = read(fd, value, sizeof(value)-1);
+ if(size_read <= 0) {
+ ALOGE("%s: Failed to read sysfd node: %s", __FUNCTION__, path);
+ close(fd);
+ return -1;
+ }
+ close(fd);
+ value[size_read] = '\0';
+ return atoi(value);
+}
+
+int MDPComp::setPartialUpdatePref(hwc_context_t *ctx, bool enable) {
+ Locker::Autolock _l(ctx->mDrawLock);
+ const int fbNum = Overlay::getFbForDpy(Overlay::DPY_PRIMARY);
+ char path[MAX_SYSFS_FILE_PATH];
+ snprintf (path, sizeof(path), "sys/class/graphics/fb%d/dyn_pu", fbNum);
+ int fd = open(path, O_WRONLY);
+ if(fd < 0) {
+ ALOGE("%s: Failed to open sysfd node: %s", __FUNCTION__, path);
+ return -1;
+ }
+ char value[4];
+ snprintf(value, sizeof(value), "%d", (int)enable);
+ ssize_t ret = write(fd, value, strlen(value));
+ if(ret <= 0) {
+ ALOGE("%s: Failed to write to sysfd nodes: %s", __FUNCTION__, path);
+ close(fd);
+ return -1;
+ }
+ close(fd);
+ sIsPartialUpdateActive = enable;
+ return 0;
+}
}; //namespace
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index 8929c40..3ce4a64 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -56,7 +56,8 @@
static void dynamicDebug(bool enable){ sDebugLogs = enable; }
static void setIdleTimeout(const uint32_t& timeout);
static void setMaxPipesPerMixer(const uint32_t value);
-
+ static int setPartialUpdatePref(hwc_context_t *ctx, bool enable);
+ static bool getPartialUpdatePref(hwc_context_t *ctx);
protected:
enum ePipeType {
MDPCOMP_OV_RGB = ovutils::OV_MDP_PIPE_RGB,
@@ -257,6 +258,7 @@
static bool sSrcSplitEnabled;
static IdleInvalidator *sIdleInvalidator;
static int sMaxSecLayers;
+ static bool sIsPartialUpdateActive;
struct FrameInfo mCurrentFrame;
struct LayerCache mCachedFrame;
//Enable 4kx2k yuv layer split
diff --git a/libhwcomposer/hwc_qclient.cpp b/libhwcomposer/hwc_qclient.cpp
index b0ebb3a..add5dc8 100644
--- a/libhwcomposer/hwc_qclient.cpp
+++ b/libhwcomposer/hwc_qclient.cpp
@@ -306,6 +306,13 @@
}
}
+static status_t setPartialUpdatePref(hwc_context_t *ctx, uint32_t enable) {
+ ALOGD("%s: enable: %d", __FUNCTION__, enable);
+ if(qhwc::MDPComp::setPartialUpdatePref(ctx, (bool)enable) < 0)
+ return NO_INIT;
+ return NO_ERROR;
+}
+
status_t QClient::notifyCallback(uint32_t command, const Parcel* inParcel,
Parcel* outParcel) {
status_t ret = NO_ERROR;
@@ -353,6 +360,8 @@
break;
case IQService::SET_MAX_PIPES_PER_MIXER:
setMaxPipesPerMixer(mHwcContext, inParcel);
+ case IQService::SET_PARTIAL_UPDATE:
+ ret = setPartialUpdatePref(mHwcContext, inParcel->readInt32());
break;
case IQService::TOGGLE_BWC:
toggleBWC(mHwcContext, inParcel);
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index ace0017..bcac4be 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -413,6 +413,7 @@
}
memset(&(ctx->mPtorInfo), 0, sizeof(ctx->mPtorInfo));
+ ctx->mHPDEnabled = false;
ALOGI("Initializing Qualcomm Hardware Composer");
ALOGI("MDP version: %d", ctx->mMDP.version);
}
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 286ae22..29c0cc9 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -479,11 +479,6 @@
return (hnd && (private_handle_t::PRIV_FLAGS_TILE_RENDERED & hnd->flags));
}
-//Return true if buffer is marked locked
-static inline bool isBufferLocked(const private_handle_t* hnd) {
- return (hnd && (private_handle_t::PRIV_FLAGS_HWC_LOCK & hnd->flags));
-}
-
//Return true if the buffer is intended for Secure Display
static inline bool isSecureDisplayBuffer(const private_handle_t* hnd) {
return (hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY));
@@ -644,6 +639,8 @@
bool mBWCEnabled;
// Provides a way for OEM's to disable setting dynfps via metadata.
bool mUseMetaDataRefreshRate;
+ // Stores the hpd enabled status- avoids re-enabling HDP on suspend resume.
+ bool mHPDEnabled;
};
namespace qhwc {
diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp
index e9c0a13..c250919 100644
--- a/liboverlay/overlay.cpp
+++ b/liboverlay/overlay.cpp
@@ -47,6 +47,9 @@
initScalar();
setDMAMultiplexingSupported();
+#ifdef USES_POST_PROCESSING
+ initPostProc();
+#endif
}
Overlay::~Overlay() {
@@ -54,6 +57,9 @@
mPipeBook[i].destroy();
}
destroyScalar();
+#ifdef USES_POST_PROCESSING
+ destroyPostProc();
+#endif
}
void Overlay::configBegin() {
@@ -526,6 +532,23 @@
}
}
+void Overlay::initPostProc() {
+ sLibAblHandle = dlopen("libmm-abl.so", RTLD_NOW);
+ if (sLibAblHandle) {
+ *(void **)&sFnppParams = dlsym(sLibAblHandle,
+ "display_pp_compute_params");
+ } else {
+ ALOGE("%s: Not able to load libmm-abl.so", __FUNCTION__);
+ }
+}
+
+void Overlay::destroyPostProc() {
+ if (sLibAblHandle) {
+ dlclose(sLibAblHandle);
+ sLibAblHandle = NULL;
+ }
+}
+
void Overlay::PipeBook::init() {
mPipe = NULL;
mDisplay = DPY_UNUSED;
@@ -557,5 +580,9 @@
{utils::OV_MDP_PIPE_ANY};
void *Overlay::sLibScaleHandle = NULL;
int (*Overlay::sFnProgramScale)(struct mdp_overlay_list *) = NULL;
+/* Dynamically link ABL library */
+void *Overlay::sLibAblHandle = NULL;
+int (*Overlay::sFnppParams)(const struct compute_params *,
+ struct mdp_overlay_pp_params *) = NULL;
}; // namespace overlay
diff --git a/liboverlay/overlay.h b/liboverlay/overlay.h
index 665e23f..984b439 100644
--- a/liboverlay/overlay.h
+++ b/liboverlay/overlay.h
@@ -33,6 +33,9 @@
#include "overlayUtils.h"
#include "mdp_version.h"
#include "utils/threads.h"
+#ifdef USES_POST_PROCESSING
+#include "lib-postproc.h"
+#endif
struct MetaData_t;
@@ -186,6 +189,12 @@
/* Sets the pipe type RGB/VG/DMA*/
void setPipeType(utils::eDest pipeIndex, const utils::eMdpPipeType pType);
+ /* Dynamically link ABL library */
+ static void initPostProc();
+ static void destroyPostProc();
+ static int (*getFnPpParams())(const struct compute_params *,
+ struct mdp_overlay_pp_params *);
+
/* Just like a Facebook for pipes, but much less profile info */
struct PipeBook {
void init();
@@ -251,6 +260,10 @@
static bool sDMAMultiplexingSupported;
static void *sLibScaleHandle;
static int (*sFnProgramScale)(struct mdp_overlay_list *);
+ /* Dynamically link ABL library */
+ static void *sLibAblHandle;
+ static int (*sFnppParams)(const struct compute_params *,
+ struct mdp_overlay_pp_params *);
static bool sDebugPipeLifecycle;
friend class MdpCtrl;
@@ -345,6 +358,11 @@
return sFnProgramScale;
}
+inline int (*Overlay::getFnPpParams())(const struct compute_params *,
+ struct mdp_overlay_pp_params *) {
+ return sFnppParams;
+}
+
inline void Overlay::debugPipeLifecycle(const bool& enable) {
sDebugPipeLifecycle = enable;
}
diff --git a/liboverlay/overlayMdp.cpp b/liboverlay/overlayMdp.cpp
index 4cd52a7..3932c4c 100644
--- a/liboverlay/overlayMdp.cpp
+++ b/liboverlay/overlayMdp.cpp
@@ -21,6 +21,7 @@
#include "overlayMdp.h"
#include "mdp_version.h"
#include <overlay.h>
+#include <dlfcn.h>
#define HSIC_SETTINGS_DEBUG 0
@@ -263,7 +264,7 @@
}
if (needUpdate) {
- mParams.params.pa_params.hue = data.hsicData.hue;
+ mParams.params.pa_params.hue = (float)data.hsicData.hue;
mParams.params.pa_params.sat = data.hsicData.saturation;
mParams.params.pa_params.intensity = data.hsicData.intensity;
mParams.params.pa_params.contrast = data.hsicData.contrast;
@@ -333,7 +334,15 @@
}
if (needUpdate) {
- display_pp_compute_params(&mParams, &mOVInfo.overlay_pp_cfg);
+ int (*sFnppParams)(const struct compute_params *,
+ struct mdp_overlay_pp_params *) =
+ Overlay::getFnPpParams();
+ if(sFnppParams) {
+ int ret = sFnppParams(&mParams, &mOVInfo.overlay_pp_cfg);
+ if (ret) {
+ ALOGE("%s: Unable to set PP params", __FUNCTION__);
+ }
+ }
}
#endif
return true;
diff --git a/libqdutils/mdp_version.cpp b/libqdutils/mdp_version.cpp
index f8729a5..8ca0824 100644
--- a/libqdutils/mdp_version.cpp
+++ b/libqdutils/mdp_version.cpp
@@ -101,7 +101,7 @@
mSourceSplitAlways = false;
mRGBHasNoScalar = false;
mRotDownscale = false;
- mBlendStages = 6; //min no. of stages supported by MDP.
+ mBlendStages = 4; //min no. of stages supported by MDP.
// this is the default limit of mixer unless driver reports it.
// For resolutions beyond this, we use dual/split overlay pipes.
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index 683c93c..a935131 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -55,8 +55,9 @@
DYNAMIC_DEBUG = 15, // Enable more logging on the fly
SET_IDLE_TIMEOUT = 16, // Set idle timeout for GPU fallback
TOGGLE_BWC = 17, // Toggle BWC On/Off on targets that support
+ SET_PARTIAL_UPDATE = 18, // Preference on partial update feature
/* Enable/Disable/Set refresh rate dynamically */
- CONFIGURE_DYN_REFRESH_RATE = 18,
+ CONFIGURE_DYN_REFRESH_RATE = 19,
COMMAND_LIST_END = 400,
};
diff --git a/libqservice/QServiceUtils.h b/libqservice/QServiceUtils.h
index f53d140..5b61c8e 100644
--- a/libqservice/QServiceUtils.h
+++ b/libqservice/QServiceUtils.h
@@ -74,6 +74,10 @@
return sendSingleParam(qService::IQService::SCREEN_REFRESH, 1);
}
+inline android::status_t setPartialUpdate(uint32_t enable) {
+ return sendSingleParam(qService::IQService::SET_PARTIAL_UPDATE, enable);
+}
+
inline android::status_t setExtOrientation(uint32_t orientation) {
return sendSingleParam(qService::IQService::EXTERNAL_ORIENTATION,
orientation);