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 "mdp_version.h"
     51 #include "qd_utils.h"
     52 
     53 using namespace android;
     54 
     55 namespace qhwc {
     56 
     57 #define MAX_SYSFS_FILE_PATH             255
     58 
     59 /* Max. resolution assignable to virtual display. */
     60 #define SUPPORTED_VIRTUAL_AREA          (1920*1080)
     61 
     62 int VirtualDisplay::configure() {
     63     if(!openFrameBuffer())
     64         return -1;
     65 
     66     if(ioctl(mFd, FBIOGET_VSCREENINFO, &mVInfo) < 0) {
     67         ALOGD("%s: FBIOGET_VSCREENINFO failed with %s", __FUNCTION__,
     68                 strerror(errno));
     69         return -1;
     70     }
     71     setAttributes();
     72     return 0;
     73 }
     74 
     75 void VirtualDisplay::getAttributes(int& width, int& height) {
     76     width = mVInfo.xres;
     77     height = mVInfo.yres;
     78 }
     79 
     80 int VirtualDisplay::teardown() {
     81     closeFrameBuffer();
     82     memset(&mVInfo, 0, sizeof(mVInfo));
     83     // Reset the resolution when we close the fb for this device. We need
     84     // this to distinguish between an ONLINE and RESUME event.
     85     mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].xres = 0;
     86     mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].yres = 0;
     87     return 0;
     88 }
     89 
     90 VirtualDisplay::VirtualDisplay(hwc_context_t* ctx):mFd(-1),
     91      mHwcContext(ctx)
     92 {
     93     memset(&mVInfo, 0, sizeof(mVInfo));
     94 }
     95 
     96 VirtualDisplay::~VirtualDisplay()
     97 {
     98     closeFrameBuffer();
     99 }
    100 
    101 /* Initializes the resolution attributes of the virtual display
    102    that are reported to SurfaceFlinger.
    103    Cases:
    104        1. ONLINE event - initialize to frame buffer resolution
    105        2. RESUME event - retain original resolution
    106 */
    107 void VirtualDisplay::initResolution(uint32_t &extW, uint32_t &extH) {
    108     // On ONLINE event, display resolution attributes are 0.
    109     if(extW == 0 || extH == 0){
    110         extW = mVInfo.xres;
    111         extH = mVInfo.yres;
    112     }
    113 }
    114 
    115 /* Sets the virtual resolution to match that of the primary
    116    display in the event that the virtual display currently
    117    connected has a lower resolution. NB: we always report the
    118    highest available resolution to SurfaceFlinger.
    119 */
    120 void VirtualDisplay::setToPrimary(uint32_t maxArea,
    121                                   uint32_t priW,
    122                                   uint32_t priH,
    123                                   uint32_t &extW,
    124                                   uint32_t &extH) {
    125     // for eg., primary in 1600p and WFD in 1080p
    126     // we wont use downscale feature because MAX MDP
    127     // writeback resolution supported is 1080p (tracked
    128     // by SUPPORTED_VIRTUAL_AREA).
    129     if((maxArea == (priW * priH))
    130         && (maxArea <= SUPPORTED_VIRTUAL_AREA)) {
    131         // tmpW and tmpH will hold the primary dimensions before we
    132         // update the aspect ratio if necessary.
    133         uint32_t tmpW = priW;
    134         uint32_t tmpH = priH;
    135         // If WFD is in landscape, assign the higher dimension
    136         // to WFD's xres.
    137         if(priH > priW) {
    138             tmpW = priH;
    139             tmpH = priW;
    140         }
    141         // The aspect ratios of the external and primary displays
    142         // can be different. As a result, directly assigning primary
    143         // resolution could lead to an incorrect final image.
    144         // We get around this by calculating a new resolution by
    145         // keeping aspect ratio intact.
    146         hwc_rect r = {0, 0, 0, 0};
    147         getAspectRatioPosition(tmpW, tmpH, extW, extH, r);
    148         extW = r.right - r.left;
    149         extH = r.bottom - r.top;
    150     }
    151 }
    152 
    153 /* Set External Display MDP Downscale mode indicator. Only set to
    154    TRUE for the following scenarios:
    155    1. Valid DRC scenarios i.e. when the original WFD resolution
    156       is greater than the new/requested resolution in mVInfo.
    157    2. WFD down scale path i.e. when WFD resolution is lower than
    158       primary resolution.
    159    Furthermore, downscale mode is only valid when downscaling from
    160    SUPPORTED_VIRTUAL_AREA to a lower resolution.
    161    (SUPPORTED_VIRTUAL_AREA represents the maximum resolution that
    162    we can configure to the virtual display)
    163 */
    164 void VirtualDisplay::setDownScaleMode(uint32_t maxArea) {
    165     if((maxArea > (mVInfo.xres * mVInfo.yres))
    166         && (maxArea <= SUPPORTED_VIRTUAL_AREA)) {
    167         mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].mDownScaleMode = true;
    168     }else {
    169         mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].mDownScaleMode = false;
    170     }
    171 }
    172 
    173 void VirtualDisplay::setAttributes() {
    174     if(mHwcContext) {
    175         uint32_t &extW = mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].xres;
    176         uint32_t &extH = mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].yres;
    177         uint32_t priW = mHwcContext->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
    178         uint32_t priH = mHwcContext->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
    179 
    180         initResolution(extW, extH);
    181 
    182         // Dynamic Resolution Change depends on MDP downscaling.
    183         // MDP downscale property will be ignored to exercise DRC use case.
    184         // If DRC is in progress, ext WxH will have non-zero values.
    185         bool isDRC = (extW > 0) && (extH > 0);
    186 
    187         if(!qdutils::MDPVersion::getInstance().is8x26()
    188                 && (mHwcContext->mMDPDownscaleEnabled || isDRC)) {
    189 
    190             // maxArea represents the maximum resolution between
    191             // primary and virtual display.
    192             uint32_t maxArea = max((extW * extH), (priW * priH));
    193 
    194             setToPrimary(maxArea, priW, priH, extW, extH);
    195 
    196             setDownScaleMode(maxArea);
    197         }
    198         mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].vsync_period =
    199                 1000000000l /60;
    200         ALOGD_IF(DEBUG,"%s: Setting Virtual Attr: res(%d x %d)",__FUNCTION__,
    201                  mVInfo.xres, mVInfo.yres);
    202     }
    203 }
    204 
    205 bool VirtualDisplay::openFrameBuffer()
    206 {
    207     if (mFd == -1) {
    208         int fbNum = overlay::Overlay::getInstance()->
    209                                    getFbForDpy(HWC_DISPLAY_VIRTUAL);
    210 
    211         char strDevPath[MAX_SYSFS_FILE_PATH];
    212         snprintf(strDevPath,sizeof(strDevPath), "/dev/graphics/fb%d", fbNum);
    213 
    214         mFd = open(strDevPath, O_RDWR);
    215         if(mFd < 0) {
    216             ALOGE("%s: Unable to open %s ", __FUNCTION__,strDevPath);
    217             return -1;
    218         }
    219 
    220         mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].fd = mFd;
    221     }
    222     return 1;
    223 }
    224 
    225 bool VirtualDisplay::closeFrameBuffer()
    226 {
    227     if(mFd >= 0) {
    228         if(close(mFd) < 0 ) {
    229             ALOGE("%s: Unable to close FD(%d)", __FUNCTION__, mFd);
    230             return -1;
    231         }
    232         mFd = -1;
    233         mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].fd = mFd;
    234     }
    235     return 1;
    236 }
    237 };
    238