107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani/* 207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * Copyright (C) 2008 The Android Open Source Project 307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. 407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * Not a Contribution, Apache license notifications and license are retained 507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * for attribution purposes only. 607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * 707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * Licensed under the Apache License, Version 2.0 (the "License"); 807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * you may not use this file except in compliance with the License. 907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * You may obtain a copy of the License at 1007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * 1107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * http://www.apache.org/licenses/LICENSE-2.0 1207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * 1307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * Unless required by applicable law or agreed to in writing, software 1407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * distributed under the License is distributed on an "AS IS" BASIS, 1507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * See the License for the specific language governing permissions and 1707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * limitations under the License. 1807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani*/ 1907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 2007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani#include <math.h> 2107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani#include "overlayUtils.h" 2207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani#include "overlayRotator.h" 2307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 2407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani#define DEBUG_MDSS_ROT 0 2507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 2607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani#ifdef VENUS_COLOR_FORMAT 2707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani#include <media/msm_media_info.h> 2807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani#else 2907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani#define VENUS_BUFFER_SIZE(args...) 0 3007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani#endif 3107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 3207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani#ifndef MDSS_MDP_ROT_ONLY 3307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani#define MDSS_MDP_ROT_ONLY 0x80 3407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani#endif 3507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 3607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani#define MDSS_ROT_MASK (MDP_ROT_90 | MDP_FLIP_UD | MDP_FLIP_LR) 3707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 3807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malaninamespace ovutils = overlay::utils; 3907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 4007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malaninamespace overlay { 4107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malaniusing namespace utils; 4207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 4307bbf1e89c031a5d41a7561433e832d396c311a5Prashant MalaniMdssRot::MdssRot() { 4407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani reset(); 4507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani init(); 4607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 4707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 4807bbf1e89c031a5d41a7561433e832d396c311a5Prashant MalaniMdssRot::~MdssRot() { close(); } 4907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 5007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanibool MdssRot::enabled() const { return mEnabled; } 5107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 5207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanivoid MdssRot::setRotations(uint32_t flags) { mRotInfo.flags |= flags; } 5307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 5407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malaniint MdssRot::getSrcMemId() const { 5507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return mRotData.data.memory_id; 5607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 5707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 5807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malaniint MdssRot::getDstMemId() const { 5907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return mRotData.dst_data.memory_id; 6007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 6107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 6207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malaniuint32_t MdssRot::getSrcOffset() const { 6307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return mRotData.data.offset; 6407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 6507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 6607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malaniuint32_t MdssRot::getDstOffset() const { 6707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return mRotData.dst_data.offset; 6807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 6907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 7007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malaniuint32_t MdssRot::getDstFormat() const { 7107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani //For mdss src and dst formats are same 7207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return mRotInfo.src.format; 7307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 7407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 7507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malaniutils::Whf MdssRot::getDstWhf() const { 7607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani //For Mdss dst_rect itself represents buffer dimensions. We ignore actual 7707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani //aligned values during buffer allocation. Also the driver overwrites the 7807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani //src.format field if destination format is different. 7907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani //This implementation detail makes it possible to retrieve w,h even before 8007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani //buffer allocation, which happens in queueBuffer. 8107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return utils::Whf(mRotInfo.dst_rect.w, mRotInfo.dst_rect.h, 8207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mRotInfo.src.format); 8307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 8407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 8507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malaniutils::Dim MdssRot::getDstDimensions() const { 8607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return utils::Dim(mRotInfo.dst_rect.x, mRotInfo.dst_rect.y, 8707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mRotInfo.dst_rect.w, mRotInfo.dst_rect.h); 8807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 8907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 9007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malaniuint32_t MdssRot::getSessId() const { return mRotInfo.id; } 9107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 9207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanivoid MdssRot::save() { 9307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mLSRotInfo = mRotInfo; 9407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 9507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 9607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanibool MdssRot::rotConfChanged() const { 9707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani // 0 means same 9807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if(0 == ::memcmp(&mRotInfo, &mLSRotInfo, 9907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani sizeof (mdp_overlay))) { 10007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return false; 10107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 10207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return true; 10307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 10407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 10507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanibool MdssRot::init() { 10607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if(!utils::openDev(mFd, 0, Res::fbPath, O_RDWR)) { 10707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani ALOGE("MdssRot failed to init fb0"); 10807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return false; 10907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 11007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return true; 11107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 11207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 11307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanivoid MdssRot::setSource(const overlay::utils::Whf& awhf) { 11407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani utils::Whf whf(awhf); 11507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 11607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mRotInfo.src.format = whf.format; 11707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mRotInfo.src.width = whf.w; 11807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mRotInfo.src.height = whf.h; 11907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 12007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 12107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanivoid MdssRot::setCrop(const utils::Dim& crop) { 12207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mRotInfo.src_rect.x = crop.x; 12307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mRotInfo.src_rect.y = crop.y; 12407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mRotInfo.src_rect.w = crop.w; 12507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mRotInfo.src_rect.h = crop.h; 12607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 12707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 12807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanivoid MdssRot::setDownscale(int downscale) { 12907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mDownscale = downscale; 13007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 13107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 13207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanivoid MdssRot::setFlags(const utils::eMdpFlags& flags) { 13307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mRotInfo.flags = flags; 13407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 13507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 13607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanivoid MdssRot::setTransform(const utils::eTransform& rot) 13707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani{ 13807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani // reset rotation flags to avoid stale orientation values 13907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mRotInfo.flags &= ~MDSS_ROT_MASK; 14007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani int flags = utils::getMdpOrient(rot); 14107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if (flags != -1) 14207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani setRotations(flags); 14307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mOrientation = static_cast<utils::eTransform>(flags); 14407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani ALOGE_IF(DEBUG_OVERLAY, "%s: rot=%d", __FUNCTION__, flags); 14507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 14607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 14707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanivoid MdssRot::doTransform() { 14807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mRotInfo.flags |= mOrientation; 14907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if(mOrientation & utils::OVERLAY_TRANSFORM_ROT_90) 15007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani utils::swap(mRotInfo.dst_rect.w, mRotInfo.dst_rect.h); 15107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 15207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 15307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanibool MdssRot::commit() { 15407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani Dim adjCrop(mRotInfo.src_rect.x,mRotInfo.src_rect.y, 15507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mRotInfo.src_rect.w,mRotInfo.src_rect.h); 15607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani adjCrop = getFormatAdjustedCrop(adjCrop, mRotInfo.src.format, 15707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mRotInfo.flags & utils::OV_MDP_DEINTERLACE); 15807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani adjCrop = getDownscaleAdjustedCrop(adjCrop, mDownscale); 15907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 16007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mRotInfo.src_rect.x = adjCrop.x; 16107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mRotInfo.src_rect.y = adjCrop.y; 16207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mRotInfo.src_rect.w = adjCrop.w; 16307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mRotInfo.src_rect.h = adjCrop.h; 16407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 16507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mRotInfo.dst_rect.x = 0; 16607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mRotInfo.dst_rect.y = 0; 16707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mRotInfo.dst_rect.w = mDownscale ? 16807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mRotInfo.src_rect.w / mDownscale : mRotInfo.src_rect.w; 16907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mRotInfo.dst_rect.h = mDownscale ? 17007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mRotInfo.src_rect.h / mDownscale : mRotInfo.src_rect.h; 17107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani //Clear for next round 17207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mDownscale = 0; 17307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 17407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani doTransform(); 17507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 17607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mRotInfo.flags |= MDSS_MDP_ROT_ONLY; 17707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mEnabled = true; 17807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if(!overlay::mdp_wrapper::setOverlay(mFd.getFD(), mRotInfo)) { 17907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani ALOGE("MdssRot commit failed!"); 18007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani dump(); 18107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return (mEnabled = false); 18207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 18307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mRotData.id = mRotInfo.id; 18407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return true; 18507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 18607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 18707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanibool MdssRot::queueBuffer(int fd, uint32_t offset) { 18807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if(enabled() and (not isRotCached(fd,offset))) { 18907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani int prev_fd = getSrcMemId(); 19007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani uint32_t prev_offset = getSrcOffset(); 19107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 19207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mRotData.data.memory_id = fd; 19307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mRotData.data.offset = offset; 19407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 19507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if(false == remap(RotMem::ROT_NUM_BUFS)) { 19607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani ALOGE("%s Remap failed, not queuing", __FUNCTION__); 19707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return false; 19807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 19907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 20007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mRotData.dst_data.offset = 20107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mMem.mRotOffset[mMem.mCurrIndex]; 20207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 20307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if(!overlay::mdp_wrapper::play(mFd.getFD(), mRotData)) { 20407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani ALOGE("MdssRot play failed!"); 20507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani dump(); 20607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mRotData.data.memory_id = prev_fd; 20707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mRotData.data.offset = prev_offset; 20807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return false; 20907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 21007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani save(); 21107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mMem.mCurrIndex = 21207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani (mMem.mCurrIndex + 1) % mMem.mem.numBufs(); 21307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 21407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return true; 21507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 21607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 21707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanibool MdssRot::open_i(uint32_t numbufs, uint32_t bufsz) 21807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani{ 21907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani OvMem mem; 22007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani OVASSERT(MAP_FAILED == mem.addr(), "MAP failed in open_i"); 22107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani bool isSecure = mRotInfo.flags & utils::OV_MDP_SECURE_OVERLAY_SESSION; 22207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 22307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if(!mem.open(numbufs, bufsz, isSecure)){ 22407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani ALOGE("%s: Failed to open", __func__); 22507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mem.close(); 22607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return false; 22707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 22807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 22907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani OVASSERT(MAP_FAILED != mem.addr(), "MAP failed"); 23007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani OVASSERT(mem.getFD() != -1, "getFd is -1"); 23107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 23207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mRotData.dst_data.memory_id = mem.getFD(); 23307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mRotData.dst_data.offset = 0; 23407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mMem.mem = mem; 23507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return true; 23607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 23707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 23807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanibool MdssRot::remap(uint32_t numbufs) { 23907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani // Calculate the size based on rotator's dst format, w and h. 24007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani uint32_t opBufSize = calcOutputBufSize(); 24107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani // If current size changed, remap 24207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if(opBufSize == mMem.size()) { 24307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani ALOGE_IF(DEBUG_OVERLAY, "%s: same size %d", __FUNCTION__, opBufSize); 24407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return true; 24507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 24607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 24707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani ALOGE_IF(DEBUG_OVERLAY, "%s: size changed - remapping", __FUNCTION__); 24807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 24907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if(!mMem.close()) { 25007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani ALOGE("%s error in closing prev rot mem", __FUNCTION__); 25107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return false; 25207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 25307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 25407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if(!open_i(numbufs, opBufSize)) { 25507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani ALOGE("%s Error could not open", __FUNCTION__); 25607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return false; 25707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 25807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 25907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani for (uint32_t i = 0; i < numbufs; ++i) { 26007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mMem.mRotOffset[i] = i * opBufSize; 26107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 26207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 26307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return true; 26407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 26507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 26607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanibool MdssRot::close() { 26707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani bool success = true; 26807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if(mFd.valid() && (getSessId() != (uint32_t) MSMFB_NEW_REQUEST)) { 26907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if(!mdp_wrapper::unsetOverlay(mFd.getFD(), getSessId())) { 27007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani ALOGE("MdssRot::close unsetOverlay failed, fd=%d sessId=%d", 27107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mFd.getFD(), getSessId()); 27207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani success = false; 27307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 27407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 27507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 27607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if (!mFd.close()) { 27707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani ALOGE("Mdss Rot error closing fd"); 27807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani success = false; 27907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 28007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if (!mMem.close()) { 28107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani ALOGE("Mdss Rot error closing mem"); 28207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani success = false; 28307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 28407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani reset(); 28507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return success; 28607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 28707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 28807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanivoid MdssRot::reset() { 28907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani ovutils::memset0(mRotInfo); 29007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani ovutils::memset0(mLSRotInfo); 29107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani ovutils::memset0(mRotData); 29207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mRotData.data.memory_id = -1; 29307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mRotInfo.id = MSMFB_NEW_REQUEST; 29407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani ovutils::memset0(mMem.mRotOffset); 29507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mMem.mCurrIndex = 0; 29607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mOrientation = utils::OVERLAY_TRANSFORM_0; 29707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mDownscale = 0; 29807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 29907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 30007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanivoid MdssRot::dump() const { 30107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani ALOGE("== Dump MdssRot start =="); 30207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mFd.dump(); 30307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mMem.mem.dump(); 30407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mdp_wrapper::dump("mRotInfo", mRotInfo); 30507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mdp_wrapper::dump("mRotData", mRotData); 30607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani ALOGE("== Dump MdssRot end =="); 30707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 30807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 30907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malaniuint32_t MdssRot::calcOutputBufSize() { 31007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani uint32_t opBufSize = 0; 31107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani ovutils::Whf destWhf(mRotInfo.dst_rect.w, mRotInfo.dst_rect.h, 31207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani mRotInfo.src.format); //mdss src and dst formats are same. 31307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 31407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if (mRotInfo.flags & ovutils::OV_MDSS_MDP_BWC_EN) { 31507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani opBufSize = calcCompressedBufSize(destWhf); 31607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } else { 31707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani opBufSize = Rotator::calcOutputBufSize(destWhf); 31807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 31907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 32007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return opBufSize; 32107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 32207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 32307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanivoid MdssRot::getDump(char *buf, size_t len) const { 32407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani ovutils::getDump(buf, len, "MdssRotCtrl", mRotInfo); 32507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani ovutils::getDump(buf, len, "MdssRotData", mRotData); 32607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 32707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 32807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani// Calculate the compressed o/p buffer size for BWC 32907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malaniuint32_t MdssRot::calcCompressedBufSize(const ovutils::Whf& destWhf) { 33007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani uint32_t bufSize = 0; 33107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani //Worst case alignments 33207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani int aWidth = ovutils::align(destWhf.w, 64); 33307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani int aHeight = ovutils::align(destWhf.h, 4); 33407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani /* 33507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani Format | RAU size (width x height) 33607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani ---------------------------------------------- 33707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani ARGB | 32 pixel x 4 line 33807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani RGB888 | 32 pixel x 4 line 33907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani Y (Luma) | 64 pixel x 4 line 34007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani CRCB 420 | 32 pixel x 2 line 34107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani CRCB 422 H2V1 | 32 pixel x 4 line 34207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani CRCB 422 H1V2 | 64 pixel x 2 line 34307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 34407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani Metadata requirements:- 34507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 1 byte meta data for every 8 RAUs 34607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 2 byte meta data per RAU 34707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani */ 34807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 34907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani //These blocks attempt to allocate for the worst case in each of the 35007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani //respective format classes, yuv/rgb. The table above is for reference 35107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if(utils::isYuv(destWhf.format)) { 35207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani int yRauCount = aWidth / 64; //Y 35307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani int cRauCount = aWidth / 32; //C 35407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani int yStride = (64 * 4 * yRauCount) + alignup(yRauCount, 8) / 8; 35507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani int cStride = ((32 * 2 * cRauCount) + alignup(cRauCount, 8) / 8) * 2; 35607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani int yStrideOffset = (aHeight / 4); 35707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani int cStrideOffset = (aHeight / 2); 35807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani bufSize = (yStride * yStrideOffset + cStride * cStrideOffset) + 35907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani (yRauCount * yStrideOffset * 2) + 36007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani (cRauCount * cStrideOffset * 2) * 2; 36107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani ALOGD_IF(DEBUG_MDSS_ROT, "%s:YUV Y RAU Count = %d C RAU Count = %d", 36207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani __FUNCTION__, yRauCount, cRauCount); 36307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } else { 36407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani int rauCount = aWidth / 32; 36507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani //Single plane 36607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani int stride = (32 * 4 * rauCount) + alignup(rauCount, 8) / 8; 36707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani int strideOffset = (aHeight / 4); 36807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani bufSize = (stride * strideOffset * 4 /*bpp*/) + 36907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani (rauCount * strideOffset * 2); 37007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani ALOGD_IF(DEBUG_MDSS_ROT, "%s:RGB RAU count = %d", __FUNCTION__, 37107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani rauCount); 37207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 37307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 37407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani ALOGD_IF(DEBUG_MDSS_ROT, "%s: aligned width = %d, aligned height = %d " 37507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani "Buf Size = %d", __FUNCTION__, aWidth, aHeight, bufSize); 37607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 37707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return bufSize; 37807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 37907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 38007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malaniint MdssRot::getDownscaleFactor(const int& srcW, const int& srcH, 38107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani const int& dstW, const int& dstH, const uint32_t& mdpFormat, 38207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani const bool& isInterlaced) { 38307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if(not srcW or not srcH or not dstW or not dstH or isInterlaced) return 0; 38407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 38507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani Dim crop(0, 0, srcW, srcH); 38607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani Dim adjCrop = getFormatAdjustedCrop(crop, mdpFormat, 38707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani false /*isInterlaced */); 38807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 38907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani uint32_t downscale = min((adjCrop.w / dstW), (adjCrop.h / dstH)); 39007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani //Reduced to a power of 2 39107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani downscale = (uint32_t) powf(2.0f, floorf(log2f((float)downscale))); 39207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 39307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if(downscale < 2 or downscale > 32) return 0; 39407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 39507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani //Allow only 1 line or pixel to be chopped off since the source needs to 39607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani //be aligned to downscale. Progressively try with smaller downscale to see 39707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani //if we can satisfy the threshold 39807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani //For YUV the loop shouldnt be needed, unless in exceptional cases 39907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani Dim dsAdjCrop = getDownscaleAdjustedCrop(adjCrop, downscale); 40007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani while(downscale > 2 and (adjCrop.w > dsAdjCrop.w or 40107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani adjCrop.h > dsAdjCrop.h)) { 40207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani downscale /= 2; 40307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani dsAdjCrop = getDownscaleAdjustedCrop(adjCrop, downscale); 40407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 40507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 40607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if(not dsAdjCrop.w or not dsAdjCrop.h) return 0; 40707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return downscale; 40807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 40907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 41007bbf1e89c031a5d41a7561433e832d396c311a5Prashant MalaniDim MdssRot::getFormatAdjustedCrop(const Dim& crop, 41107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani const uint32_t& mdpFormat, const bool& isInterlaced) { 41207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani Dim adjCrop = crop; 41307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if (isYuv(mdpFormat)) { 41407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani normalizeCrop(adjCrop.x, adjCrop.w); 41507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani normalizeCrop(adjCrop.y, adjCrop.h); 41607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani // For interlaced, crop.h should be 4-aligned 41707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if (isInterlaced and (adjCrop.h % 4)) 41807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani adjCrop.h = aligndown(adjCrop.h, 4); 41907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 42007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return adjCrop; 42107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 42207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 42307bbf1e89c031a5d41a7561433e832d396c311a5Prashant MalaniDim MdssRot::getDownscaleAdjustedCrop(const Dim& crop, 42407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani const uint32_t& downscale) { 42507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani uint32_t alignedSrcW = aligndown(crop.w, downscale * 2); 42607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani uint32_t alignedSrcH = aligndown(crop.h, downscale * 2); 42707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return Dim(crop.x, crop.y, alignedSrcW, alignedSrcH); 42807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 42907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 43007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} // namespace overlay 431