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
This commit is contained in:
Naseer Ahmed 2015-08-31 18:57:08 -04:00 committed by Ed Tam
parent 72579d94ed
commit 6109f69d57
5 changed files with 171 additions and 66 deletions

View File

@ -17,7 +17,8 @@ ifeq ($(TARGET_USES_QCOM_BSP),true)
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

View File

@ -772,8 +772,15 @@ int hwc_getDisplayConfigs(struct hwc_composer_device_1* dev, int disp,
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 @@ int hwc_getDisplayAttributes(struct hwc_composer_device_1* dev, int disp,
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 @@ int hwc_getDisplayAttributes(struct hwc_composer_device_1* dev, int disp,
}
}
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 @@ int hwc_getDisplayAttributes(struct hwc_composer_device_1* dev, int disp,
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 @@ int hwc_getActiveConfig(struct hwc_composer_device_1* dev, int disp)
// 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 @@ int hwc_setActiveConfig(struct hwc_composer_device_1* dev, int disp, int index)
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;
}

View File

@ -340,25 +340,11 @@ static void toggleScreenUpdate(hwc_context_t* ctx, uint32_t on) {
}
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,

View File

@ -418,6 +418,8 @@ void initContext(hwc_context_t *ctx)
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 @@ void closeContext(hwc_context_t *ctx)
ctx->mAD = NULL;
}
if(ctx->mColorMode) {
ctx->mColorMode->destroy();
delete ctx->mColorMode;
ctx->mColorMode = NULL;
}
}
//Helper to roundoff the refreshrates
@ -2505,8 +2511,6 @@ bool isPeripheral(const hwc_rect_t& rect1, const hwc_rect_t& rect2) {
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 @@ void processBootAnimCompleted(hwc_context_t *ctx) {
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 handle_offline(hwc_context_t* ctx, int dpy) {
}
}
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

View File

@ -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 @@ private:
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 @@ struct hwc_context_t {
bool mHPDEnabled;
//Used to notify that boot has completed
bool mBootAnimCompleted;
//Manages color modes
qhwc::ColorMode *mColorMode;
};
namespace qhwc {