Home | History | Annotate | Download | only in libvirtual
      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 
     52 using namespace android;
     53 
     54 namespace 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 
     61 int 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 
     74 void VirtualDisplay::getAttributes(int& width, int& height) {
     75     width = mVInfo.xres;
     76     height = mVInfo.yres;
     77 }
     78 
     79 int 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 
     89 VirtualDisplay::VirtualDisplay(hwc_context_t* ctx):mFd(-1),
     90      mHwcContext(ctx)
     91 {
     92     memset(&mVInfo, 0, sizeof(mVInfo));
     93 }
     94 
     95 VirtualDisplay::~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 */
    106 void 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 */
    119 void 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 */
    163 void 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 
    172 void 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 
    211 bool 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 
    231 bool 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