diff --git a/libgralloc-qsd8k/gralloc_priv.h b/libgralloc-qsd8k/gralloc_priv.h index 04a15ce..7e41906 100755 --- a/libgralloc-qsd8k/gralloc_priv.h +++ b/libgralloc-qsd8k/gralloc_priv.h @@ -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 { diff --git a/libgralloc-qsd8k/mapper.cpp b/libgralloc-qsd8k/mapper.cpp index e25a3cd..444a2ff 100755 --- a/libgralloc-qsd8k/mapper.cpp +++ b/libgralloc-qsd8k/mapper.cpp @@ -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: diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp index b33cf97..c21b210 100755 --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -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); diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index 39afe4d..8904951 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -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, diff --git a/liboverlay/overlayLib.h b/liboverlay/overlayLib.h index 42760bc..55af19f 100644 --- a/liboverlay/overlayLib.h +++ b/liboverlay/overlayLib.h @@ -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 {