virtual.cpp revision c9cbe63708025b7aed15e251b2fb3a914fd842a0
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
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        extW = priW;
131        extH = priH;
132        // If WFD is in landscape, assign the higher dimension
133        // to WFD's xres.
134        if(priH > priW) {
135            extW = priH;
136            extH = priW;
137        }
138    }
139}
140
141/* Set External Display MDP Downscale mode indicator. Only set to
142   TRUE for the following scenarios:
143   1. Valid DRC scenarios i.e. when the original WFD resolution
144      is greater than the new/requested resolution in mVInfo.
145   2. WFD down scale path i.e. when WFD resolution is lower than
146      primary resolution.
147   Furthermore, downscale mode is only valid when downscaling from
148   SUPPORTED_VIRTUAL_AREA to a lower resolution.
149   (SUPPORTED_VIRTUAL_AREA represents the maximum resolution that
150   we can configure to the virtual display)
151*/
152void VirtualDisplay::setDownScaleMode(uint32_t maxArea) {
153    if((maxArea > (mVInfo.xres * mVInfo.yres))
154        && (maxArea <= SUPPORTED_VIRTUAL_AREA)) {
155        mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].mDownScaleMode = true;
156    }else {
157        mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].mDownScaleMode = false;
158    }
159}
160
161void VirtualDisplay::setAttributes() {
162    if(mHwcContext) {
163        uint32_t &extW = mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].xres;
164        uint32_t &extH = mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].yres;
165        uint32_t priW = mHwcContext->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
166        uint32_t priH = mHwcContext->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
167
168        initResolution(extW, extH);
169
170        if(!qdutils::MDPVersion::getInstance().is8x26()) {
171
172            // maxArea represents the maximum resolution between
173            // primary and virtual display.
174            uint32_t maxArea = max((extW * extH), (priW * priH));
175
176            setToPrimary(maxArea, priW, priH, extW, extH);
177
178            setDownScaleMode(maxArea);
179        }
180        mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].vsync_period =
181                1000000000l /60;
182        ALOGD_IF(DEBUG,"%s: Setting Virtual Attr: res(%d x %d)",__FUNCTION__,
183                 mVInfo.xres, mVInfo.yres);
184    }
185}
186
187bool VirtualDisplay::openFrameBuffer()
188{
189    if (mFd == -1) {
190        int fbNum = overlay::Overlay::getInstance()->
191                                   getFbForDpy(HWC_DISPLAY_VIRTUAL);
192
193        char strDevPath[MAX_SYSFS_FILE_PATH];
194        snprintf(strDevPath,sizeof(strDevPath), "/dev/graphics/fb%d", fbNum);
195
196        mFd = open(strDevPath, O_RDWR);
197        if(mFd < 0) {
198            ALOGE("%s: Unable to open %s ", __FUNCTION__,strDevPath);
199            return -1;
200        }
201
202        mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].fd = mFd;
203    }
204    return 1;
205}
206
207bool VirtualDisplay::closeFrameBuffer()
208{
209    if(mFd >= 0) {
210        if(close(mFd) < 0 ) {
211            ALOGE("%s: Unable to close FD(%d)", __FUNCTION__, mFd);
212            return -1;
213        }
214        mFd = -1;
215        mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].fd = mFd;
216    }
217    return 1;
218}
219};
220