hwc: enable dual display on hwc 1.1
Enable dual display on HWC 1.1; video uses overlay.
Bug: 7124159
Change-Id: I8333e46cfc74072f6259fba2b82368f0dd52b6df
Signed-off-by: Iliyan Malchev <malchev@google.com>
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index f8f7f13..c72d882 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -86,18 +86,17 @@
static int hwc_prepare_primary(hwc_composer_device_1 *dev,
hwc_display_contents_1_t *list) {
hwc_context_t* ctx = (hwc_context_t*)(dev);
+ ctx->overlayInUse[HWC_DISPLAY_PRIMARY] = false;
if (LIKELY(list && list->numHwLayers)) {
uint32_t last = list->numHwLayers - 1;
hwc_layer_1_t *fblayer = &list->hwLayers[last];
setListStats(ctx, list, HWC_DISPLAY_PRIMARY);
if(VideoOverlay::prepare(ctx, list, HWC_DISPLAY_PRIMARY)) {
- ctx->overlayInUse = true;
- } else if(UIMirrorOverlay::prepare(ctx, fblayer)) {
- ctx->overlayInUse = true;
+ ctx->overlayInUse[HWC_DISPLAY_PRIMARY] = true;
} else if(MDPComp::configure(ctx, list)) {
- ctx->overlayInUse = true;
+ ctx->overlayInUse[HWC_DISPLAY_PRIMARY] = true;
} else {
- ctx->overlayInUse = false;
+ ctx->overlayInUse[HWC_DISPLAY_PRIMARY] = false;
}
}
return 0;
@@ -107,9 +106,25 @@
hwc_display_contents_1_t *list) {
hwc_context_t* ctx = (hwc_context_t*)(dev);
- if (LIKELY(list && list->numHwLayers)) {
- //setListStats(ctx, list, HWC_DISPLAY_EXTERNAL);
- //Nothing to do for now
+ ctx->overlayInUse[HWC_DISPLAY_EXTERNAL] = false;
+
+ if (LIKELY(list && list->numHwLayers) &&
+ ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive &&
+ ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected) {
+
+ setListStats(ctx, list, HWC_DISPLAY_EXTERNAL);
+
+ uint32_t last = list->numHwLayers - 1;
+ hwc_layer_1_t *fblayer = &list->hwLayers[last];
+ if(UIMirrorOverlay::prepare(ctx, fblayer)) {
+ ctx->overlayInUse[HWC_DISPLAY_EXTERNAL] = true;
+ }
+
+ if(VideoOverlay::prepare(ctx, list, HWC_DISPLAY_EXTERNAL)) {
+ ctx->overlayInUse[HWC_DISPLAY_EXTERNAL] = true;
+ } else {
+ ctx->mOverlay[HWC_DISPLAY_EXTERNAL]->setState(ovutils::OV_UI_MIRROR);
+ }
}
return 0;
}
@@ -119,7 +134,6 @@
{
int ret = 0;
hwc_context_t* ctx = (hwc_context_t*)(dev);
- ctx->overlayInUse = false;
reset(ctx, numDisplays);
@@ -200,7 +214,7 @@
case HWC_DISPLAY_PRIMARY:
if(blank) {
Locker::Autolock _l(ctx->mBlankLock);
- ctx->mOverlay->setState(ovutils::OV_CLOSED);
+ ctx->mOverlay[dpy]->setState(ovutils::OV_CLOSED);
ret = ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_POWERDOWN);
} else {
ret = ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_UNBLANK);
@@ -244,9 +258,8 @@
ALOGI("fps: %d", value[0]);
break;
case HWC_DISPLAY_TYPES_SUPPORTED:
- //TODO Enable later
- //if(ctx->mMDP.hasOverlay)
- //supported |= HWC_DISPLAY_EXTERNAL_BIT;
+ if(ctx->mMDP.hasOverlay)
+ supported |= HWC_DISPLAY_EXTERNAL_BIT;
value[0] = supported;
break;
default:
@@ -257,24 +270,22 @@
}
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)) {
- ctx->mFbDev->compositionComplete(ctx->mFbDev);
+ uint32_t last = list->numHwLayers - 1;
+ hwc_layer_1_t *fbLayer = &list->hwLayers[last];
+
hwc_sync(ctx, list, HWC_DISPLAY_PRIMARY);
VideoOverlay::draw(ctx, list, HWC_DISPLAY_PRIMARY);
MDPComp::draw(ctx, list);
- uint32_t last = list->numHwLayers - 1;
- hwc_layer_1_t *fblayer = &list->hwLayers[last];
- if(ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive) {
- UIMirrorOverlay::draw(ctx, fblayer);
- }
- if(ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive) {
- ctx->mExtDisplay->post();
- }
+
//TODO We dont check for SKIP flag on this layer because we need PAN
//always. Last layer is always FB
if(list->hwLayers[last].compositionType == HWC_FRAMEBUFFER_TARGET) {
- ctx->mFbDev->post(ctx->mFbDev, list->hwLayers[last].handle);
+ ctx->mFbDev->post(ctx->mFbDev, fbLayer->handle);
}
}
return 0;
@@ -282,17 +293,49 @@
static int hwc_set_external(hwc_context_t *ctx,
hwc_display_contents_1_t* list) {
- if (LIKELY(list && list->numHwLayers)) {
- //hwc_sync(ctx, list, HWC_DISPLAY_EXTERNAL);
+
+ if(!ctx->overlayInUse[HWC_DISPLAY_EXTERNAL])
+ ctx->mOverlay[HWC_DISPLAY_EXTERNAL]->setState(ovutils::OV_CLOSED);
+
+ if (LIKELY(list && list->numHwLayers) &&
+ ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive &&
+ ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected) {
uint32_t last = list->numHwLayers - 1;
- if(list->hwLayers[last].compositionType == HWC_FRAMEBUFFER_TARGET &&
- ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive) {
- //ctx->mExtDisplay->post(list->hwLayers[last].handle);
+ hwc_layer_1_t *fbLayer = &list->hwLayers[last];
+
+ hwc_sync(ctx, list, HWC_DISPLAY_EXTERNAL);
+
+ VideoOverlay::draw(ctx, list, HWC_DISPLAY_EXTERNAL);
+
+ private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
+ if(fbLayer->compositionType == HWC_FRAMEBUFFER_TARGET && hnd) {
+ UIMirrorOverlay::draw(ctx, fbLayer);
+ ctx->mExtDisplay->post();
}
}
return 0;
}
+static bool isGpuUsed(hwc_context_t *ctx,
+ size_t numDisplays,
+ hwc_display_contents_1_t** displays)
+{
+ bool isUsed = false;
+ for (uint32_t i = 0; i < numDisplays; i++) {
+ hwc_display_contents_1_t* list = displays[i];
+ if (list && list->numHwLayers) {
+ uint32_t last = list->numHwLayers - 1;
+ hwc_layer_1_t *fbLayer = &list->hwLayers[last];
+ if(!(fbLayer->flags & HWC_SKIP_LAYER)) {
+ isUsed = true;
+ break;
+ }
+
+ }
+ }
+ return isUsed;
+}
+
static int hwc_set(hwc_composer_device_1 *dev,
size_t numDisplays,
hwc_display_contents_1_t** displays)
@@ -300,16 +343,21 @@
int ret = 0;
hwc_context_t* ctx = (hwc_context_t*)(dev);
Locker::Autolock _l(ctx->mBlankLock);
- if(!ctx->overlayInUse)
- ctx->mOverlay->setState(ovutils::OV_CLOSED);
+
+ if(isGpuUsed(ctx, numDisplays, displays)) {
+ //Call glFinish, only if gpu is used
+ ctx->mFbDev->compositionComplete(ctx->mFbDev);
+ }
for (uint32_t i = 0; i < numDisplays; i++) {
hwc_display_contents_1_t* list = displays[i];
switch(i) {
case HWC_DISPLAY_PRIMARY:
ret = hwc_set_primary(ctx, list);
+ break;
case HWC_DISPLAY_EXTERNAL:
ret = hwc_set_external(ctx, list);
+ break;
default:
ret = -EINVAL;
}
@@ -320,18 +368,26 @@
int hwc_getDisplayConfigs(struct hwc_composer_device_1* dev, int disp,
uint32_t* configs, size_t* numConfigs) {
int ret = 0;
+ hwc_context_t* ctx = (hwc_context_t*)(dev);
//in 1.1 there is no way to choose a config, report as config id # 0
//This config is passed to getDisplayAttributes. Ignore for now.
- if(*numConfigs == 1)
- *configs = 0;
switch(disp) {
case HWC_DISPLAY_PRIMARY:
- ret = 0;
+ if(*numConfigs > 0) {
+ configs[0] = 0;
+ *numConfigs = 1;
+ }
+ ret = 0; //NO_ERROR
break;
case HWC_DISPLAY_EXTERNAL:
- //Hack until hotplug is supported.
- //This makes framework ignore external display.
- ret = -1;
+ ret = -1; //Not connected
+ if(ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected) {
+ ret = 0; //NO_ERROR
+ if(*numConfigs > 0) {
+ configs[0] = 0;
+ *numConfigs = 1;
+ }
+ }
break;
}
return ret;
@@ -341,6 +397,11 @@
uint32_t config, const uint32_t* attributes, int32_t* values) {
hwc_context_t* ctx = (hwc_context_t*)(dev);
+ //If hotpluggable displays are inactive return error
+ if(disp == HWC_DISPLAY_EXTERNAL && !ctx->dpyAttr[disp].connected) {
+ return -1;
+ }
+
//From HWComposer
static const uint32_t DISPLAY_ATTRIBUTES[] = {
HWC_DISPLAY_VSYNC_PERIOD,
@@ -361,11 +422,13 @@
break;
case HWC_DISPLAY_WIDTH:
values[i] = ctx->dpyAttr[disp].xres;
- ALOGD("%s width = %d",__FUNCTION__, ctx->dpyAttr[disp].xres);
+ ALOGD("%s disp = %d, width = %d",__FUNCTION__, disp,
+ ctx->dpyAttr[disp].xres);
break;
case HWC_DISPLAY_HEIGHT:
values[i] = ctx->dpyAttr[disp].yres;
- ALOGD("%s height = %d",__FUNCTION__, ctx->dpyAttr[disp].yres);
+ ALOGD("%s disp = %d, height = %d",__FUNCTION__, disp,
+ ctx->dpyAttr[disp].yres);
break;
case HWC_DISPLAY_DPI_X:
values[i] = (int32_t) (ctx->dpyAttr[disp].xdpi*1000.0);
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 6d40741..4c4a9a0 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -191,7 +191,7 @@
private_handle_t *hnd = (private_handle_t *)layer->handle;
- overlay::Overlay& ov = *(ctx->mOverlay);
+ overlay::Overlay& ov = *(ctx->mOverlay[HWC_DISPLAY_PRIMARY]);
if(!hnd) {
ALOGE("%s: layer handle is NULL", __FUNCTION__);
@@ -610,7 +610,7 @@
configure_var_pipe(ctx);
#endif
- overlay::Overlay& ov = *(ctx->mOverlay);
+ overlay::Overlay& ov = *(ctx->mOverlay[HWC_DISPLAY_PRIMARY]);
ovutils::eOverlayState state = ov.getState();
if (current_frame.count == 1) {
@@ -667,7 +667,7 @@
return -1;
}
- overlay::Overlay& ov = *(ctx->mOverlay);
+ overlay::Overlay& ov = *(ctx->mOverlay[HWC_DISPLAY_PRIMARY]);
int numHwLayers = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
for(int i = 0; i < numHwLayers; i++ )
diff --git a/libhwcomposer/hwc_uimirror.cpp b/libhwcomposer/hwc_uimirror.cpp
index 1b81421..62b7efd 100644
--- a/libhwcomposer/hwc_uimirror.cpp
+++ b/libhwcomposer/hwc_uimirror.cpp
@@ -26,30 +26,6 @@
namespace qhwc {
-
-// Function to get the orientation of UI on primary.
-// When external display is connected, the primary UI is
-// fixed to landscape by the phone window manager.
-// Return the landscape orientation based on w and hw of primary
-int getDeviceOrientation() {
- int orientation = 0;
- //Calculate the rect for primary based on whether the supplied
- //position
- //is within or outside bounds.
- const int fbWidth =
- ovutils::FrameBufferInfo::getInstance()->getWidth();
- const int fbHeight =
- ovutils::FrameBufferInfo::getInstance()->getHeight();
- if(fbWidth >= fbHeight) {
- // landscape panel
- orientation = overlay::utils::OVERLAY_TRANSFORM_0;
- } else {
- // portrait panel
- orientation = overlay::utils::OVERLAY_TRANSFORM_ROT_90;
- }
- return orientation;
-}
-
//Static Members
ovutils::eOverlayState UIMirrorOverlay::sState = ovutils::OV_CLOSED;
bool UIMirrorOverlay::sIsUiMirroringOn = false;
@@ -61,83 +37,75 @@
//Prepare the overlay for the UI mirroring
bool UIMirrorOverlay::prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer) {
- sState = ovutils::OV_CLOSED;
- sIsUiMirroringOn = false;
+ reset();
if(!ctx->mMDP.hasOverlay) {
ALOGD_IF(HWC_UI_MIRROR, "%s, this hw doesnt support mirroring",
__FUNCTION__);
return false;
}
- // If external display is active
- if(isExternalActive(ctx)) {
- sState = ovutils::OV_UI_MIRROR;
- configure(ctx, fblayer);
+
+ sState = ovutils::OV_UI_MIRROR;
+ ovutils::eOverlayState newState = ctx->mOverlay[HWC_DISPLAY_EXTERNAL]->getState();
+ if(newState == ovutils::OV_UI_VIDEO_TV) {
+ sState = newState;
}
+
+ configure(ctx, fblayer);
return sIsUiMirroringOn;
}
// Configure
bool UIMirrorOverlay::configure(hwc_context_t *ctx, hwc_layer_1_t *layer)
{
- if (LIKELY(ctx->mOverlay)) {
- overlay::Overlay& ov = *(ctx->mOverlay);
+ if (LIKELY(ctx->mOverlay[HWC_DISPLAY_EXTERNAL])) {
+ overlay::Overlay& ov = *(ctx->mOverlay[HWC_DISPLAY_EXTERNAL]);
// Set overlay state
ov.setState(sState);
- framebuffer_device_t *fbDev = ctx->mFbDev;
- if(fbDev) {
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
- // Determine the RGB pipe for UI depending on the state
- ovutils::eDest dest = ovutils::OV_PIPE_ALL;
- if (sState == ovutils::OV_2D_TRUE_UI_MIRROR) {
- // True UI mirroring state: external RGB pipe is OV_PIPE2
- dest = ovutils::OV_PIPE2;
- } else if (sState == ovutils::OV_UI_MIRROR) {
- // UI-only mirroring state: external RGB pipe is OV_PIPE0
- dest = ovutils::OV_PIPE0;
- }
+ private_handle_t *hnd = (private_handle_t *)layer->handle;
+ ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
+ // Determine the RGB pipe for UI depending on the state
+ ovutils::eDest dest = ovutils::OV_PIPE0;
- ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
- if(ctx->mSecureMode) {
- ovutils::setMdpFlags(mdpFlags,
- ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
- }
+ ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
+ if(ctx->mSecureMode) {
+ ovutils::setMdpFlags(mdpFlags,
+ ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
+ }
- ovutils::PipeArgs parg(mdpFlags,
- info,
- ovutils::ZORDER_0,
- ovutils::IS_FG_OFF,
- ovutils::ROT_FLAG_ENABLED);
- ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg };
- ov.setSource(pargs, dest);
+ ovutils::PipeArgs parg(mdpFlags,
+ info,
+ ovutils::ZORDER_0,
+ ovutils::IS_FG_OFF,
+ ovutils::ROT_FLAG_DISABLED);
+ ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg };
+ ov.setSource(pargs, dest);
- hwc_rect_t sourceCrop = layer->sourceCrop;
- // x,y,w,h
- ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top,
+ hwc_rect_t sourceCrop = layer->sourceCrop;
+ // x,y,w,h
+ ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top,
sourceCrop.right - sourceCrop.left,
sourceCrop.bottom - sourceCrop.top);
- ov.setCrop(dcrop, dest);
+ ov.setCrop(dcrop, dest);
- //Get the current orientation on primary panel
- int transform = getDeviceOrientation();
- ovutils::eTransform orient =
- static_cast<ovutils::eTransform>(transform);
- ov.setTransform(orient, dest);
+ int transform = layer->transform;
+ ovutils::eTransform orient =
+ static_cast<ovutils::eTransform>(transform);
+ ov.setTransform(orient, dest);
- hwc_rect_t displayFrame = layer->displayFrame;
- ovutils::Dim dpos(displayFrame.left,
+ hwc_rect_t displayFrame = layer->displayFrame;
+ ovutils::Dim dpos(displayFrame.left,
displayFrame.top,
displayFrame.right - displayFrame.left,
displayFrame.bottom - displayFrame.top);
- ov.setPosition(dpos, dest);
+ ov.setPosition(dpos, dest);
- if (!ov.commit(dest)) {
- ALOGE("%s: commit fails", __FUNCTION__);
- return false;
- }
- sIsUiMirroringOn = true;
+ if (!ov.commit(dest)) {
+ ALOGE("%s: commit fails", __FUNCTION__);
+ sIsUiMirroringOn = false;
+ return false;
}
+ sIsUiMirroringOn = true;
}
return sIsUiMirroringOn;
}
@@ -148,36 +116,20 @@
return true;
}
bool ret = true;
- overlay::Overlay& ov = *(ctx->mOverlay);
+ overlay::Overlay& ov = *(ctx->mOverlay[HWC_DISPLAY_EXTERNAL]);
ovutils::eOverlayState state = ov.getState();
- ovutils::eDest dest = ovutils::OV_PIPE_ALL;
- framebuffer_device_t *fbDev = ctx->mFbDev;
- if(fbDev) {
- private_module_t* m = reinterpret_cast<private_module_t*>(
- fbDev->common.module);
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- switch (state) {
- case ovutils::OV_UI_MIRROR:
- //TODO why is this primary fd
- if (!ov.queueBuffer(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd,
- hnd->offset, //div by line_length like in PAN?
- ovutils::OV_PIPE0)) {
- ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
- ret = false;
- }
- break;
- case ovutils::OV_2D_TRUE_UI_MIRROR:
- if (!ov.queueBuffer(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd,
- hnd->offset,
- ovutils::OV_PIPE2)) {
- ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
- ret = false;
- }
- break;
-
+ ovutils::eDest dest = ovutils::OV_PIPE0;
+ private_handle_t *hnd = (private_handle_t *)layer->handle;
+ switch (state) {
+ case ovutils::OV_UI_MIRROR:
+ case ovutils::OV_UI_VIDEO_TV:
+ if (!ov.queueBuffer(hnd->fd, hnd->offset, dest)) {
+ ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
+ ret = false;
+ }
+ break;
default:
break;
- }
}
return ret;
}
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index e198de3..ee9cc54 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -51,7 +51,10 @@
void initContext(hwc_context_t *ctx)
{
openFramebufferDevice(ctx);
- ctx->mOverlay = overlay::Overlay::getInstance();
+ overlay::Overlay::initOverlay();
+ for(uint32_t i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
+ ctx->mOverlay[i] = overlay::Overlay::getInstance(i);
+ }
ctx->mQService = qService::QService::getInstance(ctx);
ctx->mMDP.version = qdutils::MDPVersion::getInstance().getMDPVersion();
ctx->mMDP.hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay();
@@ -69,9 +72,11 @@
void closeContext(hwc_context_t *ctx)
{
- if(ctx->mOverlay) {
- delete ctx->mOverlay;
- ctx->mOverlay = NULL;
+ for(uint32_t i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
+ if(ctx->mOverlay[i]) {
+ delete ctx->mOverlay[i];
+ ctx->mOverlay[i] = NULL;
+ }
}
if(ctx->mFbDev) {
@@ -111,6 +116,9 @@
ctx->listStats[dpy].numAppLayers = list->numHwLayers - 1;
ctx->listStats[dpy].fbLayerIndex = list->numHwLayers - 1;
+ ctx->listStats[dpy].yuvCount = 0;
+ ctx->listStats[dpy].yuvIndex = -1;
+ ctx->listStats[dpy].skipCount = 0;
for (size_t i = 0; i < list->numHwLayers; i++) {
private_handle_t *hnd =
@@ -198,7 +206,7 @@
int count = 0;
int releaseFd = -1;
int fbFd = -1;
- data.flags = 0;
+ data.flags = MDP_BUF_SYNC_FLAG_WAIT;
data.acq_fen_fd = acquireFd;
data.rel_fen_fd = &releaseFd;
//Accumulate acquireFenceFds
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 0bde003..37708e6 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -60,6 +60,9 @@
float xdpi;
float ydpi;
int fd;
+ bool connected; //Applies only to pluggable disp.
+ //Connected does not mean it ready to use.
+ //It should be active also. (UNBLANKED)
bool isActive;
};
@@ -166,13 +169,13 @@
hwc_composer_device_1_t device;
const hwc_procs_t* proc;
int numHwLayers;
- int overlayInUse;
+ int overlayInUse[HWC_NUM_DISPLAY_TYPES];
//Framebuffer device
framebuffer_device_t *mFbDev;
//Overlay object - NULL for non overlay devices
- overlay::Overlay *mOverlay;
+ overlay::Overlay *mOverlay[HWC_NUM_DISPLAY_TYPES];
//QService object
qService::QService *mQService;
diff --git a/libhwcomposer/hwc_video.cpp b/libhwcomposer/hwc_video.cpp
index 2e4342a..7bbfaf9 100644
--- a/libhwcomposer/hwc_video.cpp
+++ b/libhwcomposer/hwc_video.cpp
@@ -25,19 +25,22 @@
#define FINAL_TRANSFORM_MASK 0x000F
//Static Members
-ovutils::eOverlayState VideoOverlay::sState = ovutils::OV_CLOSED;
-bool VideoOverlay::sIsModeOn = false;
+ovutils::eOverlayState VideoOverlay::sState[] = {ovutils::OV_CLOSED};
+bool VideoOverlay::sIsModeOn[] = {false};
//Cache stats, figure out the state, config overlay
bool VideoOverlay::prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list,
int dpy) {
+
int yuvIndex = ctx->listStats[dpy].yuvIndex;
+ sIsModeOn[dpy] = false;
if(!ctx->mMDP.hasOverlay) {
ALOGD_IF(VIDEO_DEBUG,"%s, this hw doesnt support overlay", __FUNCTION__);
return false;
}
- if(yuvIndex == -1) {
+
+ if(yuvIndex == -1 || ctx->listStats[dpy].yuvCount != 1) {
return false;
}
@@ -55,16 +58,16 @@
chooseState(ctx, dpy, yuvLayer);
if(configure(ctx, dpy, yuvLayer)) {
markFlags(yuvLayer);
- sIsModeOn = true;
+ sIsModeOn[dpy] = true;
}
- return sIsModeOn;
+ return sIsModeOn[dpy];
}
void VideoOverlay::chooseState(hwc_context_t *ctx, int dpy,
hwc_layer_1_t *yuvLayer) {
ALOGD_IF(VIDEO_DEBUG, "%s: old state = %s", __FUNCTION__,
- ovutils::getStateString(sState));
+ ovutils::getStateString(sState[dpy]));
private_handle_t *hnd = NULL;
if(yuvLayer) {
@@ -74,38 +77,27 @@
switch(dpy) {
case HWC_DISPLAY_PRIMARY:
if(ctx->listStats[dpy].yuvCount == 1) {
- newState = isExternalActive(ctx) ?
- ovutils::OV_2D_VIDEO_ON_PANEL_TV : ovutils::OV_2D_VIDEO_ON_PANEL;
+ newState = ovutils::OV_2D_VIDEO_ON_PANEL;
if(isSkipLayer(yuvLayer) && !isSecureBuffer(hnd)) {
- newState = isExternalActive(ctx) ?
- ovutils::OV_2D_VIDEO_ON_TV : ovutils::OV_CLOSED;
+ newState = ovutils::OV_CLOSED;
}
}
break;
case HWC_DISPLAY_EXTERNAL:
- //TODO needs overlay state change for UI also
- newState = sState; //Previously set by HWC_DISPLAY_PRIMARY
- /*if(ctx->listStats[dpy].yuvCount == 1 && isExternalActive(ctx)) {
+ newState = ctx->mOverlay[HWC_DISPLAY_EXTERNAL]->getState(); //If we are here, external is active
+ if(ctx->listStats[dpy].yuvCount == 1) {
if(!isSkipLayer(yuvLayer) || isSecureBuffer(hnd)) {
- switch(sState) { //set by primary chooseState
- case ovutils::OV_2D_VIDEO_ON_PANEL:
- //upgrade
- sState = ovutils::OV_2D_VIDEO_PANEL_TV;
- break;
- case ovutils::OV_CLOSED:
- sState = ovutils::OV_2D_VIDEO_ON_TV;
- break;
- }
+ newState = ovutils::OV_UI_VIDEO_TV;
}
- }*/
+ }
break;
default:
break;
}
- sState = newState;
+ sState[dpy] = newState;
ALOGD_IF(VIDEO_DEBUG, "%s: new chosen state = %s", __FUNCTION__,
- ovutils::getStateString(sState));
+ ovutils::getStateString(sState[dpy]));
}
void VideoOverlay::markFlags(hwc_layer_1_t *yuvLayer) {
@@ -117,7 +109,7 @@
/* Helpers */
bool configPrimVid(hwc_context_t *ctx, hwc_layer_1_t *layer) {
- overlay::Overlay& ov = *(ctx->mOverlay);
+ overlay::Overlay& ov = *(ctx->mOverlay[HWC_DISPLAY_PRIMARY]);
private_handle_t *hnd = (private_handle_t *)layer->handle;
ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
@@ -184,7 +176,7 @@
}
bool configExtVid(hwc_context_t *ctx, hwc_layer_1_t *layer) {
- overlay::Overlay& ov = *(ctx->mOverlay);
+ overlay::Overlay& ov = *(ctx->mOverlay[HWC_DISPLAY_EXTERNAL]);
private_handle_t *hnd = (private_handle_t *)layer->handle;
ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
@@ -201,10 +193,9 @@
ovutils::PipeArgs parg(mdpFlags,
info,
- ovutils::ZORDER_0,
+ ovutils::ZORDER_1,
isFgFlag,
- ovutils::ROT_FLAG_ENABLED); //TODO remove this hack when sync for
- //ext is done
+ ovutils::ROT_FLAG_DISABLED);
ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg };
ov.setSource(pargs, ovutils::OV_PIPE1);
@@ -216,9 +207,10 @@
//Only for External
ov.setCrop(dcrop, ovutils::OV_PIPE1);
- // FIXME: Use source orientation for TV when source is portrait
- //Only for External
- ov.setTransform(0, ovutils::OV_PIPE1);
+ int transform = layer->transform;
+ ovutils::eTransform orient =
+ static_cast<ovutils::eTransform>(transform);
+ ov.setTransform(orient, ovutils::OV_PIPE1);
ovutils::Dim dpos;
hwc_rect_t displayFrame = layer->displayFrame;
@@ -240,31 +232,23 @@
bool VideoOverlay::configure(hwc_context_t *ctx, int dpy,
hwc_layer_1_t *yuvLayer) {
bool ret = true;
- overlay::Overlay& ov = *(ctx->mOverlay);
+ overlay::Overlay& ov = *(ctx->mOverlay[dpy]);
switch(dpy) {
case HWC_DISPLAY_PRIMARY:
// Set overlay state
- ov.setState(sState);
- switch(sState) {
+ ov.setState(sState[dpy]);
+ switch(sState[dpy]) {
case ovutils::OV_2D_VIDEO_ON_PANEL:
ret &= configPrimVid(ctx, yuvLayer);
break;
- case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
- ret &= configPrimVid(ctx, yuvLayer);
- ret &= configExtVid(ctx, yuvLayer);
- break;
- case ovutils::OV_2D_VIDEO_ON_TV:
- ret &= configExtVid(ctx, yuvLayer);
- break;
default:
return false;
}
break;
case HWC_DISPLAY_EXTERNAL:
- ov.setState(sState);
- switch(sState) {
- case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
- case ovutils::OV_2D_VIDEO_ON_TV:
+ ov.setState(sState[dpy]);
+ switch(sState[dpy]) {
+ case ovutils::OV_UI_VIDEO_TV:
ret = configExtVid(ctx, yuvLayer);
break;
default:
@@ -278,8 +262,12 @@
bool VideoOverlay::draw(hwc_context_t *ctx, hwc_display_contents_1_t *list,
int dpy)
{
+ if(!sIsModeOn[dpy]) {
+ return true;
+ }
+
int yuvIndex = ctx->listStats[dpy].yuvIndex;
- if(!sIsModeOn || yuvIndex == -1) {
+ if(yuvIndex == -1) {
return true;
}
@@ -287,7 +275,7 @@
list->hwLayers[yuvIndex].handle;
bool ret = true;
- overlay::Overlay& ov = *(ctx->mOverlay);
+ overlay::Overlay& ov = *(ctx->mOverlay[dpy]);
ovutils::eOverlayState state = ov.getState();
switch(dpy) {
@@ -300,24 +288,6 @@
ret = false;
}
break;
- case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
- if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE0)) {
- ALOGE("%s: queueBuffer failed for primary", __FUNCTION__);
- ret = false;
- }
- // Play external
- if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE1)) {
- ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
- ret = false;
- }
- break;
- case ovutils::OV_2D_VIDEO_ON_TV:
- // Play external
- if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE1)) {
- ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
- ret = false;
- }
- break;
default:
ret = false;
break;
@@ -325,8 +295,7 @@
break;
case HWC_DISPLAY_EXTERNAL:
switch(state) {
- case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
- case ovutils::OV_2D_VIDEO_ON_TV:
+ case ovutils::OV_UI_VIDEO_TV:
// Play external
if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE1)) {
ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
diff --git a/libhwcomposer/hwc_video.h b/libhwcomposer/hwc_video.h
index f5a9709..dbfc236 100644
--- a/libhwcomposer/hwc_video.h
+++ b/libhwcomposer/hwc_video.h
@@ -43,14 +43,16 @@
//Marks layer flags if this feature is used
static void markFlags(hwc_layer_1_t *yuvLayer);
//The chosen overlay state.
- static ovutils::eOverlayState sState;
+ static ovutils::eOverlayState sState[HWC_NUM_DISPLAY_TYPES];
//Flags if this feature is on.
- static bool sIsModeOn;
+ static bool sIsModeOn[HWC_NUM_DISPLAY_TYPES];
};
inline void VideoOverlay::reset() {
- sIsModeOn = false;
- sState = ovutils::OV_CLOSED;
+ for(uint32_t i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
+ sIsModeOn[i] = false;
+ sState[i] = ovutils::OV_CLOSED;
+ }
}
}; //namespace qhwc