1/* 2* Copyright (c) 2013 The Linux Foundation. All rights reserved. 3* 4* Redistribution and use in source and binary forms, with or without 5* modification, are permitted provided that the following conditions are 6* met: 7* * Redistributions of source code must retain the above copyright 8* notice, this list of conditions and the following disclaimer. 9* * Redistributions in binary form must reproduce the above 10* copyright notice, this list of conditions and the following 11* disclaimer in the documentation and/or other materials provided 12* with the distribution. 13* * Neither the name of The Linux Foundation. nor the names of its 14* contributors may be used to endorse or promote products derived 15* from this software without specific prior written permission. 16* 17* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 18* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 20* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28*/ 29 30 31#define DEBUG 0 32#include <ctype.h> 33#include <fcntl.h> 34#include <media/IAudioPolicyService.h> 35#include <media/AudioSystem.h> 36#include <utils/threads.h> 37#include <utils/Errors.h> 38#include <utils/Log.h> 39 40#include <linux/msm_mdp.h> 41#include <linux/fb.h> 42#include <sys/ioctl.h> 43#include <sys/poll.h> 44#include <sys/resource.h> 45#include <cutils/properties.h> 46#include "hwc_utils.h" 47#include "virtual.h" 48#include "overlayUtils.h" 49#include "overlay.h" 50#include "qd_utils.h" 51 52using namespace android; 53 54namespace qhwc { 55 56#define MAX_SYSFS_FILE_PATH 255 57 58/* Max. resolution assignable to virtual display. */ 59#define SUPPORTED_VIRTUAL_AREA (1920*1080) 60 61int VirtualDisplay::configure() { 62 if(!openFrameBuffer()) 63 return -1; 64 65 if(ioctl(mFd, FBIOGET_VSCREENINFO, &mVInfo) < 0) { 66 ALOGD("%s: FBIOGET_VSCREENINFO failed with %s", __FUNCTION__, 67 strerror(errno)); 68 return -1; 69 } 70 setAttributes(); 71 return 0; 72} 73 74void VirtualDisplay::getAttributes(int& width, int& height) { 75 width = mVInfo.xres; 76 height = mVInfo.yres; 77} 78 79int VirtualDisplay::teardown() { 80 closeFrameBuffer(); 81 memset(&mVInfo, 0, sizeof(mVInfo)); 82 // Reset the resolution when we close the fb for this device. We need 83 // this to distinguish between an ONLINE and RESUME event. 84 mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].xres = 0; 85 mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].yres = 0; 86 return 0; 87} 88 89VirtualDisplay::VirtualDisplay(hwc_context_t* ctx):mFd(-1), 90 mHwcContext(ctx) 91{ 92 memset(&mVInfo, 0, sizeof(mVInfo)); 93} 94 95VirtualDisplay::~VirtualDisplay() 96{ 97 closeFrameBuffer(); 98} 99 100/* Initializes the resolution attributes of the virtual display 101 that are reported to SurfaceFlinger. 102 Cases: 103 1. ONLINE event - initialize to frame buffer resolution 104 2. RESUME event - retain original resolution 105*/ 106void VirtualDisplay::initResolution(uint32_t &extW, uint32_t &extH) { 107 // On ONLINE event, display resolution attributes are 0. 108 if(extW == 0 || extH == 0){ 109 extW = mVInfo.xres; 110 extH = mVInfo.yres; 111 } 112} 113 114/* Sets the virtual resolution to match that of the primary 115 display in the event that the virtual display currently 116 connected has a lower resolution. NB: we always report the 117 highest available resolution to SurfaceFlinger. 118*/ 119void VirtualDisplay::setToPrimary(uint32_t maxArea, 120 uint32_t priW, 121 uint32_t priH, 122 uint32_t &extW, 123 uint32_t &extH) { 124 // for eg., primary in 1600p and WFD in 1080p 125 // we wont use downscale feature because MAX MDP 126 // writeback resolution supported is 1080p (tracked 127 // by SUPPORTED_VIRTUAL_AREA). 128 if((maxArea == (priW * priH)) 129 && (maxArea <= SUPPORTED_VIRTUAL_AREA)) { 130 // tmpW and tmpH will hold the primary dimensions before we 131 // update the aspect ratio if necessary. 132 uint32_t tmpW = priW; 133 uint32_t tmpH = priH; 134 // If WFD is in landscape, assign the higher dimension 135 // to WFD's xres. 136 if(priH > priW) { 137 tmpW = priH; 138 tmpH = priW; 139 } 140 // The aspect ratios of the external and primary displays 141 // can be different. As a result, directly assigning primary 142 // resolution could lead to an incorrect final image. 143 // We get around this by calculating a new resolution by 144 // keeping aspect ratio intact. 145 hwc_rect r = {0, 0, 0, 0}; 146 getAspectRatioPosition(tmpW, tmpH, extW, extH, r); 147 extW = r.right - r.left; 148 extH = r.bottom - r.top; 149 } 150} 151 152/* Set External Display MDP Downscale mode indicator. Only set to 153 TRUE for the following scenarios: 154 1. Valid DRC scenarios i.e. when the original WFD resolution 155 is greater than the new/requested resolution in mVInfo. 156 2. WFD down scale path i.e. when WFD resolution is lower than 157 primary resolution. 158 Furthermore, downscale mode is only valid when downscaling from 159 SUPPORTED_VIRTUAL_AREA to a lower resolution. 160 (SUPPORTED_VIRTUAL_AREA represents the maximum resolution that 161 we can configure to the virtual display) 162*/ 163void VirtualDisplay::setDownScaleMode(uint32_t maxArea) { 164 if((maxArea > (mVInfo.xres * mVInfo.yres)) 165 && (maxArea <= SUPPORTED_VIRTUAL_AREA)) { 166 mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].mDownScaleMode = true; 167 }else { 168 mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].mDownScaleMode = false; 169 } 170} 171 172void VirtualDisplay::setAttributes() { 173 if(mHwcContext) { 174 uint32_t &extW = mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].xres; 175 uint32_t &extH = mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].yres; 176 uint32_t priW = mHwcContext->dpyAttr[HWC_DISPLAY_PRIMARY].xres; 177 uint32_t priH = mHwcContext->dpyAttr[HWC_DISPLAY_PRIMARY].yres; 178 179 // Dynamic Resolution Change depends on MDP downscaling. 180 // MDP downscale property will be ignored to exercise DRC use case. 181 // If DRC is in progress, ext WxH will have non-zero values. 182 bool isDRC = (extW > mVInfo.xres) && (extH > mVInfo.yres); 183 184 initResolution(extW, extH); 185 186 if(mHwcContext->mOverlay->isUIScalingOnExternalSupported() 187 && (mHwcContext->mMDPDownscaleEnabled || isDRC)) { 188 189 // maxArea represents the maximum resolution between 190 // primary and virtual display. 191 uint32_t maxArea = max((extW * extH), (priW * priH)); 192 193 setToPrimary(maxArea, priW, priH, extW, extH); 194 195 setDownScaleMode(maxArea); 196 } 197 //Initialize the display viewFrame info 198 mHwcContext->mViewFrame[HWC_DISPLAY_VIRTUAL].left = 0; 199 mHwcContext->mViewFrame[HWC_DISPLAY_VIRTUAL].top = 0; 200 mHwcContext->mViewFrame[HWC_DISPLAY_VIRTUAL].right = 201 (int)mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].xres; 202 mHwcContext->mViewFrame[HWC_DISPLAY_VIRTUAL].bottom = 203 (int)mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].yres; 204 mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].vsync_period = 205 1000000000l /60; 206 ALOGD_IF(DEBUG,"%s: Setting Virtual Attr: res(%d x %d)",__FUNCTION__, 207 mVInfo.xres, mVInfo.yres); 208 } 209} 210 211bool VirtualDisplay::openFrameBuffer() 212{ 213 if (mFd == -1) { 214 int fbNum = overlay::Overlay::getInstance()-> 215 getFbForDpy(HWC_DISPLAY_VIRTUAL); 216 217 char strDevPath[MAX_SYSFS_FILE_PATH]; 218 snprintf(strDevPath,sizeof(strDevPath), "/dev/graphics/fb%d", fbNum); 219 220 mFd = open(strDevPath, O_RDWR); 221 if(mFd < 0) { 222 ALOGE("%s: Unable to open %s ", __FUNCTION__,strDevPath); 223 return -1; 224 } 225 226 mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].fd = mFd; 227 } 228 return 1; 229} 230 231bool VirtualDisplay::closeFrameBuffer() 232{ 233 if(mFd >= 0) { 234 if(close(mFd) < 0 ) { 235 ALOGE("%s: Unable to close FD(%d)", __FUNCTION__, mFd); 236 return -1; 237 } 238 mFd = -1; 239 mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].fd = mFd; 240 } 241 return 1; 242} 243}; 244