qcom/display: add true mirroring support on HDMI

Change-Id: I7e884e5dde2a08048a28610eb88760fcdd24d558

CRs-fixed: 316397
This commit is contained in:
Arun Kumar K.R 2011-12-06 22:18:21 -08:00 committed by Andrew Sutherland
parent 3ef9f39ba5
commit ca1d2bab60
5 changed files with 434 additions and 79 deletions

View File

@ -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;

View File

@ -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

View File

@ -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,

View File

@ -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;

View File

@ -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; }