display: Add support for dynamic refresh rate
- The primary panels refresh rate can be change by clients - Required refresh rate will be set by client using metadata - If there are multiple clients requesting, it will be used only when the refresh rates are equal, else it resets to default - Set the new refresh rate only when there are only YUV layers updating or when the list has only one RGB layer updating - MdpVersion gets the dyn fps capabilities from panelInfo Change-Id: If3e7e6b2f028eb301399c4d32c748eed8a97c41f
This commit is contained in:
@@ -651,6 +651,8 @@ void ExternalDisplay::setAttributes() {
|
|||||||
(int)mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].xres;
|
(int)mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].xres;
|
||||||
mHwcContext->mViewFrame[HWC_DISPLAY_EXTERNAL].bottom =
|
mHwcContext->mViewFrame[HWC_DISPLAY_EXTERNAL].bottom =
|
||||||
(int)mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].yres;
|
(int)mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].yres;
|
||||||
|
mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].refreshRate = fps;
|
||||||
|
mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].dynRefreshRate = fps;
|
||||||
mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].vsync_period =
|
mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].vsync_period =
|
||||||
(int) 1000000000l / fps;
|
(int) 1000000000l / fps;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,11 @@ LOCAL_SHARED_LIBRARIES += libskia
|
|||||||
endif #TARGET_USES_QCOM_BSP
|
endif #TARGET_USES_QCOM_BSP
|
||||||
|
|
||||||
LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdhwcomposer\"
|
LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdhwcomposer\"
|
||||||
|
#Enable Dynamic FPS if PHASE_OFFSET is not set
|
||||||
|
ifeq ($(VSYNC_EVENT_PHASE_OFFSET_NS),)
|
||||||
|
LOCAL_CFLAGS += -DDYNAMIC_FPS
|
||||||
|
endif
|
||||||
|
|
||||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
|
LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
|
||||||
LOCAL_SRC_FILES := hwc.cpp \
|
LOCAL_SRC_FILES := hwc.cpp \
|
||||||
hwc_utils.cpp \
|
hwc_utils.cpp \
|
||||||
|
|||||||
@@ -792,6 +792,8 @@ void hwc_dump(struct hwc_composer_device_1* dev, char *buff, int buff_len)
|
|||||||
dumpsys_log(aBuf, "Qualcomm HWC state:\n");
|
dumpsys_log(aBuf, "Qualcomm HWC state:\n");
|
||||||
dumpsys_log(aBuf, " MDPVersion=%d\n", ctx->mMDP.version);
|
dumpsys_log(aBuf, " MDPVersion=%d\n", ctx->mMDP.version);
|
||||||
dumpsys_log(aBuf, " DisplayPanel=%c\n", ctx->mMDP.panel);
|
dumpsys_log(aBuf, " DisplayPanel=%c\n", ctx->mMDP.panel);
|
||||||
|
dumpsys_log(aBuf, " DynRefreshRate=%d\n",
|
||||||
|
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].dynRefreshRate);
|
||||||
for(int dpy = 0; dpy < HWC_NUM_DISPLAY_TYPES; dpy++) {
|
for(int dpy = 0; dpy < HWC_NUM_DISPLAY_TYPES; dpy++) {
|
||||||
if(ctx->mMDPComp[dpy])
|
if(ctx->mMDPComp[dpy])
|
||||||
ctx->mMDPComp[dpy]->dump(aBuf, ctx);
|
ctx->mMDPComp[dpy]->dump(aBuf, ctx);
|
||||||
|
|||||||
@@ -1063,7 +1063,7 @@ bool MDPComp::cacheBasedComp(hwc_context_t *ctx,
|
|||||||
|
|
||||||
int numAppLayers = ctx->listStats[mDpy].numAppLayers;
|
int numAppLayers = ctx->listStats[mDpy].numAppLayers;
|
||||||
mCurrentFrame.reset(numAppLayers);
|
mCurrentFrame.reset(numAppLayers);
|
||||||
updateLayerCache(ctx, list);
|
updateLayerCache(ctx, list, mCurrentFrame);
|
||||||
|
|
||||||
//If an MDP marked layer is unsupported cannot do partial MDP Comp
|
//If an MDP marked layer is unsupported cannot do partial MDP Comp
|
||||||
for(int i = 0; i < numAppLayers; i++) {
|
for(int i = 0; i < numAppLayers; i++) {
|
||||||
@@ -1078,7 +1078,7 @@ bool MDPComp::cacheBasedComp(hwc_context_t *ctx,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateYUV(ctx, list, false /*secure only*/);
|
updateYUV(ctx, list, false /*secure only*/, mCurrentFrame);
|
||||||
/* mark secure RGB layers for MDP comp */
|
/* mark secure RGB layers for MDP comp */
|
||||||
updateSecureRGB(ctx, list);
|
updateSecureRGB(ctx, list);
|
||||||
bool ret = markLayersForCaching(ctx, list); //sets up fbZ also
|
bool ret = markLayersForCaching(ctx, list); //sets up fbZ also
|
||||||
@@ -1238,7 +1238,7 @@ bool MDPComp::videoOnlyComp(hwc_context_t *ctx,
|
|||||||
|
|
||||||
mCurrentFrame.reset(numAppLayers);
|
mCurrentFrame.reset(numAppLayers);
|
||||||
mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
|
mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
|
||||||
updateYUV(ctx, list, secureOnly);
|
updateYUV(ctx, list, secureOnly, mCurrentFrame);
|
||||||
int mdpCount = mCurrentFrame.mdpCount;
|
int mdpCount = mCurrentFrame.mdpCount;
|
||||||
|
|
||||||
if(!isYuvPresent(ctx, mDpy) or (mdpCount == 0)) {
|
if(!isYuvPresent(ctx, mDpy) or (mdpCount == 0)) {
|
||||||
@@ -1297,7 +1297,7 @@ bool MDPComp::mdpOnlyLayersComp(hwc_context_t *ctx,
|
|||||||
mCurrentFrame.reset(numAppLayers);
|
mCurrentFrame.reset(numAppLayers);
|
||||||
mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
|
mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
|
||||||
|
|
||||||
updateYUV(ctx, list, secureOnly);
|
updateYUV(ctx, list, secureOnly, mCurrentFrame);
|
||||||
/* mark secure RGB layers for MDP comp */
|
/* mark secure RGB layers for MDP comp */
|
||||||
updateSecureRGB(ctx, list);
|
updateSecureRGB(ctx, list);
|
||||||
|
|
||||||
@@ -1548,56 +1548,53 @@ bool MDPComp::markLayersForCaching(hwc_context_t* ctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MDPComp::updateLayerCache(hwc_context_t* ctx,
|
void MDPComp::updateLayerCache(hwc_context_t* ctx,
|
||||||
hwc_display_contents_1_t* list) {
|
hwc_display_contents_1_t* list, FrameInfo& frame) {
|
||||||
int numAppLayers = ctx->listStats[mDpy].numAppLayers;
|
int numAppLayers = ctx->listStats[mDpy].numAppLayers;
|
||||||
int fbCount = 0;
|
int fbCount = 0;
|
||||||
|
|
||||||
for(int i = 0; i < numAppLayers; i++) {
|
for(int i = 0; i < numAppLayers; i++) {
|
||||||
if (mCachedFrame.hnd[i] == list->hwLayers[i].handle) {
|
if (mCachedFrame.hnd[i] == list->hwLayers[i].handle) {
|
||||||
if(!mCurrentFrame.drop[i])
|
if(!frame.drop[i])
|
||||||
fbCount++;
|
fbCount++;
|
||||||
mCurrentFrame.isFBComposed[i] = true;
|
frame.isFBComposed[i] = true;
|
||||||
} else {
|
} else {
|
||||||
mCurrentFrame.isFBComposed[i] = false;
|
frame.isFBComposed[i] = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mCurrentFrame.fbCount = fbCount;
|
frame.fbCount = fbCount;
|
||||||
mCurrentFrame.mdpCount = mCurrentFrame.layerCount - mCurrentFrame.fbCount
|
frame.mdpCount = frame.layerCount - frame.fbCount
|
||||||
- mCurrentFrame.dropCount;
|
- frame.dropCount;
|
||||||
|
|
||||||
ALOGD_IF(isDebug(),"%s: MDP count: %d FB count %d drop count: %d"
|
ALOGD_IF(isDebug(),"%s: MDP count: %d FB count %d drop count: %d",
|
||||||
,__FUNCTION__, mCurrentFrame.mdpCount, mCurrentFrame.fbCount,
|
__FUNCTION__, frame.mdpCount, frame.fbCount, frame.dropCount);
|
||||||
mCurrentFrame.dropCount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MDPComp::updateYUV(hwc_context_t* ctx, hwc_display_contents_1_t* list,
|
void MDPComp::updateYUV(hwc_context_t* ctx, hwc_display_contents_1_t* list,
|
||||||
bool secureOnly) {
|
bool secureOnly, FrameInfo& frame) {
|
||||||
int nYuvCount = ctx->listStats[mDpy].yuvCount;
|
int nYuvCount = ctx->listStats[mDpy].yuvCount;
|
||||||
for(int index = 0;index < nYuvCount; index++){
|
for(int index = 0;index < nYuvCount; index++){
|
||||||
int nYuvIndex = ctx->listStats[mDpy].yuvIndices[index];
|
int nYuvIndex = ctx->listStats[mDpy].yuvIndices[index];
|
||||||
hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
|
hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
|
||||||
|
|
||||||
if(!isYUVDoable(ctx, layer)) {
|
if(!isYUVDoable(ctx, layer)) {
|
||||||
if(!mCurrentFrame.isFBComposed[nYuvIndex]) {
|
if(!frame.isFBComposed[nYuvIndex]) {
|
||||||
mCurrentFrame.isFBComposed[nYuvIndex] = true;
|
frame.isFBComposed[nYuvIndex] = true;
|
||||||
mCurrentFrame.fbCount++;
|
frame.fbCount++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(mCurrentFrame.isFBComposed[nYuvIndex]) {
|
if(frame.isFBComposed[nYuvIndex]) {
|
||||||
private_handle_t *hnd = (private_handle_t *)layer->handle;
|
private_handle_t *hnd = (private_handle_t *)layer->handle;
|
||||||
if(!secureOnly || isSecureBuffer(hnd)) {
|
if(!secureOnly || isSecureBuffer(hnd)) {
|
||||||
mCurrentFrame.isFBComposed[nYuvIndex] = false;
|
frame.isFBComposed[nYuvIndex] = false;
|
||||||
mCurrentFrame.fbCount--;
|
frame.fbCount--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
|
frame.mdpCount = frame.layerCount - frame.fbCount - frame.dropCount;
|
||||||
mCurrentFrame.fbCount - mCurrentFrame.dropCount;
|
ALOGD_IF(isDebug(),"%s: fb count: %d",__FUNCTION__, frame.fbCount);
|
||||||
ALOGD_IF(isDebug(),"%s: fb count: %d",__FUNCTION__,
|
|
||||||
mCurrentFrame.fbCount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MDPComp::updateSecureRGB(hwc_context_t* ctx,
|
void MDPComp::updateSecureRGB(hwc_context_t* ctx,
|
||||||
@@ -1878,6 +1875,26 @@ int MDPComp::prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
|
|||||||
ALOGD("%s",sDump.string());
|
ALOGD("%s",sDump.string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DYNAMIC_FPS
|
||||||
|
//For primary display, set the dynamic refreshrate
|
||||||
|
if(!mDpy && qdutils::MDPVersion::getInstance().isDynFpsSupported()) {
|
||||||
|
FrameInfo frame;
|
||||||
|
frame.reset(mCurrentFrame.layerCount);
|
||||||
|
ALOGD_IF(isDebug(), "%s: Update Cache and YUVInfo for Dyn Refresh Rate",
|
||||||
|
__FUNCTION__);
|
||||||
|
updateLayerCache(ctx, list, frame);
|
||||||
|
updateYUV(ctx, list, false /*secure only*/, frame);
|
||||||
|
uint32_t refreshRate = ctx->dpyAttr[mDpy].refreshRate;
|
||||||
|
//Set the new fresh rate, if there is only one updating YUV layer
|
||||||
|
//or there is one single RGB layer with this request
|
||||||
|
if((ctx->listStats[mDpy].yuvCount == frame.mdpCount) ||
|
||||||
|
(frame.layerCount == 1)) {
|
||||||
|
refreshRate = ctx->listStats[mDpy].refreshRateRequest;
|
||||||
|
}
|
||||||
|
setRefreshRate(ctx, mDpy, refreshRate);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
mCachedFrame.cacheAll(list);
|
mCachedFrame.cacheAll(list);
|
||||||
mCachedFrame.updateCounts(mCurrentFrame);
|
mCachedFrame.updateCounts(mCurrentFrame);
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
@@ -209,7 +209,8 @@ protected:
|
|||||||
/* checks for mdp comp dimension limitation */
|
/* checks for mdp comp dimension limitation */
|
||||||
bool isValidDimension(hwc_context_t *ctx, hwc_layer_1_t *layer);
|
bool isValidDimension(hwc_context_t *ctx, hwc_layer_1_t *layer);
|
||||||
/* tracks non updating layers*/
|
/* tracks non updating layers*/
|
||||||
void updateLayerCache(hwc_context_t* ctx, hwc_display_contents_1_t* list);
|
void updateLayerCache(hwc_context_t* ctx, hwc_display_contents_1_t* list,
|
||||||
|
FrameInfo& frame);
|
||||||
/* optimize layers for mdp comp*/
|
/* optimize layers for mdp comp*/
|
||||||
bool markLayersForCaching(hwc_context_t* ctx,
|
bool markLayersForCaching(hwc_context_t* ctx,
|
||||||
hwc_display_contents_1_t* list);
|
hwc_display_contents_1_t* list);
|
||||||
@@ -223,7 +224,7 @@ protected:
|
|||||||
|
|
||||||
/* updates cache map with YUV info */
|
/* updates cache map with YUV info */
|
||||||
void updateYUV(hwc_context_t* ctx, hwc_display_contents_1_t* list,
|
void updateYUV(hwc_context_t* ctx, hwc_display_contents_1_t* list,
|
||||||
bool secureOnly);
|
bool secureOnly, FrameInfo& frame);
|
||||||
/* updates cache map with secure RGB info */
|
/* updates cache map with secure RGB info */
|
||||||
void updateSecureRGB(hwc_context_t* ctx,
|
void updateSecureRGB(hwc_context_t* ctx,
|
||||||
hwc_display_contents_1_t* list);
|
hwc_display_contents_1_t* list);
|
||||||
|
|||||||
@@ -75,6 +75,9 @@ EGLAPI EGLBoolean eglGpuPerfHintQCOM(EGLDisplay dpy, EGLContext ctx,
|
|||||||
|
|
||||||
namespace qhwc {
|
namespace qhwc {
|
||||||
|
|
||||||
|
//Std refresh rates for digital videos- 24p, 30p and 48p
|
||||||
|
uint32_t stdRefreshRates[] = { 30, 24, 48 };
|
||||||
|
|
||||||
bool isValidResolution(hwc_context_t *ctx, uint32_t xres, uint32_t yres)
|
bool isValidResolution(hwc_context_t *ctx, uint32_t xres, uint32_t yres)
|
||||||
{
|
{
|
||||||
return !((xres > qdutils::MDPVersion::getInstance().getMaxMixerWidth() &&
|
return !((xres > qdutils::MDPVersion::getInstance().getMaxMixerWidth() &&
|
||||||
@@ -170,6 +173,8 @@ static int openFramebufferDevice(hwc_context_t *ctx)
|
|||||||
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres = info.yres;
|
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres = info.yres;
|
||||||
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xdpi = xdpi;
|
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xdpi = xdpi;
|
||||||
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].ydpi = ydpi;
|
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].ydpi = ydpi;
|
||||||
|
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].refreshRate = (uint32_t)fps;
|
||||||
|
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].dynRefreshRate = (uint32_t)fps;
|
||||||
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period =
|
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period =
|
||||||
(uint32_t)(1000000000l / fps);
|
(uint32_t)(1000000000l / fps);
|
||||||
|
|
||||||
@@ -362,6 +367,50 @@ void closeContext(hwc_context_t *ctx)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Helper to roundoff the refreshrates
|
||||||
|
static uint32_t roundOff(uint32_t refreshRate) {
|
||||||
|
int count = (int) (sizeof(stdRefreshRates)/sizeof(stdRefreshRates[0]));
|
||||||
|
uint32_t rate = refreshRate;
|
||||||
|
for(int i=0; i< count; i++) {
|
||||||
|
if(abs(stdRefreshRates[i] - refreshRate) < 2) {
|
||||||
|
// Most likely used for video, the fps can fluctuate
|
||||||
|
// Ex: b/w 29 and 30 for 30 fps clip
|
||||||
|
rate = stdRefreshRates[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Helper func to set the dyn fps
|
||||||
|
void setRefreshRate(hwc_context_t* ctx, int dpy, uint32_t refreshRate) {
|
||||||
|
//Update only if different
|
||||||
|
if(!ctx || refreshRate == ctx->dpyAttr[dpy].dynRefreshRate)
|
||||||
|
return;
|
||||||
|
const int fbNum = Overlay::getFbForDpy(dpy);
|
||||||
|
char sysfsPath[qdutils::MAX_SYSFS_FILE_PATH];
|
||||||
|
snprintf (sysfsPath, sizeof(sysfsPath),
|
||||||
|
"/sys/class/graphics/fb%d/dynamic_fps", fbNum);
|
||||||
|
|
||||||
|
int fd = open(sysfsPath, O_WRONLY);
|
||||||
|
if(fd >= 0) {
|
||||||
|
char str[64];
|
||||||
|
snprintf(str, sizeof(str), "%d", refreshRate);
|
||||||
|
ssize_t ret = write(fd, str, strlen(str));
|
||||||
|
if(ret < 0) {
|
||||||
|
ALOGE("%s: Failed to write %d with error %s",
|
||||||
|
__FUNCTION__, refreshRate, strerror(errno));
|
||||||
|
} else {
|
||||||
|
ctx->dpyAttr[dpy].dynRefreshRate = refreshRate;
|
||||||
|
ALOGD_IF(HWC_UTILS_DEBUG, "%s: Wrote %d to dynamic_fps",
|
||||||
|
__FUNCTION__, refreshRate);
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
} else {
|
||||||
|
ALOGE("%s: Failed to open %s with error %s", __FUNCTION__, sysfsPath,
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void dumpsys_log(android::String8& buf, const char* fmt, ...)
|
void dumpsys_log(android::String8& buf, const char* fmt, ...)
|
||||||
{
|
{
|
||||||
@@ -829,6 +878,9 @@ void setListStats(hwc_context_t *ctx,
|
|||||||
ctx->dpyAttr[dpy].mActionSafePresent = isActionSafePresent(ctx, dpy);
|
ctx->dpyAttr[dpy].mActionSafePresent = isActionSafePresent(ctx, dpy);
|
||||||
ctx->listStats[dpy].renderBufIndexforABC = -1;
|
ctx->listStats[dpy].renderBufIndexforABC = -1;
|
||||||
ctx->listStats[dpy].secureRGBCount = 0;
|
ctx->listStats[dpy].secureRGBCount = 0;
|
||||||
|
ctx->listStats[dpy].refreshRateRequest = ctx->dpyAttr[dpy].refreshRate;
|
||||||
|
uint32_t refreshRate = 0;
|
||||||
|
qdutils::MDPVersion& mdpHw = qdutils::MDPVersion::getInstance();
|
||||||
|
|
||||||
resetROI(ctx, dpy);
|
resetROI(ctx, dpy);
|
||||||
|
|
||||||
@@ -882,6 +934,27 @@ void setListStats(hwc_context_t *ctx,
|
|||||||
if(layer->blending == HWC_BLENDING_PREMULT)
|
if(layer->blending == HWC_BLENDING_PREMULT)
|
||||||
ctx->listStats[dpy].preMultipliedAlpha = true;
|
ctx->listStats[dpy].preMultipliedAlpha = true;
|
||||||
|
|
||||||
|
#ifdef DYNAMIC_FPS
|
||||||
|
if (dpy == HWC_DISPLAY_PRIMARY && mdpHw.isDynFpsSupported()) {
|
||||||
|
//dyn fps: get refreshrate from metadata
|
||||||
|
//Support multiple refresh rates if they are same
|
||||||
|
//else set to default
|
||||||
|
MetaData_t *mdata = hnd ? (MetaData_t *)hnd->base_metadata : NULL;
|
||||||
|
if (mdata && (mdata->operation & UPDATE_REFRESH_RATE)) {
|
||||||
|
// Valid refreshRate in metadata and within the range
|
||||||
|
uint32_t rate = roundOff(mdata->refreshrate);
|
||||||
|
if((rate >= mdpHw.getMinFpsSupported() &&
|
||||||
|
rate <= mdpHw.getMaxFpsSupported())) {
|
||||||
|
if (!refreshRate) {
|
||||||
|
refreshRate = rate;
|
||||||
|
} else if(refreshRate != rate) {
|
||||||
|
// multiple refreshrate requests, set to default
|
||||||
|
refreshRate = ctx->dpyAttr[dpy].refreshRate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
if(ctx->listStats[dpy].yuvCount > 0) {
|
if(ctx->listStats[dpy].yuvCount > 0) {
|
||||||
if (property_get("hw.cabl.yuv", property, NULL) > 0) {
|
if (property_get("hw.cabl.yuv", property, NULL) > 0) {
|
||||||
@@ -905,6 +978,9 @@ void setListStats(hwc_context_t *ctx,
|
|||||||
|
|
||||||
if(dpy == HWC_DISPLAY_PRIMARY) {
|
if(dpy == HWC_DISPLAY_PRIMARY) {
|
||||||
ctx->mAD->markDoable(ctx, list);
|
ctx->mAD->markDoable(ctx, list);
|
||||||
|
//Store the requested fresh rate
|
||||||
|
ctx->listStats[dpy].refreshRateRequest = refreshRate ?
|
||||||
|
refreshRate : ctx->dpyAttr[dpy].refreshRate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -80,6 +80,8 @@ struct MDPInfo {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct DisplayAttributes {
|
struct DisplayAttributes {
|
||||||
|
uint32_t refreshRate;
|
||||||
|
uint32_t dynRefreshRate;
|
||||||
uint32_t vsync_period; //nanos
|
uint32_t vsync_period; //nanos
|
||||||
uint32_t xres;
|
uint32_t xres;
|
||||||
uint32_t yres;
|
uint32_t yres;
|
||||||
@@ -137,6 +139,8 @@ struct ListStats {
|
|||||||
// Secure RGB specific
|
// Secure RGB specific
|
||||||
int secureRGBCount;
|
int secureRGBCount;
|
||||||
int secureRGBIndices[MAX_NUM_APP_LAYERS];
|
int secureRGBIndices[MAX_NUM_APP_LAYERS];
|
||||||
|
//dyn refresh rate-Client requested refreshrate
|
||||||
|
uint32_t refreshRateRequest;
|
||||||
};
|
};
|
||||||
|
|
||||||
//PTOR Comp info
|
//PTOR Comp info
|
||||||
@@ -305,6 +309,8 @@ void getActionSafePosition(hwc_context_t *ctx, int dpy, hwc_rect_t& dst);
|
|||||||
void getAspectRatioPosition(hwc_context_t* ctx, int dpy, int extOrientation,
|
void getAspectRatioPosition(hwc_context_t* ctx, int dpy, int extOrientation,
|
||||||
hwc_rect_t& inRect, hwc_rect_t& outRect);
|
hwc_rect_t& inRect, hwc_rect_t& outRect);
|
||||||
|
|
||||||
|
void setRefreshRate(hwc_context_t *ctx, int dpy, uint32_t refreshRate);
|
||||||
|
|
||||||
bool isPrimaryPortrait(hwc_context_t *ctx);
|
bool isPrimaryPortrait(hwc_context_t *ctx);
|
||||||
|
|
||||||
bool isOrientationPortrait(hwc_context_t *ctx);
|
bool isOrientationPortrait(hwc_context_t *ctx);
|
||||||
|
|||||||
@@ -226,6 +226,19 @@ void MDPVersion::updatePanelInfo() {
|
|||||||
mPanelInfo.mNeedsROIMerge = atoi(tokens[1]);
|
mPanelInfo.mNeedsROIMerge = atoi(tokens[1]);
|
||||||
ALOGI("Needs ROI Merge: %d", mPanelInfo.mNeedsROIMerge);
|
ALOGI("Needs ROI Merge: %d", mPanelInfo.mNeedsROIMerge);
|
||||||
}
|
}
|
||||||
|
if(!strncmp(tokens[0], "dyn_fps_en", strlen("dyn_fps_en"))) {
|
||||||
|
mPanelInfo.mDynFpsSupported = atoi(tokens[1]);
|
||||||
|
ALOGI("Dynamic Fps: %s", mPanelInfo.mDynFpsSupported ?
|
||||||
|
"Enabled" : "Disabled");
|
||||||
|
}
|
||||||
|
if(!strncmp(tokens[0], "min_fps", strlen("min_fps"))) {
|
||||||
|
mPanelInfo.mMinFps = atoi(tokens[1]);
|
||||||
|
ALOGI("Min Panel fps: %d", mPanelInfo.mMinFps);
|
||||||
|
}
|
||||||
|
if(!strncmp(tokens[0], "max_fps", strlen("max_fps"))) {
|
||||||
|
mPanelInfo.mMaxFps = atoi(tokens[1]);
|
||||||
|
ALOGI("Max Panel fps: %d", mPanelInfo.mMaxFps);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if((property_get("persist.hwc.pubypass", property, 0) > 0) &&
|
if((property_get("persist.hwc.pubypass", property, 0) > 0) &&
|
||||||
|
|||||||
@@ -92,9 +92,13 @@ struct PanelInfo {
|
|||||||
int mMinROIWidth; // Min width needed for ROI
|
int mMinROIWidth; // Min width needed for ROI
|
||||||
int mMinROIHeight; // Min height needed for ROI
|
int mMinROIHeight; // Min height needed for ROI
|
||||||
bool mNeedsROIMerge; // Merge ROI's of both the DSI's
|
bool mNeedsROIMerge; // Merge ROI's of both the DSI's
|
||||||
|
bool mDynFpsSupported; // Panel Supports dyn fps
|
||||||
|
uint32_t mMinFps; // Min fps supported by panel
|
||||||
|
uint32_t mMaxFps; // Max fps supported by panel
|
||||||
PanelInfo() : mType(NO_PANEL), mPartialUpdateEnable(0),
|
PanelInfo() : mType(NO_PANEL), mPartialUpdateEnable(0),
|
||||||
mLeftAlign(0), mWidthAlign(0), mTopAlign(0), mHeightAlign(0),
|
mLeftAlign(0), mWidthAlign(0), mTopAlign(0), mHeightAlign(0),
|
||||||
mMinROIWidth(0), mMinROIHeight(0), mNeedsROIMerge(false){}
|
mMinROIWidth(0), mMinROIHeight(0), mNeedsROIMerge(false),
|
||||||
|
mDynFpsSupported(0), mMinFps(0), mMaxFps(0) {}
|
||||||
friend class MDPVersion;
|
friend class MDPVersion;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -130,6 +134,9 @@ public:
|
|||||||
unsigned long getLowBw() { return mLowBw; }
|
unsigned long getLowBw() { return mLowBw; }
|
||||||
unsigned long getHighBw() { return mHighBw; }
|
unsigned long getHighBw() { return mHighBw; }
|
||||||
bool isRotDownscaleEnabled() { return mRotDownscale; }
|
bool isRotDownscaleEnabled() { return mRotDownscale; }
|
||||||
|
bool isDynFpsSupported() { return mPanelInfo.mDynFpsSupported; }
|
||||||
|
uint32_t getMinFpsSupported() { return mPanelInfo.mMinFps; }
|
||||||
|
uint32_t getMaxFpsSupported() { return mPanelInfo.mMaxFps; }
|
||||||
int getMaxMixerWidth() const { return mMaxMixerWidth; }
|
int getMaxMixerWidth() const { return mMaxMixerWidth; }
|
||||||
bool isSrcSplit() const;
|
bool isSrcSplit() const;
|
||||||
bool isSrcSplitAlways() const;
|
bool isSrcSplitAlways() const;
|
||||||
|
|||||||
@@ -83,7 +83,10 @@ int setMetaData(private_handle_t *handle, DispParamType paramType,
|
|||||||
break;
|
break;
|
||||||
case UPDATE_BUFFER_GEOMETRY:
|
case UPDATE_BUFFER_GEOMETRY:
|
||||||
memcpy((void *)&data->bufferDim, param, sizeof(BufferDim_t));
|
memcpy((void *)&data->bufferDim, param, sizeof(BufferDim_t));
|
||||||
break;
|
break;
|
||||||
|
case UPDATE_REFRESH_RATE:
|
||||||
|
data->refreshrate = *((uint32_t *)param);
|
||||||
|
break;
|
||||||
case UPDATE_COLOR_SPACE:
|
case UPDATE_COLOR_SPACE:
|
||||||
data->colorSpace = *((ColorSpace_t *)param);
|
data->colorSpace = *((ColorSpace_t *)param);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ struct MetaData_t {
|
|||||||
struct IGCData_t igcData;
|
struct IGCData_t igcData;
|
||||||
struct Sharp2Data_t Sharp2Data;
|
struct Sharp2Data_t Sharp2Data;
|
||||||
int64_t timestamp;
|
int64_t timestamp;
|
||||||
|
uint32_t refreshrate;
|
||||||
enum ColorSpace_t colorSpace;
|
enum ColorSpace_t colorSpace;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -89,6 +90,7 @@ enum DispParamType {
|
|||||||
PP_PARAM_SHARP2 = 0x0020,
|
PP_PARAM_SHARP2 = 0x0020,
|
||||||
PP_PARAM_TIMESTAMP = 0x0040,
|
PP_PARAM_TIMESTAMP = 0x0040,
|
||||||
UPDATE_BUFFER_GEOMETRY = 0x0080,
|
UPDATE_BUFFER_GEOMETRY = 0x0080,
|
||||||
|
UPDATE_REFRESH_RATE = 0x0100,
|
||||||
UPDATE_COLOR_SPACE = 0x0200,
|
UPDATE_COLOR_SPACE = 0x0200,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user