qcom/display: add true mirroring support on HDMI
Change-Id: I7e884e5dde2a08048a28610eb88760fcdd24d558 CRs-fixed: 316397
This commit is contained in:
parent
3ef9f39ba5
commit
ca1d2bab60
@ -212,6 +212,14 @@ static void *disp_loop(void *ptr)
|
||||
}
|
||||
|
||||
#if defined(HDMI_DUAL_DISPLAY)
|
||||
static int closeHDMIChannel(private_module_t* m)
|
||||
{
|
||||
Overlay* pTemp = m->pobjOverlay;
|
||||
if(pTemp != NULL)
|
||||
pTemp->closeChannel();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *hdmi_ui_loop(void *ptr)
|
||||
{
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||
@ -227,12 +235,13 @@ static void *hdmi_ui_loop(void *ptr)
|
||||
}
|
||||
float asWidthRatio = m->actionsafeWidthRatio/100.0f;
|
||||
float asHeightRatio = m->actionsafeHeightRatio/100.0f;
|
||||
bool waitForVsync = true;
|
||||
|
||||
if (m->pobjOverlay) {
|
||||
Overlay* pTemp = m->pobjOverlay;
|
||||
if (!m->enableHDMIOutput)
|
||||
pTemp->closeChannel();
|
||||
else if (m->enableHDMIOutput && !m->videoOverlay) {
|
||||
if (m->hdmiMirroringState == HDMI_NO_MIRRORING)
|
||||
closeHDMIChannel(m);
|
||||
else if(m->hdmiMirroringState == HDMI_UI_MIRRORING) {
|
||||
if (!pTemp->isChannelUP()) {
|
||||
int alignedW = ALIGN(m->info.xres, 32);
|
||||
|
||||
@ -244,12 +253,15 @@ static void *hdmi_ui_loop(void *ptr)
|
||||
info.format = hnd->format;
|
||||
info.size = hnd->size;
|
||||
|
||||
if (pTemp->startChannel(info, 1,
|
||||
false, true, 0, VG0_PIPE, true)) {
|
||||
if (m->trueMirrorSupport)
|
||||
waitForVsync = false;
|
||||
|
||||
if (pTemp->startChannel(info, FRAMEBUFFER_1,
|
||||
false, true, 0, VG0_PIPE, waitForVsync)) {
|
||||
pTemp->setFd(m->framebuffer->fd);
|
||||
pTemp->setCrop(0, 0, m->info.xres, m->info.yres);
|
||||
} else
|
||||
pTemp->closeChannel();
|
||||
closeHDMIChannel(m);
|
||||
}
|
||||
|
||||
if (pTemp->isChannelUP()) {
|
||||
@ -259,21 +271,23 @@ static void *hdmi_ui_loop(void *ptr)
|
||||
int asX = 0, asY = 0; // Action safe x, y co-ordinates
|
||||
int fbwidth = m->info.xres, fbheight = m->info.yres;
|
||||
float defaultASWidthRatio = 0.0f, defaultASHeightRatio = 0.0f;
|
||||
if(HEIGHT_1080P == height) {
|
||||
defaultASHeightRatio = AS_1080_RATIO_H;
|
||||
defaultASWidthRatio = AS_1080_RATIO_W;
|
||||
} else if(HEIGHT_720P == height) {
|
||||
defaultASHeightRatio = AS_720_RATIO_H;
|
||||
defaultASWidthRatio = AS_720_RATIO_W;
|
||||
} else if(HEIGHT_480P == height) {
|
||||
defaultASHeightRatio = AS_480_RATIO_H;
|
||||
defaultASWidthRatio = AS_480_RATIO_W;
|
||||
// TODO: disable OverScan for now
|
||||
if(!m->trueMirrorSupport) {
|
||||
if(HEIGHT_1080P == height) {
|
||||
defaultASHeightRatio = AS_1080_RATIO_H;
|
||||
defaultASWidthRatio = AS_1080_RATIO_W;
|
||||
} else if(HEIGHT_720P == height) {
|
||||
defaultASHeightRatio = AS_720_RATIO_H;
|
||||
defaultASWidthRatio = AS_720_RATIO_W;
|
||||
} else if(HEIGHT_480P == height) {
|
||||
defaultASHeightRatio = AS_480_RATIO_H;
|
||||
defaultASWidthRatio = AS_480_RATIO_W;
|
||||
}
|
||||
if(asWidthRatio <= 0.0f)
|
||||
asWidthRatio = defaultASWidthRatio;
|
||||
if(asHeightRatio <= 0.0f)
|
||||
asHeightRatio = defaultASHeightRatio;
|
||||
}
|
||||
if(asWidthRatio <= 0.0f)
|
||||
asWidthRatio = defaultASWidthRatio;
|
||||
if(asHeightRatio <= 0.0f)
|
||||
asHeightRatio = defaultASHeightRatio;
|
||||
|
||||
aswidth = (int)((float)width - (float)(width * asWidthRatio));
|
||||
asheight = (int)((float)height - (float)(height * asHeightRatio));
|
||||
asX = (width - aswidth) / 2;
|
||||
@ -348,11 +362,16 @@ static void *hdmi_ui_loop(void *ptr)
|
||||
pTemp->setPosition(asX, asY, aswidth, asheight);
|
||||
}
|
||||
}
|
||||
if (m->trueMirrorSupport) {
|
||||
// if video is started the UI channel should be NO_WAIT.
|
||||
waitForVsync = !m->videoOverlay;
|
||||
pTemp->updateWaitForVsyncFlags(waitForVsync);
|
||||
}
|
||||
pTemp->queueBuffer(m->currentOffset);
|
||||
}
|
||||
}
|
||||
else
|
||||
pTemp->closeChannel();
|
||||
closeHDMIChannel(m);
|
||||
}
|
||||
pthread_mutex_unlock(&m->overlayLock);
|
||||
}
|
||||
@ -366,16 +385,16 @@ static int fb_videoOverlayStarted(struct framebuffer_device_t* dev, int started)
|
||||
pthread_mutex_lock(&m->overlayLock);
|
||||
Overlay* pTemp = m->pobjOverlay;
|
||||
if(started != m->videoOverlay) {
|
||||
m->hdmiStateChanged = true;
|
||||
if (started && pTemp) {
|
||||
pTemp->closeChannel();
|
||||
m->videoOverlay = true;
|
||||
m->videoOverlay = started;
|
||||
if (!m->trueMirrorSupport) {
|
||||
m->hdmiStateChanged = true;
|
||||
if (started && pTemp) {
|
||||
m->hdmiMirroringState = HDMI_NO_MIRRORING;
|
||||
closeHDMIChannel(m);
|
||||
} else if (m->enableHDMIOutput)
|
||||
m->hdmiMirroringState = HDMI_UI_MIRRORING;
|
||||
pthread_cond_signal(&(m->overlayPost));
|
||||
}
|
||||
else {
|
||||
m->videoOverlay = false;
|
||||
pthread_cond_signal(&(m->overlayPost));
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&m->overlayLock);
|
||||
return 0;
|
||||
@ -387,15 +406,25 @@ static int fb_enableHDMIOutput(struct framebuffer_device_t* dev, int enable)
|
||||
dev->common.module);
|
||||
pthread_mutex_lock(&m->overlayLock);
|
||||
Overlay* pTemp = m->pobjOverlay;
|
||||
if (!enable && pTemp)
|
||||
pTemp->closeChannel();
|
||||
m->enableHDMIOutput = enable;
|
||||
if(enable) {
|
||||
if (m->trueMirrorSupport) {
|
||||
m->hdmiMirroringState = HDMI_UI_MIRRORING;
|
||||
} else {
|
||||
if(!m->videoOverlay)
|
||||
m->hdmiMirroringState = HDMI_UI_MIRRORING;
|
||||
}
|
||||
} else if (!enable && pTemp) {
|
||||
m->hdmiMirroringState = HDMI_NO_MIRRORING;
|
||||
closeHDMIChannel(m);
|
||||
}
|
||||
m->hdmiStateChanged = true;
|
||||
pthread_cond_signal(&(m->overlayPost));
|
||||
pthread_mutex_unlock(&m->overlayLock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int fb_setActionSafeWidthRatio(struct framebuffer_device_t* dev, float asWidthRatio)
|
||||
{
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||
@ -409,12 +438,13 @@ static int fb_setActionSafeWidthRatio(struct framebuffer_device_t* dev, float as
|
||||
static int fb_setActionSafeHeightRatio(struct framebuffer_device_t* dev, float asHeightRatio)
|
||||
{
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||
dev->common.module);
|
||||
dev->common.module);
|
||||
pthread_mutex_lock(&m->overlayLock);
|
||||
m->actionsafeHeightRatio = asHeightRatio;
|
||||
pthread_mutex_unlock(&m->overlayLock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fb_orientationChanged(struct framebuffer_device_t* dev, int orientation)
|
||||
{
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||
@ -805,6 +835,8 @@ int mapFrameBufferLocked(struct private_module_t* module)
|
||||
module->hdmiStateChanged = false;
|
||||
pthread_t hdmiUIThread;
|
||||
pthread_create(&hdmiUIThread, NULL, &hdmi_ui_loop, (void *) module);
|
||||
module->hdmiMirroringState = HDMI_NO_MIRRORING;
|
||||
module->trueMirrorSupport = FrameBufferInfo::getInstance()->canSupportTrueMirroring();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
@ -214,6 +214,14 @@ enum {
|
||||
BUFFER_TYPE_UI = 0,
|
||||
BUFFER_TYPE_VIDEO
|
||||
};
|
||||
|
||||
#if defined(HDMI_DUAL_DISPLAY)
|
||||
enum hdmi_mirroring_state {
|
||||
HDMI_NO_MIRRORING,
|
||||
HDMI_UI_MIRRORING,
|
||||
HDMI_ORIGINAL_RESOLUTION_MIRRORING
|
||||
};
|
||||
#endif
|
||||
/*****************************************************************************/
|
||||
|
||||
struct private_module_t;
|
||||
@ -277,10 +285,12 @@ struct private_module_t {
|
||||
bool videoOverlay;
|
||||
uint32_t currentOffset;
|
||||
bool enableHDMIOutput;
|
||||
bool trueMirrorSupport;
|
||||
bool exitHDMIUILoop;
|
||||
float actionsafeWidthRatio;
|
||||
float actionsafeHeightRatio;
|
||||
bool hdmiStateChanged;
|
||||
hdmi_mirroring_state hdmiMirroringState;
|
||||
pthread_mutex_t overlayLock;
|
||||
pthread_cond_t overlayPost;
|
||||
#endif
|
||||
|
@ -307,7 +307,19 @@ static int prepareOverlay(hwc_context_t *ctx, hwc_layer_t *layer, const bool wai
|
||||
LOGE("prepareOverlay setCrop failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if defined HDMI_DUAL_DISPLAY
|
||||
// Send the device orientation to overlayLib
|
||||
if(hwcModule) {
|
||||
framebuffer_device_t *fbDev = reinterpret_cast<framebuffer_device_t*>
|
||||
(hwcModule->fbDevice);
|
||||
if(fbDev) {
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||
fbDev->common.module);
|
||||
if(m)
|
||||
ovLibObject->setDeviceOrientation(m->orientation);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (layer->flags & HWC_USE_ORIGINAL_RESOLUTION) {
|
||||
framebuffer_device_t* fbDev = hwcModule->fbDevice;
|
||||
ret = ovLibObject->setPosition(0, 0,
|
||||
|
@ -37,6 +37,13 @@ bool Overlay::sHDMIAsPrimary = true;
|
||||
bool Overlay::sHDMIAsPrimary = false;
|
||||
#endif
|
||||
|
||||
template <class Type>
|
||||
void swapWidthHeight(Type& width, Type& height) {
|
||||
Type tmp = width;
|
||||
width = height;
|
||||
height = tmp;
|
||||
}
|
||||
|
||||
int overlay::get_mdp_format(int format) {
|
||||
switch (format) {
|
||||
case HAL_PIXEL_FORMAT_RGBA_8888 :
|
||||
@ -183,6 +190,66 @@ const char* overlay::getFormatString(int format){
|
||||
};
|
||||
return formats[format];
|
||||
}
|
||||
ZOrderManager* ZOrderManager::sInstance = 0;
|
||||
FrameBufferInfo* FrameBufferInfo::sFBInfoInstance = 0;
|
||||
|
||||
int ZOrderManager::getZ(int fbnum){
|
||||
int zorder = NO_PIPE;;
|
||||
Mutex::Autolock objLock(mObjMutex);
|
||||
if(mPipesInuse == mMaxPipes) {
|
||||
LOGE("No free pipes available.. inUse = %d ", mPipesInuse);
|
||||
return NO_PIPE;
|
||||
}
|
||||
switch(fbnum) {
|
||||
case FRAMEBUFFER_0:
|
||||
for (int i = 0;i < NUM_CHANNELS; i++) {
|
||||
if(mFB0Pipes[i] == false) {
|
||||
mFB0Pipes[i]= true;
|
||||
zorder = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FRAMEBUFFER_1:
|
||||
for (int i = 0;i < mMaxPipes; i++) {
|
||||
if(mFB1Pipes[i] == false) {
|
||||
mFB1Pipes[i]= true;
|
||||
zorder = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOGE("getZ: Invalid framebuffer..");
|
||||
break;
|
||||
}
|
||||
mPipesInuse++;
|
||||
LOGE("getZ: return zorder = %d for fbdev = %d, pipesinUse = %d",
|
||||
zorder, fbnum, mPipesInuse);
|
||||
return zorder;
|
||||
}
|
||||
|
||||
void ZOrderManager::decZ(int fbnum, int zorder){
|
||||
Mutex::Autolock objLock(mObjMutex);
|
||||
switch(fbnum) {
|
||||
case FRAMEBUFFER_0:
|
||||
LOG_ASSERT(!mFB0Pipes[zorder],"channel with ZOrder does not exist");
|
||||
LOGE("decZ: freeing the pipe with zorder = %d for fbdev = %d", zorder, fbnum);
|
||||
mFB0Pipes[zorder] = false;
|
||||
break;
|
||||
case FRAMEBUFFER_1:
|
||||
LOG_ASSERT(!mFB1Pipes[zorder],"channel with ZOrder does not exist");
|
||||
LOGE("decZ: freeing the pipe with zorder = %d for fbdev = %d", zorder, fbnum);
|
||||
mFB1Pipes[zorder] = false;
|
||||
break;
|
||||
default:
|
||||
LOGE("decZ: Invalid framebuffer ");
|
||||
break;
|
||||
}
|
||||
if(mPipesInuse > 0)
|
||||
mPipesInuse--;
|
||||
LOGE("decZ: Pipes in use = %d", mPipesInuse);
|
||||
}
|
||||
|
||||
bool overlay::isHDMIConnected () {
|
||||
char value[PROPERTY_VALUE_MAX];
|
||||
@ -387,55 +454,77 @@ bool Overlay::getOrientation(int& orientation, int channel) const {
|
||||
return objOvCtrlChannel[channel].getOrientation(orientation);
|
||||
}
|
||||
|
||||
bool Overlay::setDeviceOrientation(int orientation) {
|
||||
// Use this to calculate the position on HDMI
|
||||
mDevOrientation = orientation;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Overlay::setPosition(int x, int y, uint32_t w, uint32_t h) {
|
||||
bool ret = false;
|
||||
overlay_rect rect;
|
||||
switch (mState) {
|
||||
case OV_UI_MIRROR_TV:
|
||||
case OV_2D_VIDEO_ON_PANEL:
|
||||
case OV_3D_VIDEO_2D_PANEL:
|
||||
return setChannelPosition(x, y, w, h, VG0_PIPE);
|
||||
break;
|
||||
case OV_2D_VIDEO_ON_TV:
|
||||
objOvCtrlChannel[VG1_PIPE].getAspectRatioPosition(mCroppedSrcWidth,
|
||||
mCroppedSrcHeight, &rect);
|
||||
setChannelPosition(rect.x, rect.y, rect.w, rect.h, VG1_PIPE);
|
||||
return setChannelPosition(x, y, w, h, VG0_PIPE);
|
||||
break;
|
||||
case OV_3D_VIDEO_3D_PANEL:
|
||||
for (int i = 0; i < NUM_CHANNELS; i++) {
|
||||
if (sHDMIAsPrimary)
|
||||
objOvCtrlChannel[i].getPositionS3D(i, mS3DFormat, &rect);
|
||||
else {
|
||||
if (!objOvCtrlChannel[i].useVirtualFB()) {
|
||||
LOGE("%s: failed virtual fb for channel %d", __FUNCTION__, i);
|
||||
overlay_rect inrect;
|
||||
int currX, currY;
|
||||
uint32_t currW, currH;
|
||||
// Set even destination co-ordinates
|
||||
EVEN_OUT(x); EVEN_OUT(y);
|
||||
EVEN_OUT(w); EVEN_OUT(h);
|
||||
objOvCtrlChannel[VG0_PIPE].getPosition(currX, currY, currW, currH);
|
||||
inrect.x = x, inrect.y = y;
|
||||
inrect.w = w, inrect.h = h;
|
||||
if(x != currX || y != currY || w != currW || h != currH) {
|
||||
switch (mState) {
|
||||
case OV_UI_MIRROR_TV:
|
||||
case OV_2D_VIDEO_ON_PANEL:
|
||||
case OV_3D_VIDEO_2D_PANEL:
|
||||
return setChannelPosition(x, y, w, h, VG0_PIPE);
|
||||
break;
|
||||
case OV_2D_VIDEO_ON_TV:
|
||||
if (FrameBufferInfo::getInstance()->canSupportTrueMirroring()) {
|
||||
objOvCtrlChannel[VG1_PIPE].getAspectRatioPosition(mCroppedSrcWidth,
|
||||
mCroppedSrcHeight, mDevOrientation, &inrect, &rect);
|
||||
} else {
|
||||
objOvCtrlChannel[VG1_PIPE].getAspectRatioPosition(mCroppedSrcWidth,
|
||||
mCroppedSrcHeight, &rect);
|
||||
}
|
||||
setChannelPosition(rect.x, rect.y, rect.w, rect.h, VG1_PIPE);
|
||||
return setChannelPosition(x, y, w, h, VG0_PIPE);
|
||||
break;
|
||||
case OV_3D_VIDEO_3D_PANEL:
|
||||
for (int i = 0; i < NUM_CHANNELS; i++) {
|
||||
if (sHDMIAsPrimary)
|
||||
objOvCtrlChannel[i].getPositionS3D(i, mS3DFormat, &rect);
|
||||
else {
|
||||
if (!objOvCtrlChannel[i].useVirtualFB()) {
|
||||
LOGE("%s: failed virtual fb for channel %d", __FUNCTION__, i);
|
||||
return false;
|
||||
}
|
||||
objOvCtrlChannel[i].getPositionS3D(i, 0x1, &rect);
|
||||
}
|
||||
if(!setChannelPosition(rect.x, rect.y, rect.w, rect.h, i)) {
|
||||
LOGE("%s: failed for channel %d", __FUNCTION__, i);
|
||||
return false;
|
||||
}
|
||||
objOvCtrlChannel[i].getPositionS3D(i, 0x1, &rect);
|
||||
}
|
||||
if(!setChannelPosition(rect.x, rect.y, rect.w, rect.h, i)) {
|
||||
LOGE("%s: failed for channel %d", __FUNCTION__, i);
|
||||
return false;
|
||||
break;
|
||||
case OV_3D_VIDEO_2D_TV:
|
||||
case OV_3D_VIDEO_3D_TV:
|
||||
for (int i = 0; i < NUM_CHANNELS; i++) {
|
||||
ret = objOvCtrlChannel[i].getPositionS3D(i, mS3DFormat, &rect);
|
||||
if (!ret)
|
||||
ret = setChannelPosition(x, y, w, h, i);
|
||||
else
|
||||
ret = setChannelPosition(rect.x, rect.y, rect.w, rect.h, i);
|
||||
if (!ret) {
|
||||
LOGE("%s: failed for channel %d", __FUNCTION__, i);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OV_3D_VIDEO_2D_TV:
|
||||
case OV_3D_VIDEO_3D_TV:
|
||||
for (int i = 0; i < NUM_CHANNELS; i++) {
|
||||
ret = objOvCtrlChannel[i].getPositionS3D(i, mS3DFormat, &rect);
|
||||
if (!ret)
|
||||
ret = setChannelPosition(x, y, w, h, i);
|
||||
else
|
||||
ret = setChannelPosition(rect.x, rect.y, rect.w, rect.h, i);
|
||||
if (!ret) {
|
||||
LOGE("%s: failed for channel %d", __FUNCTION__, i);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOGE("%s:Unknown state %d", __FUNCTION__, mState);
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
LOGE("%s:Unknown state %d", __FUNCTION__, mState);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -606,9 +695,7 @@ bool Overlay::setSource(const overlay_buffer_info& info, int orientation,
|
||||
return false;
|
||||
}
|
||||
}
|
||||
overlay_rect rect;
|
||||
objOvCtrlChannel[VG1_PIPE].getAspectRatioPosition(info.width, info.height, &rect);
|
||||
return setChannelPosition(rect.x, rect.y, rect.w, rect.h, VG1_PIPE);
|
||||
return true;
|
||||
break;
|
||||
case OV_3D_VIDEO_3D_TV:
|
||||
for (int i=0; i<NUM_CHANNELS; i++) {
|
||||
@ -679,6 +766,10 @@ bool Overlay::setChannelCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h, int
|
||||
return objOvDataChannel[channel].setCrop(x, y, w, h);
|
||||
}
|
||||
|
||||
bool Overlay::updateWaitForVsyncFlags(bool waitForVsync) {
|
||||
return objOvCtrlChannel[VG0_PIPE].updateWaitForVsyncFlags(waitForVsync);
|
||||
}
|
||||
|
||||
bool Overlay::setTransform(int value) {
|
||||
int barrier = 0;
|
||||
switch (mState) {
|
||||
@ -847,6 +938,106 @@ bool OverlayControlChannel::getAspectRatioPosition(int w, int h, overlay_rect *r
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// This function gets the destination position for Seconday display
|
||||
// based on the aspect ratio of the primary
|
||||
bool OverlayControlChannel::getAspectRatioPosition(int w, int h, int orientation,
|
||||
overlay_rect *inRect, overlay_rect *outRect) {
|
||||
float priWidth = FrameBufferInfo::getInstance()->getWidth();
|
||||
float priHeight = FrameBufferInfo::getInstance()->getHeight();
|
||||
float fbWidth = getFBWidth();
|
||||
float fbHeight = getFBHeight();
|
||||
float wRatio = 1.0;
|
||||
float hRatio = 1.0;
|
||||
float xRatio = 1.0;
|
||||
float yRatio = 1.0;
|
||||
|
||||
int xPos = 0;
|
||||
int tmp = 0;
|
||||
float actualWidth = fbWidth;
|
||||
if(priWidth < priHeight) {
|
||||
switch(orientation) {
|
||||
case MDP_ROT_NOP:
|
||||
actualWidth = (fbHeight * priWidth) / priHeight;
|
||||
xPos = (fbWidth - actualWidth) / 2;
|
||||
break;
|
||||
case MDP_ROT_180:
|
||||
actualWidth = (fbHeight * priWidth) / priHeight;
|
||||
xPos = (fbWidth - actualWidth) / 2;
|
||||
inRect->x = priWidth - (inRect->x + inRect->w);
|
||||
inRect->y = priHeight - (inRect->y + inRect->h);
|
||||
break;
|
||||
case MDP_ROT_90:
|
||||
tmp = inRect->y;
|
||||
inRect->y = priWidth - (inRect->x + inRect->w);
|
||||
inRect->x = tmp;
|
||||
// Swap width/height for primary
|
||||
swapWidthHeight(priWidth, priHeight);
|
||||
//Swap the destination width/height
|
||||
swapWidthHeight(inRect->w, inRect->h);
|
||||
break;
|
||||
case MDP_ROT_270:
|
||||
tmp = inRect->x;
|
||||
inRect->x = priHeight - (inRect->y + inRect->h);
|
||||
inRect->y = tmp;
|
||||
// Swap width/height for primary
|
||||
swapWidthHeight(priWidth, priHeight);
|
||||
//Swap the destination width/height
|
||||
swapWidthHeight(inRect->w, inRect->h);
|
||||
break;
|
||||
default:
|
||||
LOGE("In %s: Portrait: Unknown Orientation", __FUNCTION__);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch(orientation) {
|
||||
case MDP_ROT_NOP:
|
||||
break;
|
||||
case MDP_ROT_180:
|
||||
inRect->x = priWidth - (inRect->x + inRect->w);
|
||||
inRect->y = priHeight - (inRect->y + inRect->h);
|
||||
break;
|
||||
case MDP_ROT_90:
|
||||
case MDP_ROT_270:
|
||||
// Swap width/height for primary
|
||||
swapWidthHeight(priWidth, priHeight);
|
||||
//Swap the destination width/height
|
||||
swapWidthHeight(inRect->w, inRect->h);
|
||||
actualWidth = ( fbHeight * priWidth) / priHeight;
|
||||
xPos = (fbWidth - actualWidth) / 2;
|
||||
if(orientation == MDP_ROT_90) {
|
||||
tmp = inRect->y;
|
||||
inRect->y = priWidth - (inRect->x + inRect->w);
|
||||
inRect->x = tmp;
|
||||
}
|
||||
else if(orientation == MDP_ROT_270) {
|
||||
tmp = inRect->x;
|
||||
inRect->x = priHeight - (inRect->y + inRect->h);
|
||||
inRect->y = tmp;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOGE("In %s: Landscape: Unknown Orientation", __FUNCTION__);
|
||||
break;
|
||||
}
|
||||
}
|
||||
//Calculate the position...
|
||||
xRatio = inRect->x/priWidth;
|
||||
yRatio = inRect->y/priHeight;
|
||||
|
||||
wRatio = inRect->w/priWidth;
|
||||
hRatio = inRect->h/priHeight;
|
||||
outRect->x = (xRatio * fbWidth) + xPos;
|
||||
outRect->y = yRatio * fbHeight;
|
||||
|
||||
outRect->w = (wRatio * actualWidth);
|
||||
outRect->h = hRatio * fbHeight;
|
||||
LOGE("Calculated AS Position for HDMI: X= %d, y = %d w = %d h = %d",
|
||||
outRect->x, outRect->y,outRect->w, outRect->h);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool OverlayControlChannel::getPositionS3D(int channel, int format, overlay_rect *rect) {
|
||||
int wDisp = getFBWidth();
|
||||
int hDisp = getFBHeight();
|
||||
@ -1090,6 +1281,7 @@ bool OverlayControlChannel::startControlChannel(int w, int h,
|
||||
mNoRot = norot;
|
||||
mFormat = format;
|
||||
mUIChannel = uichannel;
|
||||
mFBNum = fbnum;
|
||||
fb_fix_screeninfo finfo;
|
||||
fb_var_screeninfo vinfo;
|
||||
int hw_format;
|
||||
@ -1114,9 +1306,18 @@ bool OverlayControlChannel::startControlChannel(int w, int h,
|
||||
// Set the share bit for sharing the VG pipe
|
||||
flags |= MDP_OV_PIPE_SHARE;
|
||||
}
|
||||
//do not set the PIPE SHARE bit for true mirroring
|
||||
if(uichannel && FrameBufferInfo::getInstance()->canSupportTrueMirroring())
|
||||
flags &= ~MDP_OV_PIPE_SHARE;
|
||||
if (!openDevices(fbnum))
|
||||
return false;
|
||||
|
||||
//get Z order
|
||||
zorder = ZOrderManager::getInstance()->getZ(fbnum);
|
||||
if (zorder == NO_PIPE)
|
||||
return false;
|
||||
|
||||
|
||||
int orientation = mNoRot ? 0: 1;
|
||||
overlay_buffer_info ovBufInfo;
|
||||
ovBufInfo.width = w;
|
||||
@ -1146,9 +1347,15 @@ bool OverlayControlChannel::closeControlChannel() {
|
||||
}
|
||||
|
||||
close(mFD);
|
||||
|
||||
if(NO_PIPE != mOVInfo.z_order){
|
||||
ZOrderManager::getInstance()->decZ(mFBNum, mOVInfo.z_order);
|
||||
}
|
||||
memset(&mOVInfo, 0, sizeof(mOVInfo));
|
||||
memset(&mRotInfo, 0, sizeof(mRotInfo));
|
||||
memset(&m3DOVInfo, 0, sizeof(m3DOVInfo));
|
||||
|
||||
mOVInfo.z_order = NO_PIPE;
|
||||
mFD = -1;
|
||||
|
||||
return true;
|
||||
|
@ -39,6 +39,7 @@
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <utils/threads.h>
|
||||
#include <utils/RefBase.h>
|
||||
#include <alloc_controller.h>
|
||||
#include <memalloc.h>
|
||||
@ -47,6 +48,7 @@
|
||||
#define HW_OVERLAY_MINIFICATION_LIMIT HW_OVERLAY_MAGNIFICATION_LIMIT
|
||||
|
||||
#define EVEN_OUT(x) if (x & 0x0001) {x--;}
|
||||
#define NO_PIPE -1
|
||||
#define VG0_PIPE 0
|
||||
#define VG1_PIPE 1
|
||||
#define NUM_CHANNELS 2
|
||||
@ -125,7 +127,58 @@ enum {
|
||||
OVERLAY_TRANSFORM_ROT_270 = HAL_TRANSFORM_ROT_270
|
||||
};
|
||||
|
||||
using android::Mutex;
|
||||
namespace overlay {
|
||||
//Utility Class to query the framebuffer info
|
||||
class FrameBufferInfo {
|
||||
int mFBWidth;
|
||||
int mFBHeight;
|
||||
bool mBorderFillSupported;
|
||||
static FrameBufferInfo *sFBInfoInstance;
|
||||
|
||||
FrameBufferInfo():mFBWidth(0),mFBHeight(0), mBorderFillSupported(false) {
|
||||
char const * const device_name =
|
||||
"/dev/graphics/fb0";
|
||||
int fd = open(device_name, O_RDWR, 0);
|
||||
mdp_overlay ov;
|
||||
memset(&ov, 0, sizeof(ov));
|
||||
if (fd < 0) {
|
||||
LOGE("FrameBufferInfo: Cant open framebuffer ");
|
||||
return;
|
||||
}
|
||||
fb_var_screeninfo vinfo;
|
||||
if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) == -1) {
|
||||
LOGE("FrameBufferInfo: FBIOGET_VSCREENINFO on fb0 failed");
|
||||
close(fd);
|
||||
fd = -1;
|
||||
return;
|
||||
}
|
||||
ov.id = 1;
|
||||
if(ioctl(fd, MSMFB_OVERLAY_GET, &ov)) {
|
||||
LOGE("FrameBufferInfo: MSMFB_OVERLAY_GET on fb0 failed");
|
||||
close(fd);
|
||||
fd = -1;
|
||||
return;
|
||||
}
|
||||
close(fd);
|
||||
fd = -1;
|
||||
mFBWidth = vinfo.xres;
|
||||
mFBHeight = vinfo.yres;
|
||||
mBorderFillSupported = (ov.flags & MDP_BORDERFILL_SUPPORTED) ?
|
||||
true : false;
|
||||
}
|
||||
public:
|
||||
static FrameBufferInfo* getInstance(){
|
||||
if (!sFBInfoInstance){
|
||||
sFBInfoInstance = new FrameBufferInfo;
|
||||
}
|
||||
return sFBInfoInstance;
|
||||
}
|
||||
int getWidth() const { return mFBWidth; }
|
||||
int getHeight() const { return mFBHeight; }
|
||||
bool canSupportTrueMirroring() const {
|
||||
return mBorderFillSupported; }
|
||||
};
|
||||
|
||||
enum {
|
||||
OV_UI_MIRROR_TV = 0,
|
||||
@ -158,13 +211,46 @@ void dump(msm_rotator_img_info& mRotInfo);
|
||||
void dump(mdp_overlay& mOvInfo);
|
||||
const char* getFormatString(int format);
|
||||
|
||||
//singleton class to decide the z order of new overlay surfaces
|
||||
class ZOrderManager {
|
||||
bool mFB0Pipes[NUM_CHANNELS];
|
||||
bool mFB1Pipes[NUM_CHANNELS+1]; //FB1 can have 3 pipes
|
||||
int mPipesInuse; // Holds the number of pipes in use
|
||||
int mMaxPipes; // Max number of pipes
|
||||
static ZOrderManager *sInstance;
|
||||
Mutex *mObjMutex;
|
||||
ZOrderManager(){
|
||||
mPipesInuse = 0;
|
||||
// for true mirroring support there can be 3 pipes on secondary
|
||||
mMaxPipes = FrameBufferInfo::getInstance()->canSupportTrueMirroring()?
|
||||
NUM_CHANNELS+1 : NUM_CHANNELS;
|
||||
for (int i = 0; i < NUM_CHANNELS; i++)
|
||||
mFB0Pipes[i] = false;
|
||||
for (int j = 0; j < mMaxPipes; j++)
|
||||
mFB1Pipes[j] = false;
|
||||
mObjMutex = new Mutex();
|
||||
}
|
||||
~ZOrderManager() {
|
||||
delete sInstance;
|
||||
delete mObjMutex;
|
||||
}
|
||||
public:
|
||||
static ZOrderManager* getInstance(){
|
||||
if (!sInstance){
|
||||
sInstance = new ZOrderManager;
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
int getZ(int fbnum);
|
||||
void decZ(int fbnum, int zorder);
|
||||
};
|
||||
const int max_num_buffers = 3;
|
||||
typedef struct mdp_rect overlay_rect;
|
||||
|
||||
class OverlayControlChannel {
|
||||
|
||||
bool mNoRot;
|
||||
|
||||
int mFBNum;
|
||||
int mFBWidth;
|
||||
int mFBHeight;
|
||||
int mFBbpp;
|
||||
@ -210,6 +296,10 @@ public:
|
||||
bool getOrientation(int& orientation) const;
|
||||
bool updateWaitForVsyncFlags(bool waitForVsync);
|
||||
bool getAspectRatioPosition(int w, int h, overlay_rect *rect);
|
||||
// Calculates the aspect ratio for video on HDMI based on primary
|
||||
// aspect ratio used in case of true mirroring
|
||||
bool getAspectRatioPosition(int w, int h, int orientation,
|
||||
overlay_rect *inRect, overlay_rect *outRect);
|
||||
bool getPositionS3D(int channel, int format, overlay_rect *rect);
|
||||
bool updateOverlaySource(const overlay_buffer_info& info, int orientation, bool waitForVsync);
|
||||
bool getFormat() const { return mFormat; }
|
||||
@ -274,6 +364,8 @@ class Overlay {
|
||||
int mCroppedSrcHeight;
|
||||
overlay_buffer_info mOVBufferInfo;
|
||||
int mState;
|
||||
// Stores the current device orientation
|
||||
int mDevOrientation;
|
||||
OverlayControlChannel objOvCtrlChannel[2];
|
||||
OverlayDataChannel objOvDataChannel[2];
|
||||
|
||||
@ -287,6 +379,7 @@ public:
|
||||
int channel = 0, bool ignoreFB = false,
|
||||
int num_buffers = 2);
|
||||
bool closeChannel();
|
||||
bool setDeviceOrientation(int orientation);
|
||||
bool setPosition(int x, int y, uint32_t w, uint32_t h);
|
||||
bool setTransform(int value);
|
||||
bool setOrientation(int value, int channel = 0);
|
||||
@ -301,6 +394,7 @@ public:
|
||||
bool setSource(const overlay_buffer_info& info, int orientation, bool hdmiConnected,
|
||||
bool ignoreFB = false, int numBuffers = 2);
|
||||
bool setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h);
|
||||
bool updateWaitForVsyncFlags(bool waitForVsync);
|
||||
bool waitForHdmiVsync(int channel);
|
||||
int getChannelStatus() const { return (mChannelUP ? OVERLAY_CHANNEL_UP: OVERLAY_CHANNEL_DOWN); }
|
||||
void setHDMIStatus (bool isHDMIConnected) { mHDMIConnected = isHDMIConnected; mState = -1; }
|
||||
|
Loading…
x
Reference in New Issue
Block a user