hwc: clean up overlay for external from the draw thread only

Cleanup overlay for external from the draw thread. If done from the uevent
thread, its possible that the object being used by draw thread is deleted by
uevent thread.

This also removes unnecessary side-effects where libexternal sets states in
hwc, whereas, it could be set from hwc itself. There should be no need for
libexternal to modify states in hwc.

Bug: 7335863 (partial fix)
Change-Id: If07483e640abae2ced2418e0d5c8f278f8c6ec33
Signed-off-by: Iliyan Malchev <malchev@google.com>
This commit is contained in:
Saurabh Shah
2012-10-12 17:00:39 -07:00
committed by Iliyan Malchev
parent f83d4480f2
commit 1a8cda0b2c
5 changed files with 54 additions and 73 deletions

View File

@@ -408,16 +408,6 @@ void ExternalDisplay::setExternalDisplay(int connected)
const char* prop = (connected) ? "1" : "0"; const char* prop = (connected) ? "1" : "0";
// set system property // set system property
property_set("hw.hdmiON", prop); property_set("hw.hdmiON", prop);
ALOGD("%s sending hotplug: connected = %d", __FUNCTION__,connected);
//Inform SF. Disabled until SF calls unblank
ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive = false;
ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected = connected;
//TODO ideally should be done on "connected" not "online"
ctx->proc->hotplug(ctx->proc, HWC_DISPLAY_EXTERNAL, connected);
if(connected == false)
ctx->priv_proc.onExtDisconnect(ctx->priv_proc);
} }
return; return;
} }

View File

@@ -79,7 +79,8 @@ static void hwc_registerProcs(struct hwc_composer_device_1* dev,
//Helper //Helper
static void reset(hwc_context_t *ctx, int numDisplays) { static void reset(hwc_context_t *ctx, int numDisplays) {
memset(ctx->listStats, 0, sizeof(ctx->listStats)); memset(ctx->listStats, 0, sizeof(ctx->listStats));
for(int i = 0; i < numDisplays; i++){ for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++){
ctx->overlayInUse[i] = false;
ctx->listStats[i].yuvIndex = -1; ctx->listStats[i].yuvIndex = -1;
} }
} }
@@ -87,17 +88,21 @@ static void reset(hwc_context_t *ctx, int numDisplays) {
static int hwc_prepare_primary(hwc_composer_device_1 *dev, static int hwc_prepare_primary(hwc_composer_device_1 *dev,
hwc_display_contents_1_t *list) { hwc_display_contents_1_t *list) {
hwc_context_t* ctx = (hwc_context_t*)(dev); hwc_context_t* ctx = (hwc_context_t*)(dev);
ctx->overlayInUse[HWC_DISPLAY_PRIMARY] = false;
if (LIKELY(list && list->numHwLayers > 1)) { if (LIKELY(list && list->numHwLayers > 1) &&
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isActive) {
uint32_t last = list->numHwLayers - 1; uint32_t last = list->numHwLayers - 1;
hwc_layer_1_t *fblayer = &list->hwLayers[last]; hwc_layer_1_t *fbLayer = &list->hwLayers[last];
setListStats(ctx, list, HWC_DISPLAY_PRIMARY); if(fbLayer->handle) {
if(VideoOverlay::prepare(ctx, list, HWC_DISPLAY_PRIMARY)) { setListStats(ctx, list, HWC_DISPLAY_PRIMARY);
ctx->overlayInUse[HWC_DISPLAY_PRIMARY] = true; if(VideoOverlay::prepare(ctx, list, HWC_DISPLAY_PRIMARY)) {
} else if(MDPComp::configure(ctx, list)) { ctx->overlayInUse[HWC_DISPLAY_PRIMARY] = true;
ctx->overlayInUse[HWC_DISPLAY_PRIMARY] = true; } else if(MDPComp::configure(ctx, list)) {
} else { ctx->overlayInUse[HWC_DISPLAY_PRIMARY] = true;
ctx->overlayInUse[HWC_DISPLAY_PRIMARY] = false; } else {
ctx->overlayInUse[HWC_DISPLAY_PRIMARY] = false;
}
} }
} }
return 0; return 0;
@@ -105,9 +110,7 @@ static int hwc_prepare_primary(hwc_composer_device_1 *dev,
static int hwc_prepare_external(hwc_composer_device_1 *dev, static int hwc_prepare_external(hwc_composer_device_1 *dev,
hwc_display_contents_1_t *list) { hwc_display_contents_1_t *list) {
hwc_context_t* ctx = (hwc_context_t*)(dev); hwc_context_t* ctx = (hwc_context_t*)(dev);
ctx->overlayInUse[HWC_DISPLAY_EXTERNAL] = false;
if (LIKELY(list && list->numHwLayers > 1) && if (LIKELY(list && list->numHwLayers > 1) &&
ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive && ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive &&
@@ -116,15 +119,18 @@ static int hwc_prepare_external(hwc_composer_device_1 *dev,
setListStats(ctx, list, HWC_DISPLAY_EXTERNAL); setListStats(ctx, list, HWC_DISPLAY_EXTERNAL);
uint32_t last = list->numHwLayers - 1; uint32_t last = list->numHwLayers - 1;
hwc_layer_1_t *fblayer = &list->hwLayers[last]; hwc_layer_1_t *fbLayer = &list->hwLayers[last];
if(UIMirrorOverlay::prepare(ctx, fblayer)) { if(fbLayer->handle) {
ctx->overlayInUse[HWC_DISPLAY_EXTERNAL] = true; if(UIMirrorOverlay::prepare(ctx, fbLayer)) {
} ctx->overlayInUse[HWC_DISPLAY_EXTERNAL] = true;
}
if(VideoOverlay::prepare(ctx, list, HWC_DISPLAY_EXTERNAL)) { if(VideoOverlay::prepare(ctx, list, HWC_DISPLAY_EXTERNAL)) {
ctx->overlayInUse[HWC_DISPLAY_EXTERNAL] = true; ctx->overlayInUse[HWC_DISPLAY_EXTERNAL] = true;
} else { } else {
ctx->mOverlay[HWC_DISPLAY_EXTERNAL]->setState(ovutils::OV_UI_MIRROR); ctx->mOverlay[HWC_DISPLAY_EXTERNAL]->setState(
ovutils::OV_UI_MIRROR);
}
} }
} }
return 0; return 0;
@@ -135,7 +141,6 @@ static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays,
{ {
int ret = 0; int ret = 0;
hwc_context_t* ctx = (hwc_context_t*)(dev); hwc_context_t* ctx = (hwc_context_t*)(dev);
reset(ctx, numDisplays); reset(ctx, numDisplays);
//If securing of h/w in progress skip comp using overlay. //If securing of h/w in progress skip comp using overlay.
@@ -143,20 +148,15 @@ static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays,
for (uint32_t i = 0; i < numDisplays; i++) { for (uint32_t i = 0; i < numDisplays; i++) {
hwc_display_contents_1_t *list = displays[i]; hwc_display_contents_1_t *list = displays[i];
if(list && list->numHwLayers) { switch(i) {
uint32_t last = list->numHwLayers - 1; case HWC_DISPLAY_PRIMARY:
if(list->hwLayers[last].handle != NULL) { ret = hwc_prepare_primary(dev, list);
switch(i) { break;
case HWC_DISPLAY_PRIMARY: case HWC_DISPLAY_EXTERNAL:
ret = hwc_prepare_primary(dev, list); ret = hwc_prepare_external(dev, list);
break; break;
case HWC_DISPLAY_EXTERNAL: default:
ret = hwc_prepare_external(dev, list); ret = -EINVAL;
break;
default:
ret = -EINVAL;
}
}
} }
} }
return ret; return ret;
@@ -254,9 +254,6 @@ static int hwc_query(struct hwc_composer_device_1* dev,
} }
static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) { static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
if(!ctx->overlayInUse[HWC_DISPLAY_PRIMARY])
ctx->mOverlay[HWC_DISPLAY_PRIMARY]->setState(ovutils::OV_CLOSED);
if (LIKELY(list && list->numHwLayers > 1) && if (LIKELY(list && list->numHwLayers > 1) &&
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isActive) { ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isActive) {
uint32_t last = list->numHwLayers - 1; uint32_t last = list->numHwLayers - 1;
@@ -279,8 +276,6 @@ static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
static int hwc_set_external(hwc_context_t *ctx, static int hwc_set_external(hwc_context_t *ctx,
hwc_display_contents_1_t* list) { hwc_display_contents_1_t* list) {
Locker::Autolock _l(ctx->mExtSetLock); Locker::Autolock _l(ctx->mExtSetLock);
if(!ctx->overlayInUse[HWC_DISPLAY_EXTERNAL])
ctx->mOverlay[HWC_DISPLAY_EXTERNAL]->setState(ovutils::OV_CLOSED);
if (LIKELY(list && list->numHwLayers > 1) && if (LIKELY(list && list->numHwLayers > 1) &&
ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive && ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive &&
@@ -310,6 +305,11 @@ static int hwc_set(hwc_composer_device_1 *dev,
hwc_context_t* ctx = (hwc_context_t*)(dev); hwc_context_t* ctx = (hwc_context_t*)(dev);
Locker::Autolock _l(ctx->mBlankLock); Locker::Autolock _l(ctx->mBlankLock);
for(uint32_t i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
if(!ctx->overlayInUse[i])
ctx->mOverlay[i]->setState(ovutils::OV_CLOSED);
}
for (uint32_t i = 0; i < numDisplays; i++) { for (uint32_t i = 0; i < numDisplays; i++) {
hwc_display_contents_1_t* list = displays[i]; hwc_display_contents_1_t* list = displays[i];
switch(i) { switch(i) {

View File

@@ -53,14 +53,23 @@ static void handle_uevent(hwc_context_t* ctx, const char* udata, int len)
// for now just parsing onlin/offline info is enough // for now just parsing onlin/offline info is enough
if (hdmi) { if (hdmi) {
str = udata; str = udata;
int connected = 0; int connected = -1; //some event other than online and offline .. e.g
if(!(strncmp(str,"online@",strlen("online@")))) { if(!(strncmp(str,"online@",strlen("online@")))) {
//Disabled until SF calls unblank
ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive = false;
connected = 1; connected = 1;
ctx->mExtDisplay->setExternalDisplay(connected);;
} else if(!(strncmp(str,"offline@",strlen("offline@")))) { } else if(!(strncmp(str,"offline@",strlen("offline@")))) {
//Disabled until SF calls unblank
ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive = false;
connected = 0; connected = 0;
Locker::Autolock _l(ctx->mExtSetLock); }
ctx->mExtDisplay->setExternalDisplay(connected);; if(connected != -1) { //either we got online or offline
ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected = connected;
ctx->mExtDisplay->setExternalDisplay(connected);
ALOGD("%s sending hotplug: connected = %d", __FUNCTION__,connected);
Locker::Autolock _l(ctx->mExtSetLock); //hwc comp could be on
//TODO ideally should be done on "connected" not "online"
ctx->proc->hotplug(ctx->proc, HWC_DISPLAY_EXTERNAL, connected);
} }
} }
} }

View File

@@ -48,13 +48,6 @@ static void openFramebufferDevice(hwc_context_t *ctx)
} }
} }
static void onExtDisconnect(const hwc_context_t::Callbacks& priv_proc) {
hwc_context_t *ctx = priv_proc.ctx;
overlay::Overlay& ov = *(ctx->mOverlay[HWC_DISPLAY_EXTERNAL]);
// Set overlay state
ov.setState(ovutils::OV_CLOSED);
}
void initContext(hwc_context_t *ctx) void initContext(hwc_context_t *ctx)
{ {
openFramebufferDevice(ctx); openFramebufferDevice(ctx);
@@ -73,9 +66,6 @@ void initContext(hwc_context_t *ctx)
pthread_cond_init(&(ctx->vstate.cond), NULL); pthread_cond_init(&(ctx->vstate.cond), NULL);
ctx->vstate.enable = false; ctx->vstate.enable = false;
ctx->priv_proc.onExtDisconnect = onExtDisconnect;
ctx->priv_proc.ctx = ctx;
ALOGI("Initializing Qualcomm Hardware Composer"); ALOGI("Initializing Qualcomm Hardware Composer");
ALOGI("MDP version: %d", ctx->mMDP.version); ALOGI("MDP version: %d", ctx->mMDP.version);
} }

View File

@@ -176,14 +176,6 @@ struct hwc_context_t {
hwc_composer_device_1_t device; hwc_composer_device_1_t device;
const hwc_procs_t* proc; const hwc_procs_t* proc;
//Private hwc handlers
struct Callbacks {
void (*onExtDisconnect)(const Callbacks& priv_proc);
hwc_context_t *ctx;
};
Callbacks priv_proc;
int overlayInUse[HWC_NUM_DISPLAY_TYPES]; int overlayInUse[HWC_NUM_DISPLAY_TYPES];
//Framebuffer device //Framebuffer device