Add support for dynamic resolution change with overlays
Whenever there is a change in the buffer geometry, set a flag in the gralloc handle stating that the buffer geometry has changed. In the HWC, whenever we encounter an update in the geometry, if the channel is already open, we just call the necessary ioctls to update the overlay information and not unnecessarily open/close channels. Change-Id: I27db8fc497ebc514e262d6b7854739f312644714
This commit is contained in:
parent
56a78ad233
commit
9c2ba115fd
@ -257,6 +257,7 @@ struct private_handle_t {
|
||||
PRIV_FLAGS_USES_PMEM_ADSP = 0x00000004,
|
||||
PRIV_FLAGS_NEEDS_FLUSH = 0x00000008,
|
||||
PRIV_FLAGS_USES_ASHMEM = 0x00000010,
|
||||
PRIV_FLAGS_FORMAT_CHANGED = 0x00000020,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -369,7 +369,10 @@ int gralloc_perform(struct gralloc_module_t const* module,
|
||||
private_handle_t* hnd = (private_handle_t*)handle;
|
||||
hnd->width = w;
|
||||
hnd->height = h;
|
||||
hnd->format = f;
|
||||
if (hnd->format != f) {
|
||||
hnd->format = f;
|
||||
hnd->flags |= private_handle_t::PRIV_FLAGS_FORMAT_CHANGED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -341,12 +341,31 @@ static int drawLayerUsingOverlay(hwc_context_t *ctx, hwc_layer_t *layer)
|
||||
|
||||
private_handle_t *hnd = (private_handle_t *)layer->handle;
|
||||
overlay::Overlay *ovLibObject = ctx->mOverlayLibObject;
|
||||
int orientation = 0;
|
||||
if (OVERLAY_CHANNEL_UP == ovLibObject->getChannelStatus())
|
||||
ovLibObject->getOrientation(orientation);
|
||||
|
||||
ret = ovLibObject->setSource(hnd->width, hnd->height, hnd->format, layer->transform,
|
||||
if ((OVERLAY_CHANNEL_DOWN == ovLibObject->getChannelStatus())
|
||||
|| (layer->transform != orientation) ||
|
||||
(hnd->flags & private_handle_t::PRIV_FLAGS_FORMAT_CHANGED)) {
|
||||
// Overlay channel is not started, or we have an orientation change or there is a
|
||||
// format change, call setSource to open the overlay if necessary
|
||||
ret = ovLibObject->setSource(hnd->width, hnd->height, hnd->format, layer->transform,
|
||||
(ovLibObject->getHDMIStatus()?true:false), false);
|
||||
if (!ret) {
|
||||
LOGE("drawLayerUsingOverlay setSource failed");
|
||||
return -1;
|
||||
if (!ret) {
|
||||
LOGE("drawLayerUsingOverlay setSource failed");
|
||||
return -1;
|
||||
}
|
||||
// Reset this flag so that we don't keep opening and closing channels unnecessarily
|
||||
hnd->flags &= ~private_handle_t::PRIV_FLAGS_FORMAT_CHANGED;
|
||||
} else {
|
||||
// The overlay goemetry may have changed, we only need to update the overlay
|
||||
ret = ovLibObject->updateOverlaySource(hnd->width, hnd->height, hnd->format,
|
||||
layer->transform);
|
||||
if (!ret) {
|
||||
LOGE("drawLayerUsingOverlay updateOverlaySource failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
hwc_rect_t sourceCrop = layer->sourceCrop;
|
||||
@ -373,7 +392,6 @@ static int drawLayerUsingOverlay(hwc_context_t *ctx, hwc_layer_t *layer)
|
||||
return -1;
|
||||
}
|
||||
|
||||
int orientation;
|
||||
ovLibObject->getOrientation(orientation);
|
||||
if (orientation != layer->transform)
|
||||
ret = ovLibObject->setParameter(OVERLAY_TRANSFORM, layer->transform);
|
||||
|
@ -271,6 +271,37 @@ bool Overlay::setPositionS3D(int x, int y, uint32_t w, uint32_t h) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Overlay::updateOverlaySource(uint32_t w, uint32_t h, int format, int orientation) {
|
||||
if (hasHDMIStatusChanged()) {
|
||||
return setSource(w, h, format, orientation, mHDMIConnected);
|
||||
}
|
||||
|
||||
bool ret = true;
|
||||
// Set the overlay source info
|
||||
if (objOvCtrlChannel[0].isChannelUP()) {
|
||||
ret = objOvCtrlChannel[0].updateOverlaySource(w, h);
|
||||
if (ret && objOvCtrlChannel[1].isChannelUP())
|
||||
ret = objOvCtrlChannel[1].updateOverlaySource(w, h);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Overlay::hasHDMIStatusChanged() {
|
||||
int hdmiChanged = 0;
|
||||
if (mHDMIConnected) {
|
||||
// If HDMI is connected and both channels are not up, set the status
|
||||
if (!objOvCtrlChannel[0].isChannelUP() || !objOvCtrlChannel[1].isChannelUP()) {
|
||||
hdmiChanged = 0x1;
|
||||
}
|
||||
} else {
|
||||
// HDMI is disconnected and both channels are up, set the status
|
||||
if (objOvCtrlChannel[0].isChannelUP() && objOvCtrlChannel[1].isChannelUP()) {
|
||||
hdmiChanged = 0x1;
|
||||
}
|
||||
}
|
||||
return hdmiChanged;
|
||||
}
|
||||
|
||||
bool Overlay::setSource(uint32_t w, uint32_t h, int format, int orientation,
|
||||
bool hdmiConnected, bool ignoreFB, int num_buffers) {
|
||||
if (mCloseChannel)
|
||||
@ -298,19 +329,8 @@ bool Overlay::setSource(uint32_t w, uint32_t h, int format, int orientation,
|
||||
|
||||
if (format3D != mS3DFormat)
|
||||
s3dChanged = 0x10;
|
||||
if (mHDMIConnected) {
|
||||
// If HDMI is connected and both channels are not up, set the status
|
||||
if (!objOvCtrlChannel[0].isChannelUP() || !objOvCtrlChannel[1].isChannelUP()) {
|
||||
hdmiChanged = 0x1;
|
||||
}
|
||||
} else {
|
||||
// HDMI is disconnected and both channels are up, set the status
|
||||
if (objOvCtrlChannel[0].isChannelUP() && objOvCtrlChannel[1].isChannelUP()) {
|
||||
hdmiChanged = 0x1;
|
||||
}
|
||||
}
|
||||
|
||||
stateChanged = s3dChanged|hdmiChanged;
|
||||
stateChanged = s3dChanged|hasHDMIStatusChanged();
|
||||
if (stateChanged || !objOvCtrlChannel[0].setSource(w, h, colorFormat, orientation, ignoreFB)) {
|
||||
if (mChannelUP && isRGBType(hw_format) && (stateChanged != 0x10)) {
|
||||
mCloseChannel = true;
|
||||
@ -682,6 +702,91 @@ bool OverlayControlChannel::startOVRotatorSessions(int w, int h,
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool OverlayControlChannel::updateOverlaySource(uint32_t w, uint32_t h)
|
||||
{
|
||||
// Set Rotator info
|
||||
if (mRotFD >=0) {
|
||||
if(mRotInfo.src.format == MDP_Y_CRCB_H2V2_TILE) {
|
||||
if ((mRotInfo.src.width == (((w-1)/64 +1)*64)) &&
|
||||
(mRotInfo.src.height == (((h-1)/32 +1)*32)))
|
||||
return true;
|
||||
|
||||
mRotInfo.src.width = (((w-1)/64 +1)*64);
|
||||
mRotInfo.src.height = (((h-1)/32 +1)*32);
|
||||
mRotInfo.src_rect.w = (((w-1)/64 +1)*64);
|
||||
mRotInfo.src_rect.h = (((h-1)/32 +1)*32);
|
||||
mRotInfo.dst.height = (((w-1)/64 +1)*64);
|
||||
mRotInfo.dst.width = (((h-1)/32 +1)*32);
|
||||
mRotInfo.dst.format = MDP_Y_CRCB_H2V2;
|
||||
} else {
|
||||
if ((mRotInfo.src.width == w) &&
|
||||
(mRotInfo.src.height == h))
|
||||
return true;
|
||||
|
||||
mRotInfo.src.width = w;
|
||||
mRotInfo.src.height = h;
|
||||
mRotInfo.src_rect.w = w;
|
||||
mRotInfo.src_rect.h = h;
|
||||
mRotInfo.dst.width = h;
|
||||
mRotInfo.dst.height = w;
|
||||
}
|
||||
|
||||
if (mOVInfo.user_data[0] == MDP_ROT_NOP)
|
||||
mRotInfo.enable = 0;
|
||||
|
||||
if (ioctl(mRotFD, MSM_ROTATOR_IOCTL_START, &mRotInfo)) {
|
||||
LOGE("updateOverlaySource MSM_ROTATOR_IOCTL_START failed");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Set overlay info
|
||||
switch (mOVInfo.user_data[0]) {
|
||||
case MDP_ROT_90:
|
||||
case (MDP_ROT_90 | MDP_FLIP_UD):
|
||||
case (MDP_ROT_90 | MDP_FLIP_LR):
|
||||
case MDP_ROT_270: {
|
||||
if ((mOVInfo.src.height == (((w-1)/64 +1)*64)) &&
|
||||
(mOVInfo.src.width == (((h-1)/32 +1)*32)))
|
||||
return true;
|
||||
|
||||
mOVInfo.src_rect.w = h;
|
||||
mOVInfo.src_rect.h = w;
|
||||
mOVInfo.src.height = (((w-1)/64 +1)*64);
|
||||
mOVInfo.src.width = (((h-1)/32 +1)*32);
|
||||
mOVInfo.src_rect.x = 0;
|
||||
mOVInfo.src_rect.y = 0;;
|
||||
} break;
|
||||
case MDP_ROT_180:
|
||||
case MDP_ROT_NOP: {
|
||||
if ((mOVInfo.src.width == w) &&
|
||||
(mOVInfo.src.height == h))
|
||||
return true;
|
||||
|
||||
mOVInfo.src.width = w;
|
||||
mOVInfo.src.height = h;
|
||||
mOVInfo.src_rect.x = 0;
|
||||
mOVInfo.src_rect.y = 0;
|
||||
if(mOVInfo.src.format == MDP_Y_CRCB_H2V2_TILE) {
|
||||
mOVInfo.src_rect.w = w - ( (((w-1)/64 +1)*64) - w);
|
||||
mOVInfo.src_rect.h = h - ((((h-1)/32 +1)*32) - h);
|
||||
} else {
|
||||
mOVInfo.src_rect.w = w;
|
||||
mOVInfo.src_rect.h = h;
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
LOGE("updateOverlaySource: Invalid rotation parameter");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) {
|
||||
LOGE("updateOverlaySource MSMFB_OVERLAY_SET failed");
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OverlayControlChannel::startControlChannel(int w, int h,
|
||||
int format, int fbnum, bool norot,
|
||||
bool uichannel,
|
||||
|
@ -139,6 +139,7 @@ public:
|
||||
int orientation, bool ignoreFB);
|
||||
bool getAspectRatioPosition(int w, int h, int format, overlay_rect *rect);
|
||||
bool getPositionS3D(int channel, int format, overlay_rect *rect);
|
||||
bool updateOverlaySource(uint32_t w, uint32_t h);
|
||||
};
|
||||
|
||||
class OverlayDataChannel {
|
||||
@ -216,6 +217,7 @@ public:
|
||||
int getChannelStatus() const { return (mChannelUP ? OVERLAY_CHANNEL_UP: OVERLAY_CHANNEL_DOWN); }
|
||||
void setHDMIStatus (bool isHDMIConnected) { mHDMIConnected = isHDMIConnected; }
|
||||
int getHDMIStatus() const {return (mHDMIConnected ? HDMI_ON : HDMI_OFF); }
|
||||
bool updateOverlaySource(uint32_t w, uint32_t h, int format, int orientation);
|
||||
|
||||
private:
|
||||
bool startChannelHDMI(int w, int h, int format, bool norot);
|
||||
@ -225,6 +227,7 @@ private:
|
||||
bool setChannelPosition(int x, int y, uint32_t w, uint32_t h, int channel = 0);
|
||||
bool setChannelCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h, int channel);
|
||||
bool queueBuffer(int fd, uint32_t offset, int channel);
|
||||
int hasHDMIStatusChanged();
|
||||
};
|
||||
|
||||
struct overlay_shared_data {
|
||||
|
Loading…
x
Reference in New Issue
Block a user