h/q/d: Add binder-api support to change refresh-rate.
** Now, there are two ways for the clients to request change in the refresh-rate of the target. (a) Using metadata of the input-buffer. (b) Using binder api added as part of this change. ** configureDynRefreshRate binder api provides three op-modes which can be used as following: (a) "DISABLE_METADATA_DYN_REFRESH_RATE" can be used by the clients, to disallow display-hal from honoring refresh-rate change requests, made by video-clients using the metadata. For ex: This can be used during streaming use-cases (Dash-playback, playback at WFD-sink,etc) where the idea is not to change the refresh-rate, though video-client requests for it using metadata, as video-clients cannot distinguish between streaming and non-streaming usecases. Usage: adb shell service call display.qservice 18 i32 0 i32 0 (b) "ENABLE_METADATA_DYN_REFRESH_RATE" can be used by the clients after DISABLE_METADATA_DYN_REFRESH_RATE, to once again allow display-hal to be able to change refresh-rate based on requests made by the video-clients using metadata. For ex: This can be used by clients( Dash-playback, WFD, etc) once they are done with their use-case. WFD-framework will also use this when the wfd-session is paused. Usage: adb shell service call display.qservice 18 i32 1 i32 0 (c) "SET_BINDER_DYN_REFRESH_RATE" can be used by the clients to change the refresh-rate of the target using binder-api, provided they have disallowed display from honoring the refresh-rate requests made using metadata. In other words, changing refresh-rate through this binder api and using metadata approach cannot co-exist together. Usage: adb shell service call display.qservice 18 i32 2 i32 45 -- The refresh-rate set here will correspond to 45fps. ** Added property "persist.metadata_dynfps.disable" that can be used by OEM's, to disable setting of refresh-rate using the metadata. Change-Id: I767fa174dcf1cfd061a578e96cd68af28e7dd36b
This commit is contained in:
@@ -1978,7 +1978,8 @@ int MDPComp::prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
|
|||||||
|
|
||||||
#ifdef DYNAMIC_FPS
|
#ifdef DYNAMIC_FPS
|
||||||
//For primary display, set the dynamic refreshrate
|
//For primary display, set the dynamic refreshrate
|
||||||
if(!mDpy && qdutils::MDPVersion::getInstance().isDynFpsSupported()) {
|
if(!mDpy && qdutils::MDPVersion::getInstance().isDynFpsSupported() &&
|
||||||
|
ctx->mUseMetaDataRefreshRate) {
|
||||||
FrameInfo frame;
|
FrameInfo frame;
|
||||||
frame.reset(mCurrentFrame.layerCount);
|
frame.reset(mCurrentFrame.layerCount);
|
||||||
memset(&frame.drop, 0, sizeof(frame.drop));
|
memset(&frame.drop, 0, sizeof(frame.drop));
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#include <hwc_mdpcomp.h>
|
#include <hwc_mdpcomp.h>
|
||||||
#include <hwc_virtual.h>
|
#include <hwc_virtual.h>
|
||||||
#include <overlay.h>
|
#include <overlay.h>
|
||||||
|
#include <display_config.h>
|
||||||
|
|
||||||
#define QCLIENT_DEBUG 0
|
#define QCLIENT_DEBUG 0
|
||||||
|
|
||||||
@@ -175,13 +176,13 @@ static void setSecondaryDisplayStatus(hwc_context_t *ctx,
|
|||||||
dpy, getExternalDisplayState(status));
|
dpy, getExternalDisplayState(status));
|
||||||
|
|
||||||
if(dpy > HWC_DISPLAY_PRIMARY && dpy <= HWC_DISPLAY_VIRTUAL) {
|
if(dpy > HWC_DISPLAY_PRIMARY && dpy <= HWC_DISPLAY_VIRTUAL) {
|
||||||
if(dpy == HWC_DISPLAY_VIRTUAL && status == EXTERNAL_OFFLINE) {
|
if(dpy == HWC_DISPLAY_VIRTUAL && status == qdutils::EXTERNAL_OFFLINE) {
|
||||||
ctx->mWfdSyncLock.lock();
|
ctx->mWfdSyncLock.lock();
|
||||||
ctx->mWfdSyncLock.signal();
|
ctx->mWfdSyncLock.signal();
|
||||||
ctx->mWfdSyncLock.unlock();
|
ctx->mWfdSyncLock.unlock();
|
||||||
} else if(status == EXTERNAL_PAUSE) {
|
} else if(status == qdutils::EXTERNAL_PAUSE) {
|
||||||
handle_pause(ctx, dpy);
|
handle_pause(ctx, dpy);
|
||||||
} else if(status == EXTERNAL_RESUME) {
|
} else if(status == qdutils::EXTERNAL_RESUME) {
|
||||||
handle_resume(ctx, dpy);
|
handle_resume(ctx, dpy);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -263,6 +264,48 @@ static void toggleBWC(hwc_context_t* ctx, const Parcel* inParcel) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void configureDynRefreshRate(hwc_context_t* ctx,
|
||||||
|
const Parcel* inParcel) {
|
||||||
|
uint32_t op = (uint32_t)inParcel->readInt32();
|
||||||
|
uint32_t refresh_rate = (uint32_t)inParcel->readInt32();
|
||||||
|
MDPVersion& mdpHw = MDPVersion::getInstance();
|
||||||
|
uint32_t dpy = HWC_DISPLAY_PRIMARY;
|
||||||
|
|
||||||
|
if(mdpHw.isDynFpsSupported()) {
|
||||||
|
Locker::Autolock _sl(ctx->mDrawLock);
|
||||||
|
|
||||||
|
switch (op) {
|
||||||
|
case DISABLE_METADATA_DYN_REFRESH_RATE:
|
||||||
|
ctx->mUseMetaDataRefreshRate = false;
|
||||||
|
setRefreshRate(ctx, dpy, ctx->dpyAttr[dpy].refreshRate);
|
||||||
|
break;
|
||||||
|
case ENABLE_METADATA_DYN_REFRESH_RATE:
|
||||||
|
ctx->mUseMetaDataRefreshRate = true;
|
||||||
|
setRefreshRate(ctx, dpy, ctx->dpyAttr[dpy].refreshRate);
|
||||||
|
break;
|
||||||
|
case SET_BINDER_DYN_REFRESH_RATE:
|
||||||
|
if(ctx->mUseMetaDataRefreshRate)
|
||||||
|
ALOGW("%s: Ignoring binder request to change refresh-rate",
|
||||||
|
__FUNCTION__);
|
||||||
|
else {
|
||||||
|
uint32_t rate = roundOff(refresh_rate);
|
||||||
|
if((rate >= mdpHw.getMinFpsSupported() &&
|
||||||
|
rate <= mdpHw.getMaxFpsSupported())) {
|
||||||
|
setRefreshRate(ctx, dpy, rate);
|
||||||
|
} else {
|
||||||
|
ALOGE("%s: Requested refresh-rate should be between \
|
||||||
|
(%d) and (%d). Given (%d)", __FUNCTION__,
|
||||||
|
mdpHw.getMinFpsSupported(),
|
||||||
|
mdpHw.getMaxFpsSupported(), rate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ALOGE("%s: Invalid op %d",__FUNCTION__,op);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
status_t QClient::notifyCallback(uint32_t command, const Parcel* inParcel,
|
status_t QClient::notifyCallback(uint32_t command, const Parcel* inParcel,
|
||||||
Parcel* outParcel) {
|
Parcel* outParcel) {
|
||||||
status_t ret = NO_ERROR;
|
status_t ret = NO_ERROR;
|
||||||
@@ -314,6 +357,9 @@ status_t QClient::notifyCallback(uint32_t command, const Parcel* inParcel,
|
|||||||
case IQService::TOGGLE_BWC:
|
case IQService::TOGGLE_BWC:
|
||||||
toggleBWC(mHwcContext, inParcel);
|
toggleBWC(mHwcContext, inParcel);
|
||||||
break;
|
break;
|
||||||
|
case IQService::CONFIGURE_DYN_REFRESH_RATE:
|
||||||
|
configureDynRefreshRate(mHwcContext, inParcel);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ret = NO_ERROR;
|
ret = NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -401,6 +401,12 @@ void initContext(hwc_context_t *ctx)
|
|||||||
ctx->mWindowboxFeature = true;
|
ctx->mWindowboxFeature = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx->mUseMetaDataRefreshRate = true;
|
||||||
|
if(property_get("persist.metadata_dynfps.disable", value, "false")
|
||||||
|
&& !strcmp(value, "true")) {
|
||||||
|
ctx->mUseMetaDataRefreshRate = false;
|
||||||
|
}
|
||||||
|
|
||||||
memset(&(ctx->mPtorInfo), 0, sizeof(ctx->mPtorInfo));
|
memset(&(ctx->mPtorInfo), 0, sizeof(ctx->mPtorInfo));
|
||||||
ALOGI("Initializing Qualcomm Hardware Composer");
|
ALOGI("Initializing Qualcomm Hardware Composer");
|
||||||
ALOGI("MDP version: %d", ctx->mMDP.version);
|
ALOGI("MDP version: %d", ctx->mMDP.version);
|
||||||
@@ -460,7 +466,7 @@ void closeContext(hwc_context_t *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Helper to roundoff the refreshrates
|
//Helper to roundoff the refreshrates
|
||||||
static uint32_t roundOff(uint32_t refreshRate) {
|
uint32_t roundOff(uint32_t refreshRate) {
|
||||||
int count = (int) (sizeof(stdRefreshRates)/sizeof(stdRefreshRates[0]));
|
int count = (int) (sizeof(stdRefreshRates)/sizeof(stdRefreshRates[0]));
|
||||||
uint32_t rate = refreshRate;
|
uint32_t rate = refreshRate;
|
||||||
for(int i=0; i< count; i++) {
|
for(int i=0; i< count; i++) {
|
||||||
@@ -1052,7 +1058,7 @@ void setListStats(hwc_context_t *ctx,
|
|||||||
ctx->listStats[dpy].preMultipliedAlpha = true;
|
ctx->listStats[dpy].preMultipliedAlpha = true;
|
||||||
|
|
||||||
#ifdef DYNAMIC_FPS
|
#ifdef DYNAMIC_FPS
|
||||||
if (dpy == HWC_DISPLAY_PRIMARY && mdpHw.isDynFpsSupported()) {
|
if (!dpy && mdpHw.isDynFpsSupported() && ctx->mUseMetaDataRefreshRate){
|
||||||
//dyn fps: get refreshrate from metadata
|
//dyn fps: get refreshrate from metadata
|
||||||
//Support multiple refresh rates if they are same
|
//Support multiple refresh rates if they are same
|
||||||
//else set to default
|
//else set to default
|
||||||
|
|||||||
@@ -325,6 +325,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);
|
||||||
|
|
||||||
|
uint32_t roundOff(uint32_t refreshRate);
|
||||||
|
|
||||||
void setRefreshRate(hwc_context_t *ctx, int dpy, uint32_t refreshRate);
|
void setRefreshRate(hwc_context_t *ctx, int dpy, uint32_t refreshRate);
|
||||||
|
|
||||||
bool isPrimaryPortrait(hwc_context_t *ctx);
|
bool isPrimaryPortrait(hwc_context_t *ctx);
|
||||||
@@ -639,6 +641,8 @@ struct hwc_context_t {
|
|||||||
float mAspectRatioToleranceLevel;
|
float mAspectRatioToleranceLevel;
|
||||||
// Runtime switch for BWC for targets that support it
|
// Runtime switch for BWC for targets that support it
|
||||||
bool mBWCEnabled;
|
bool mBWCEnabled;
|
||||||
|
// Provides a way for OEM's to disable setting dynfps via metadata.
|
||||||
|
bool mUseMetaDataRefreshRate;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace qhwc {
|
namespace qhwc {
|
||||||
|
|||||||
@@ -152,6 +152,24 @@ int setSecondaryDisplayStatus(int dpy, uint32_t status) {
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int configureDynRefreshRate(uint32_t op, uint32_t refreshRate) {
|
||||||
|
status_t err = (status_t) FAILED_TRANSACTION;
|
||||||
|
sp<IQService> binder = getBinder();
|
||||||
|
Parcel inParcel, outParcel;
|
||||||
|
inParcel.writeInt32(op);
|
||||||
|
inParcel.writeInt32(refreshRate);
|
||||||
|
|
||||||
|
if(binder != NULL) {
|
||||||
|
err = binder->dispatch(IQService::CONFIGURE_DYN_REFRESH_RATE,
|
||||||
|
&inParcel, &outParcel);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(err)
|
||||||
|
ALOGE("%s: Failed setting op %d err=%d", __FUNCTION__, op, err);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
}; //namespace
|
}; //namespace
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -39,6 +39,12 @@
|
|||||||
|
|
||||||
namespace qdutils {
|
namespace qdutils {
|
||||||
|
|
||||||
|
|
||||||
|
/* TODO: Have all the common enums that need be exposed to clients and which
|
||||||
|
* are also needed in hwc defined here. Remove such definitions we have in
|
||||||
|
* hwc_utils.h
|
||||||
|
*/
|
||||||
|
|
||||||
// Use this enum to specify the dpy parameters where needed
|
// Use this enum to specify the dpy parameters where needed
|
||||||
enum {
|
enum {
|
||||||
DISPLAY_PRIMARY = 0,
|
DISPLAY_PRIMARY = 0,
|
||||||
@@ -55,6 +61,12 @@ enum {
|
|||||||
EXTERNAL_RESUME,
|
EXTERNAL_RESUME,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
DISABLE_METADATA_DYN_REFRESH_RATE = 0,
|
||||||
|
ENABLE_METADATA_DYN_REFRESH_RATE,
|
||||||
|
SET_BINDER_DYN_REFRESH_RATE,
|
||||||
|
};
|
||||||
|
|
||||||
// Display Attributes that are available to clients of this library
|
// Display Attributes that are available to clients of this library
|
||||||
// Not to be confused with a similar struct in hwc_utils (in the hwc namespace)
|
// Not to be confused with a similar struct in hwc_utils (in the hwc namespace)
|
||||||
struct DisplayAttributes_t {
|
struct DisplayAttributes_t {
|
||||||
@@ -89,4 +101,7 @@ int setViewFrame(int dpy, int l, int t, int r, int b);
|
|||||||
|
|
||||||
// Set the secondary display status(pause/resume/offline etc.,)
|
// Set the secondary display status(pause/resume/offline etc.,)
|
||||||
int setSecondaryDisplayStatus(int dpy, uint32_t status);
|
int setSecondaryDisplayStatus(int dpy, uint32_t status);
|
||||||
|
|
||||||
|
// Enable/Disable/Set refresh rate dynamically
|
||||||
|
int configureDynRefreshRate(uint32_t op, uint32_t refreshRate);
|
||||||
}; //namespace
|
}; //namespace
|
||||||
|
|||||||
@@ -55,6 +55,8 @@ public:
|
|||||||
DYNAMIC_DEBUG = 15, // Enable more logging on the fly
|
DYNAMIC_DEBUG = 15, // Enable more logging on the fly
|
||||||
SET_IDLE_TIMEOUT = 16, // Set idle timeout for GPU fallback
|
SET_IDLE_TIMEOUT = 16, // Set idle timeout for GPU fallback
|
||||||
TOGGLE_BWC = 17, // Toggle BWC On/Off on targets that support
|
TOGGLE_BWC = 17, // Toggle BWC On/Off on targets that support
|
||||||
|
/* Enable/Disable/Set refresh rate dynamically */
|
||||||
|
CONFIGURE_DYN_REFRESH_RATE = 18,
|
||||||
COMMAND_LIST_END = 400,
|
COMMAND_LIST_END = 400,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user