Merge "Display and wfd synchronization during teardown"
This commit is contained in:
committed by
Gerrit - the friendly Code Review server
commit
38ef977bad
@@ -74,6 +74,7 @@ void free_buffer(private_handle_t *hnd);
|
|||||||
|
|
||||||
class Locker {
|
class Locker {
|
||||||
pthread_mutex_t mutex;
|
pthread_mutex_t mutex;
|
||||||
|
pthread_cond_t cond;
|
||||||
public:
|
public:
|
||||||
class Autolock {
|
class Autolock {
|
||||||
Locker& locker;
|
Locker& locker;
|
||||||
@@ -81,10 +82,18 @@ class Locker {
|
|||||||
inline Autolock(Locker& locker) : locker(locker) { locker.lock(); }
|
inline Autolock(Locker& locker) : locker(locker) { locker.lock(); }
|
||||||
inline ~Autolock() { locker.unlock(); }
|
inline ~Autolock() { locker.unlock(); }
|
||||||
};
|
};
|
||||||
inline Locker() { pthread_mutex_init(&mutex, 0); }
|
inline Locker() {
|
||||||
inline ~Locker() { pthread_mutex_destroy(&mutex); }
|
pthread_mutex_init(&mutex, 0);
|
||||||
|
pthread_cond_init(&cond, 0);
|
||||||
|
}
|
||||||
|
inline ~Locker() {
|
||||||
|
pthread_mutex_destroy(&mutex);
|
||||||
|
pthread_cond_destroy(&cond);
|
||||||
|
}
|
||||||
inline void lock() { pthread_mutex_lock(&mutex); }
|
inline void lock() { pthread_mutex_lock(&mutex); }
|
||||||
|
inline void wait() { pthread_cond_wait(&cond, &mutex); }
|
||||||
inline void unlock() { pthread_mutex_unlock(&mutex); }
|
inline void unlock() { pthread_mutex_unlock(&mutex); }
|
||||||
|
inline void signal() { pthread_cond_signal(&cond); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -157,6 +157,9 @@ static status_t getDisplayVisibleRegion(hwc_context_t* ctx, int dpy,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void pauseWFD(hwc_context_t *ctx, uint32_t pause) {
|
static void pauseWFD(hwc_context_t *ctx, uint32_t pause) {
|
||||||
|
/* TODO: Will remove pauseWFD once all the clients start using
|
||||||
|
* setWfdStatus to indicate the status of WFD display
|
||||||
|
*/
|
||||||
int dpy = HWC_DISPLAY_VIRTUAL;
|
int dpy = HWC_DISPLAY_VIRTUAL;
|
||||||
if(pause) {
|
if(pause) {
|
||||||
//WFD Pause
|
//WFD Pause
|
||||||
@@ -167,6 +170,24 @@ static void pauseWFD(hwc_context_t *ctx, uint32_t pause) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void setWfdStatus(hwc_context_t *ctx, uint32_t wfdStatus) {
|
||||||
|
|
||||||
|
ALOGD_IF(HWC_WFDDISPSYNC_LOG,
|
||||||
|
"%s: Received a binder call that WFD state is %s",
|
||||||
|
__FUNCTION__,getExternalDisplayState(wfdStatus));
|
||||||
|
int dpy = HWC_DISPLAY_VIRTUAL;
|
||||||
|
|
||||||
|
if(wfdStatus == EXTERNAL_OFFLINE) {
|
||||||
|
ctx->mWfdSyncLock.lock();
|
||||||
|
ctx->mWfdSyncLock.signal();
|
||||||
|
ctx->mWfdSyncLock.unlock();
|
||||||
|
} else if(wfdStatus == EXTERNAL_PAUSE) {
|
||||||
|
handle_pause(ctx, dpy);
|
||||||
|
} else if(wfdStatus == EXTERNAL_RESUME) {
|
||||||
|
handle_resume(ctx, dpy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
@@ -199,15 +220,17 @@ status_t QClient::notifyCallback(uint32_t command, const Parcel* inParcel,
|
|||||||
break;
|
break;
|
||||||
case IQService::SET_HSIC_DATA:
|
case IQService::SET_HSIC_DATA:
|
||||||
setHSIC(inParcel);
|
setHSIC(inParcel);
|
||||||
|
break;
|
||||||
case IQService::PAUSE_WFD:
|
case IQService::PAUSE_WFD:
|
||||||
pauseWFD(mHwcContext, inParcel->readInt32());
|
pauseWFD(mHwcContext, inParcel->readInt32());
|
||||||
break;
|
break;
|
||||||
|
case IQService::SET_WFD_STATUS:
|
||||||
|
setWfdStatus(mHwcContext,inParcel->readInt32());
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ret = NO_ERROR;
|
ret = NO_ERROR;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,14 +39,6 @@ namespace qhwc {
|
|||||||
#define HWC_UEVENT_SWITCH_STR "change@/devices/virtual/switch/"
|
#define HWC_UEVENT_SWITCH_STR "change@/devices/virtual/switch/"
|
||||||
#define HWC_UEVENT_THREAD_NAME "hwcUeventThread"
|
#define HWC_UEVENT_THREAD_NAME "hwcUeventThread"
|
||||||
|
|
||||||
/* External Display states */
|
|
||||||
enum {
|
|
||||||
EXTERNAL_OFFLINE = 0,
|
|
||||||
EXTERNAL_ONLINE,
|
|
||||||
EXTERNAL_PAUSE,
|
|
||||||
EXTERNAL_RESUME
|
|
||||||
};
|
|
||||||
|
|
||||||
static void setup(hwc_context_t* ctx, int dpy)
|
static void setup(hwc_context_t* ctx, int dpy)
|
||||||
{
|
{
|
||||||
ctx->mFBUpdate[dpy] = IFBUpdate::getObject(ctx, dpy);
|
ctx->mFBUpdate[dpy] = IFBUpdate::getObject(ctx, dpy);
|
||||||
@@ -145,9 +137,24 @@ static void teardownWfd(hwc_context_t* ctx) {
|
|||||||
ctx->mVirtualonExtActive = false;
|
ctx->mVirtualonExtActive = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Wait for few frames for SF to tear down the WFD session. */
|
|
||||||
usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
|
if(ctx->mVDSEnabled) {
|
||||||
* 2 / 1000);
|
ctx->mWfdSyncLock.lock();
|
||||||
|
ALOGD_IF(HWC_WFDDISPSYNC_LOG,
|
||||||
|
"%s: Waiting for wfd-teardown to be signalled",__FUNCTION__);
|
||||||
|
ctx->mWfdSyncLock.wait();
|
||||||
|
ALOGD_IF(HWC_WFDDISPSYNC_LOG,
|
||||||
|
"%s: Teardown signalled. Completed waiting in uevent thread",
|
||||||
|
__FUNCTION__);
|
||||||
|
ctx->mWfdSyncLock.unlock();
|
||||||
|
} else {
|
||||||
|
/*TODO: Remove this else block and have wait rather than usleep
|
||||||
|
once wfd module issues binder call on teardown.*/
|
||||||
|
|
||||||
|
/* For now, Wait for few frames for SF to tear down the WFD session.*/
|
||||||
|
usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
|
||||||
|
* 2 / 1000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_uevent(hwc_context_t* ctx, const char* udata, int len)
|
static void handle_uevent(hwc_context_t* ctx, const char* udata, int len)
|
||||||
@@ -166,7 +173,7 @@ static void handle_uevent(hwc_context_t* ctx, const char* udata, int len)
|
|||||||
|
|
||||||
int switch_state = getConnectedState(udata, len);
|
int switch_state = getConnectedState(udata, len);
|
||||||
|
|
||||||
ALOGE_IF(UEVENT_DEBUG,"%s: uevent recieved: %s switch state: %d",
|
ALOGE_IF(UEVENT_DEBUG,"%s: uevent received: %s switch state: %d",
|
||||||
__FUNCTION__,udata, switch_state);
|
__FUNCTION__,udata, switch_state);
|
||||||
|
|
||||||
switch(switch_state) {
|
switch(switch_state) {
|
||||||
|
|||||||
@@ -184,6 +184,7 @@ static int openFramebufferDevice(hwc_context_t *ctx)
|
|||||||
void initContext(hwc_context_t *ctx)
|
void initContext(hwc_context_t *ctx)
|
||||||
{
|
{
|
||||||
openFramebufferDevice(ctx);
|
openFramebufferDevice(ctx);
|
||||||
|
char value[PROPERTY_VALUE_MAX];
|
||||||
ctx->mMDP.version = qdutils::MDPVersion::getInstance().getMDPVersion();
|
ctx->mMDP.version = qdutils::MDPVersion::getInstance().getMDPVersion();
|
||||||
ctx->mMDP.hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay();
|
ctx->mMDP.hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay();
|
||||||
ctx->mMDP.panel = qdutils::MDPVersion::getInstance().getPanelType();
|
ctx->mMDP.panel = qdutils::MDPVersion::getInstance().getPanelType();
|
||||||
@@ -225,7 +226,14 @@ void initContext(hwc_context_t *ctx)
|
|||||||
ctx->mMDPComp[HWC_DISPLAY_PRIMARY] =
|
ctx->mMDPComp[HWC_DISPLAY_PRIMARY] =
|
||||||
MDPComp::getObject(ctx, HWC_DISPLAY_PRIMARY);
|
MDPComp::getObject(ctx, HWC_DISPLAY_PRIMARY);
|
||||||
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].connected = true;
|
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].connected = true;
|
||||||
ctx->mHWCVirtual = HWCVirtualBase::getObject();
|
|
||||||
|
ctx->mVDSEnabled = false;
|
||||||
|
if((property_get("persist.hwc.enable_vds", value, NULL) > 0)) {
|
||||||
|
if(atoi(value) != 0) {
|
||||||
|
ctx->mVDSEnabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctx->mHWCVirtual = HWCVirtualBase::getObject(ctx->mVDSEnabled);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
|
for (uint32_t i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
|
||||||
ctx->mHwcDebug[i] = new HwcDebug(i);
|
ctx->mHwcDebug[i] = new HwcDebug(i);
|
||||||
@@ -262,7 +270,6 @@ void initContext(hwc_context_t *ctx)
|
|||||||
|
|
||||||
// Read the system property to determine if downscale feature is enabled.
|
// Read the system property to determine if downscale feature is enabled.
|
||||||
ctx->mMDPDownscaleEnabled = false;
|
ctx->mMDPDownscaleEnabled = false;
|
||||||
char value[PROPERTY_VALUE_MAX];
|
|
||||||
if(property_get("sys.hwc.mdp_downscale_enabled", value, "false")
|
if(property_get("sys.hwc.mdp_downscale_enabled", value, "false")
|
||||||
&& !strcmp(value, "true")) {
|
&& !strcmp(value, "true")) {
|
||||||
ctx->mMDPDownscaleEnabled = true;
|
ctx->mMDPDownscaleEnabled = true;
|
||||||
@@ -642,6 +649,21 @@ int getMirrorModeOrientation(hwc_context_t *ctx) {
|
|||||||
return extOrientation;
|
return extOrientation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get External State names */
|
||||||
|
const char* getExternalDisplayState(uint32_t external_state) {
|
||||||
|
static const char* externalStates[EXTERNAL_MAXSTATES] = {0};
|
||||||
|
externalStates[EXTERNAL_OFFLINE] = STR(EXTERNAL_OFFLINE);
|
||||||
|
externalStates[EXTERNAL_ONLINE] = STR(EXTERNAL_ONLINE);
|
||||||
|
externalStates[EXTERNAL_PAUSE] = STR(EXTERNAL_PAUSE);
|
||||||
|
externalStates[EXTERNAL_RESUME] = STR(EXTERNAL_RESUME);
|
||||||
|
|
||||||
|
if(external_state >= EXTERNAL_MAXSTATES) {
|
||||||
|
return "EXTERNAL_INVALID";
|
||||||
|
}
|
||||||
|
|
||||||
|
return externalStates[external_state];
|
||||||
|
}
|
||||||
|
|
||||||
bool isDownscaleRequired(hwc_layer_1_t const* layer) {
|
bool isDownscaleRequired(hwc_layer_1_t const* layer) {
|
||||||
hwc_rect_t displayFrame = layer->displayFrame;
|
hwc_rect_t displayFrame = layer->displayFrame;
|
||||||
hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
|
hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
|
||||||
|
|||||||
@@ -39,6 +39,8 @@
|
|||||||
#define MAX_NUM_APP_LAYERS 32
|
#define MAX_NUM_APP_LAYERS 32
|
||||||
#define MIN_DISPLAY_XRES 200
|
#define MIN_DISPLAY_XRES 200
|
||||||
#define MIN_DISPLAY_YRES 200
|
#define MIN_DISPLAY_YRES 200
|
||||||
|
#define HWC_WFDDISPSYNC_LOG 0
|
||||||
|
#define STR(f) #f;
|
||||||
|
|
||||||
//Fwrd decls
|
//Fwrd decls
|
||||||
struct hwc_context_t;
|
struct hwc_context_t;
|
||||||
@@ -154,6 +156,15 @@ enum {
|
|||||||
HWC_FORMAT_RB_SWAP = 0x00000040,
|
HWC_FORMAT_RB_SWAP = 0x00000040,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* External Display states */
|
||||||
|
enum {
|
||||||
|
EXTERNAL_OFFLINE = 0,
|
||||||
|
EXTERNAL_ONLINE,
|
||||||
|
EXTERNAL_PAUSE,
|
||||||
|
EXTERNAL_RESUME,
|
||||||
|
EXTERNAL_MAXSTATES
|
||||||
|
};
|
||||||
|
|
||||||
class LayerRotMap {
|
class LayerRotMap {
|
||||||
public:
|
public:
|
||||||
LayerRotMap() { reset(); }
|
LayerRotMap() { reset(); }
|
||||||
@@ -280,6 +291,9 @@ void calcExtDisplayPosition(hwc_context_t *ctx,
|
|||||||
// BufferMirrirMode(Sidesync)
|
// BufferMirrirMode(Sidesync)
|
||||||
int getMirrorModeOrientation(hwc_context_t *ctx);
|
int getMirrorModeOrientation(hwc_context_t *ctx);
|
||||||
|
|
||||||
|
/* Get External State names */
|
||||||
|
const char* getExternalDisplayState(uint32_t external_state);
|
||||||
|
|
||||||
// Handles wfd Pause and resume events
|
// Handles wfd Pause and resume events
|
||||||
void handle_pause(hwc_context_t *ctx, int dpy);
|
void handle_pause(hwc_context_t *ctx, int dpy);
|
||||||
void handle_resume(hwc_context_t *ctx, int dpy);
|
void handle_resume(hwc_context_t *ctx, int dpy);
|
||||||
@@ -516,14 +530,21 @@ struct hwc_context_t {
|
|||||||
//Used for SideSync feature
|
//Used for SideSync feature
|
||||||
//which overrides the mExtOrientation
|
//which overrides the mExtOrientation
|
||||||
bool mBufferMirrorMode;
|
bool mBufferMirrorMode;
|
||||||
|
// Used to synchronize between WFD and Display modules
|
||||||
|
mutable Locker mWfdSyncLock;
|
||||||
|
|
||||||
qhwc::LayerRotMap *mLayerRotMap[HWC_NUM_DISPLAY_TYPES];
|
qhwc::LayerRotMap *mLayerRotMap[HWC_NUM_DISPLAY_TYPES];
|
||||||
// Panel reset flag will be set if BTA check fails
|
// Panel reset flag will be set if BTA check fails
|
||||||
bool mPanelResetStatus;
|
bool mPanelResetStatus;
|
||||||
// number of active Displays
|
// number of active Displays
|
||||||
int numActiveDisplays;
|
int numActiveDisplays;
|
||||||
// Downscale feature switch, set via system the property
|
// Downscale feature switch, set via system property
|
||||||
// sys.hwc.mdp_downscale_enabled
|
// sys.hwc.mdp_downscale_enabled
|
||||||
bool mMDPDownscaleEnabled;
|
bool mMDPDownscaleEnabled;
|
||||||
|
// Is WFD enabled through VDS solution ?
|
||||||
|
// This can be set via system property
|
||||||
|
// persist.hwc.enable_vds
|
||||||
|
bool mVDSEnabled;
|
||||||
struct gpu_hint_info mGPUHintInfo;
|
struct gpu_hint_info mGPUHintInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -35,19 +35,17 @@
|
|||||||
using namespace qhwc;
|
using namespace qhwc;
|
||||||
using namespace overlay;
|
using namespace overlay;
|
||||||
|
|
||||||
HWCVirtualBase* HWCVirtualBase::getObject() {
|
HWCVirtualBase* HWCVirtualBase::getObject(bool isVDSEnabled) {
|
||||||
char property[PROPERTY_VALUE_MAX];
|
|
||||||
|
|
||||||
if((property_get("persist.hwc.enable_vds", property, NULL) > 0)) {
|
if(isVDSEnabled) {
|
||||||
if(atoi(property) != 0) {
|
ALOGD_IF(HWCVIRTUAL_LOG, "%s: VDS is enabled for Virtual display",
|
||||||
ALOGD_IF(HWCVIRTUAL_LOG, "%s: VDS is enabled for Virtual display",
|
__FUNCTION__);
|
||||||
__FUNCTION__);
|
return new HWCVirtualVDS();
|
||||||
return new HWCVirtualVDS();
|
} else {
|
||||||
}
|
ALOGD_IF(HWCVIRTUAL_LOG, "%s: V4L2 is enabled for Virtual display",
|
||||||
|
__FUNCTION__);
|
||||||
|
return new HWCVirtualV4L2();
|
||||||
}
|
}
|
||||||
ALOGD_IF(HWCVIRTUAL_LOG, "%s: V4L2 is enabled for Virtual display",
|
|
||||||
__FUNCTION__);
|
|
||||||
return new HWCVirtualV4L2();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HWCVirtualVDS::init(hwc_context_t *ctx) {
|
void HWCVirtualVDS::init(hwc_context_t *ctx) {
|
||||||
@@ -84,6 +82,9 @@ void HWCVirtualVDS::destroy(hwc_context_t *ctx, size_t /*numDisplays*/,
|
|||||||
if(!Writeback::getInstance()->setSecure(false)) {
|
if(!Writeback::getInstance()->setSecure(false)) {
|
||||||
ALOGE("Failure while attempting to reset WB session.");
|
ALOGE("Failure while attempting to reset WB session.");
|
||||||
}
|
}
|
||||||
|
ctx->mWfdSyncLock.lock();
|
||||||
|
ctx->mWfdSyncLock.signal();
|
||||||
|
ctx->mWfdSyncLock.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public:
|
|||||||
explicit HWCVirtualBase(){};
|
explicit HWCVirtualBase(){};
|
||||||
virtual ~HWCVirtualBase(){};
|
virtual ~HWCVirtualBase(){};
|
||||||
// instantiates and returns the pointer to VDS or V4L2 object.
|
// instantiates and returns the pointer to VDS or V4L2 object.
|
||||||
static HWCVirtualBase* getObject();
|
static HWCVirtualBase* getObject(bool isVDSEnabled);
|
||||||
virtual int prepare(hwc_composer_device_1 *dev,
|
virtual int prepare(hwc_composer_device_1 *dev,
|
||||||
hwc_display_contents_1_t* list) = 0;
|
hwc_display_contents_1_t* list) = 0;
|
||||||
virtual int set(hwc_context_t *ctx, hwc_display_contents_1_t *list) = 0;
|
virtual int set(hwc_context_t *ctx, hwc_display_contents_1_t *list) = 0;
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ public:
|
|||||||
SET_HSIC_DATA, // Set HSIC on dspp
|
SET_HSIC_DATA, // Set HSIC on dspp
|
||||||
GET_DISPLAY_VISIBLE_REGION, // Get the visibleRegion for dpy
|
GET_DISPLAY_VISIBLE_REGION, // Get the visibleRegion for dpy
|
||||||
PAUSE_WFD, // Pause/Resume WFD
|
PAUSE_WFD, // Pause/Resume WFD
|
||||||
|
SET_WFD_STATUS, // Set if wfd connection is on/off
|
||||||
COMMAND_LIST_END = 400,
|
COMMAND_LIST_END = 400,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -87,4 +87,7 @@ inline android::status_t pauseWFD(uint32_t pause) {
|
|||||||
return sendSingleParam(qService::IQService::PAUSE_WFD, pause);
|
return sendSingleParam(qService::IQService::PAUSE_WFD, pause);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline android::status_t setWfdStatus(uint32_t wfdStatus) {
|
||||||
|
return sendSingleParam(qService::IQService::SET_WFD_STATUS, wfdStatus);
|
||||||
|
}
|
||||||
#endif /* end of include guard: QSERVICEUTILS_H */
|
#endif /* end of include guard: QSERVICEUTILS_H */
|
||||||
|
|||||||
Reference in New Issue
Block a user