hwc: Add support for color mode switching
Add a ColorMode class to HWC to manage color modes and expose
them as display attributes to SurfaceFlinger
Change-Id: I1010096120db6aec61163a84390527f5a0a3645e
diff --git a/msm8994/libhwcomposer/Android.mk b/msm8994/libhwcomposer/Android.mk
index df3e464..293eb49 100644
--- a/msm8994/libhwcomposer/Android.mk
+++ b/msm8994/libhwcomposer/Android.mk
@@ -17,7 +17,8 @@
LOCAL_SHARED_LIBRARIES += libskia
endif #TARGET_USES_QCOM_BSP
-LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdhwcomposer\"
+LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdhwcomposer\" \
+ -std=c++11
#Enable Dynamic FPS if PHASE_OFFSET is not set
ifeq ($(VSYNC_EVENT_PHASE_OFFSET_NS),)
LOCAL_CFLAGS += -DDYNAMIC_FPS
diff --git a/msm8994/libhwcomposer/hwc.cpp b/msm8994/libhwcomposer/hwc.cpp
index 662a80e..64a147d 100644
--- a/msm8994/libhwcomposer/hwc.cpp
+++ b/msm8994/libhwcomposer/hwc.cpp
@@ -772,8 +772,15 @@
if (hotPluggable) {
ctx->mHDMIDisplay->getDisplayConfigs(configs, numConfigs);
} else {
- configs[0] = 0;
- *numConfigs = 1;
+ if(ctx->mColorMode->getNumModes() > 0) {
+ *numConfigs = ctx->mColorMode->getNumModes();
+ for (size_t i = 0; i < *numConfigs; i++)
+ configs[i] = (uint32_t) i;
+
+ } else {
+ configs[0] = 0;
+ *numConfigs = 1;
+ }
}
break;
case HWC_DISPLAY_EXTERNAL:
@@ -801,22 +808,6 @@
return -EINVAL;
}
- //From HWComposer
- static const uint32_t DISPLAY_ATTRIBUTES[] = {
- HWC_DISPLAY_VSYNC_PERIOD,
- HWC_DISPLAY_WIDTH,
- HWC_DISPLAY_HEIGHT,
- HWC_DISPLAY_DPI_X,
- HWC_DISPLAY_DPI_Y,
-#ifdef QCOM_BSP
- HWC_DISPLAY_SECURE,
-#endif
- HWC_DISPLAY_NO_ATTRIBUTE,
- };
-
- const size_t NUM_DISPLAY_ATTRIBUTES = (sizeof(DISPLAY_ATTRIBUTES) /
- sizeof(DISPLAY_ATTRIBUTES)[0]);
-
uint32_t xres = 0, yres = 0, refresh = 0;
int ret = 0;
if (hotPluggable) {
@@ -828,7 +819,7 @@
}
}
- for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) {
+ for (size_t i = 0; attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; i++) {
switch (attributes[i]) {
case HWC_DISPLAY_VSYNC_PERIOD:
values[i] =
@@ -857,11 +848,9 @@
case HWC_DISPLAY_DPI_Y:
values[i] = (int32_t) (ctx->dpyAttr[disp].ydpi*1000.0);
break;
-#ifdef QCOM_BSP
- case HWC_DISPLAY_SECURE:
- values[i] = (int32_t) (ctx->dpyAttr[disp].secure);
+ case HWC_DISPLAY_COLOR_TRANSFORM:
+ values[i] = ctx->mColorMode->getModeForIndex(config);
break;
-#endif
default:
ALOGE("Unknown display attribute %d",
attributes[i]);
@@ -914,7 +903,9 @@
// For use cases when primary panel is the default interface we only have
// the default config (0th index)
- if (!hotPluggable) {
+ if (!hotPluggable && HWC_DISPLAY_PRIMARY) {
+ return ctx->mColorMode->getActiveModeIndex();
+ } else if (isVirtualDisplay) {
return 0;
}
@@ -934,10 +925,12 @@
return -EINVAL;
}
- // For use cases when primary panel is the default interface we only have
- // the default config (0th index)
- if (!hotPluggable) {
- // Primary and virtual supports only the default config (0th index)
+ // For use cases when primary panel is the default interface we only switch
+ // color modes
+ if(!hotPluggable && disp == HWC_DISPLAY_PRIMARY) {
+ return ctx->mColorMode->applyModeByIndex(index);
+ } else if (isVirtualDisplay) {
+ // virtual supports only the default config (0th index)
return (index == 0) ? index : -EINVAL;
}
diff --git a/msm8994/libhwcomposer/hwc_qclient.cpp b/msm8994/libhwcomposer/hwc_qclient.cpp
index c2c09c6..6d05d38 100644
--- a/msm8994/libhwcomposer/hwc_qclient.cpp
+++ b/msm8994/libhwcomposer/hwc_qclient.cpp
@@ -340,25 +340,11 @@
}
static void applyModeById(hwc_context_t* ctx, int32_t modeId) {
- int (*applyMode)(int, int) = NULL;
- void *modeHandle = NULL;
-
- modeHandle = dlopen("libmm-qdcm.so", RTLD_NOW);
- if (modeHandle) {
- *(void **)&applyMode = dlsym(modeHandle, "applyModeById");
- if (applyMode) {
- int err = applyMode(modeId, HWC_DISPLAY_PRIMARY);
- if (err)
- ALOGD("%s: Not able to apply mode: %d", __FUNCTION__, modeId);
- else
- ctx->proc->invalidate(ctx->proc);
- } else {
- ALOGE("%s: No symbol applyModeById found", __FUNCTION__);
- }
- dlclose(modeHandle);
- } else {
- ALOGE("%s: Not able to load libmm-qdcm.so", __FUNCTION__);
- }
+ int err = ctx->mColorMode->applyModeByID(modeId);
+ if (err)
+ ALOGD("%s: Not able to apply mode: %d", __FUNCTION__, modeId);
+ else
+ ctx->proc->invalidate(ctx->proc);
}
status_t QClient::notifyCallback(uint32_t command, const Parcel* inParcel,
diff --git a/msm8994/libhwcomposer/hwc_utils.cpp b/msm8994/libhwcomposer/hwc_utils.cpp
index 35d1f1f..50c1536 100644
--- a/msm8994/libhwcomposer/hwc_utils.cpp
+++ b/msm8994/libhwcomposer/hwc_utils.cpp
@@ -418,6 +418,8 @@
memset(&(ctx->mPtorInfo), 0, sizeof(ctx->mPtorInfo));
ctx->mHPDEnabled = false;
+ ctx->mColorMode = new ColorMode();
+ ctx->mColorMode->init();
ALOGI("Initializing Qualcomm Hardware Composer");
ALOGI("MDP version: %d", ctx->mMDP.version);
}
@@ -472,7 +474,11 @@
ctx->mAD = NULL;
}
-
+ if(ctx->mColorMode) {
+ ctx->mColorMode->destroy();
+ delete ctx->mColorMode;
+ ctx->mColorMode = NULL;
+ }
}
//Helper to roundoff the refreshrates
@@ -2505,8 +2511,6 @@
void processBootAnimCompleted(hwc_context_t *ctx) {
char value[PROPERTY_VALUE_MAX];
int boot_finished = 0, ret = -1;
- int (*applyMode)(int) = NULL;
- void *modeHandle = NULL;
// Reading property set on boot finish in SF
property_get("service.bootanim.exit", value, "0");
@@ -2514,21 +2518,9 @@
if (!boot_finished)
return;
- modeHandle = dlopen("libmm-qdcm.so", RTLD_NOW);
- if (modeHandle) {
- *(void **)&applyMode = dlsym(modeHandle, "applyDefaults");
- if (applyMode) {
- ret = applyMode(HWC_DISPLAY_PRIMARY);
- if (ret)
- ALOGD("%s: Not able to apply default mode", __FUNCTION__);
- } else {
- ALOGE("%s: No symbol applyDefaults found", __FUNCTION__);
- }
- dlclose(modeHandle);
- } else {
- ALOGE("%s: Not able to load libmm-qdcm.so", __FUNCTION__);
- }
-
+ ret = ctx->mColorMode->applyDefaultMode();
+ if (ret)
+ ALOGD("%s: Not able to apply default mode", __FUNCTION__);
ctx->mBootAnimCompleted = true;
}
@@ -2851,4 +2843,104 @@
}
}
+void ColorMode::init() {
+ //Map symbols from libmm-qdcm and get list of modes
+ mModeHandle = dlopen("libmm-qdcm.so", RTLD_NOW);
+ if (mModeHandle) {
+ *(void **)& fnApplyDefaultMode = dlsym(mModeHandle, "applyDefaults");
+ *(void **)& fnApplyModeById = dlsym(mModeHandle, "applyModeById");
+ *(void **)& fnGetNumModes = dlsym(mModeHandle, "getNumDisplayModes");
+ *(void **)& fnGetModeList = dlsym(mModeHandle, "getDisplayModeIdList");
+ *(void **)& fnSetDefaultMode = dlsym(mModeHandle, "setDefaultMode");
+ } else {
+ ALOGW("Unable to load libmm-qdcm");
+ }
+
+ if(fnGetNumModes) {
+ mNumModes = fnGetNumModes(HWC_DISPLAY_PRIMARY);
+ if(mNumModes > MAX_NUM_COLOR_MODES) {
+ ALOGE("Number of modes is above the limit: %d", mNumModes);
+ mNumModes = 0;
+ return;
+ }
+ if(fnGetModeList) {
+ fnGetModeList(mModeList, &mCurMode, HWC_DISPLAY_PRIMARY);
+ mCurModeIndex = getIndexForMode(mCurMode);
+ ALOGI("ColorMode: current mode: %d current mode index: %d number of modes: %d",
+ mCurMode, mCurModeIndex, mNumModes);
+ }
+ }
+}
+
+//Legacy API
+int ColorMode::applyDefaultMode() {
+ if(fnApplyDefaultMode) {
+ return fnApplyDefaultMode(HWC_DISPLAY_PRIMARY);
+ } else {
+ return -EINVAL;
+ }
+}
+
+int ColorMode::applyModeByID(int modeID) {
+ if(fnApplyModeById) {
+ int ret = fnApplyModeById(modeID, HWC_DISPLAY_PRIMARY);
+ if (!ret)
+ ret = setDefaultMode(modeID);
+ return ret;
+ } else {
+ return -EINVAL;
+ }
+}
+
+//This API is called from setActiveConfig
+//The value here must be set as default
+int ColorMode::applyModeByIndex(int index) {
+ int ret = 0;
+ int mode = getModeForIndex(index);
+ if(mode < 0) {
+ ALOGE("Invalid mode for index: %d", index);
+ return -EINVAL;
+ }
+ ALOGD("%s: Applying mode index: %d modeID: %d", __FUNCTION__, index, mode);
+ ret = applyModeByID(mode);
+ if(!ret) {
+ mCurModeIndex = index;
+ setDefaultMode(mode);
+ }
+ return ret;
+}
+
+int ColorMode::setDefaultMode(int modeID) {
+ if(fnSetDefaultMode) {
+ ALOGD("Setting default color mode to %d", modeID);
+ return fnSetDefaultMode(modeID, HWC_DISPLAY_PRIMARY);
+ } else {
+ return -EINVAL;
+ }
+}
+
+int ColorMode::getModeForIndex(int index) {
+ if(index < mNumModes) {
+ return mModeList[index];
+ } else {
+ return -EINVAL;
+ }
+}
+
+int ColorMode::getIndexForMode(int mode) {
+ if(mModeList) {
+ for(int32_t i = 0; i < mNumModes; i++)
+ if(mModeList[i] == mode)
+ return i;
+ }
+ return -EINVAL;
+}
+
+void ColorMode::destroy() {
+ if(mModeHandle) {
+ dlclose(mModeHandle);
+ mModeHandle = NULL;
+ }
+}
+
};//namespace qhwc
diff --git a/msm8994/libhwcomposer/hwc_utils.h b/msm8994/libhwcomposer/hwc_utils.h
index e8c7545..b298a25 100644
--- a/msm8994/libhwcomposer/hwc_utils.h
+++ b/msm8994/libhwcomposer/hwc_utils.h
@@ -48,6 +48,7 @@
#define STR(f) #f;
// Max number of PTOR layers handled
#define MAX_PTOR_LAYERS 2
+#define MAX_NUM_COLOR_MODES 32
//Fwrd decls
struct hwc_context_t;
@@ -229,6 +230,36 @@
uint32_t mCount;
};
+//ColorModes for primary displays
+class ColorMode {
+public:
+ void init();
+ void destroy();
+ int32_t getNumModes() { return mNumModes; }
+ const int32_t* getModeList() { return mModeList; }
+ int32_t getModeForIndex(int32_t index);
+ int32_t getIndexForMode(int32_t mode);
+ int applyDefaultMode();
+ int applyModeByID(int modeID);
+ int applyModeByIndex(int index);
+ int setDefaultMode(int modeID);
+ int getActiveModeIndex() { return mCurModeIndex; }
+private:
+ int32_t (*fnGetNumModes)(int /*dispID*/);
+ int32_t (*fnGetModeList)(int32_t* /*mModeList*/, int32_t* /*current default*/,
+ int32_t /*dispID*/);
+ int (*fnApplyDefaultMode)(int /*dispID*/);
+ int (*fnApplyModeById)(int /*modeID*/, int /*dispID*/);
+ int (*fnSetDefaultMode)(int /*modeID*/, int /*dispID*/);
+
+ void* mModeHandle = NULL;
+ int32_t mModeList[MAX_NUM_COLOR_MODES];
+ int32_t mNumModes = 0;
+ int32_t mCurModeIndex = 0;
+ int32_t mCurMode = 0;
+
+};
+
inline uint32_t LayerRotMap::getCount() const {
return mCount;
}
@@ -650,6 +681,8 @@
bool mHPDEnabled;
//Used to notify that boot has completed
bool mBootAnimCompleted;
+ //Manages color modes
+ qhwc::ColorMode *mColorMode;
};
namespace qhwc {