blob: 795d8a1d3615659da77214e06ce9b2bcd48ed97f [file] [log] [blame]
Jeykumar Sankaran27dee262013-08-01 17:09:54 -07001/*
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"
Amara Venkata Mastan Manoj Kumar376d8a82013-03-13 19:18:47 -070050#include "mdp_version.h"
Jeykumar Sankaran27dee262013-08-01 17:09:54 -070051
52using namespace android;
53
54namespace qhwc {
55
56#define MAX_SYSFS_FILE_PATH 255
57
Tatenda Chipeperekwa7f0c4222013-09-18 10:54:20 -070058/* Max. resolution assignable to virtual display. */
59#define SUPPORTED_VIRTUAL_AREA (1920*1080)
60
Jeykumar Sankaran27dee262013-08-01 17:09:54 -070061int 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
Amara Venkata Mastan Manoj Kumar376d8a82013-03-13 19:18:47 -070074void VirtualDisplay::getAttributes(int& width, int& height) {
75 width = mVInfo.xres;
76 height = mVInfo.yres;
77}
78
Jeykumar Sankaran27dee262013-08-01 17:09:54 -070079int VirtualDisplay::teardown() {
80 closeFrameBuffer();
81 memset(&mVInfo, 0, sizeof(mVInfo));
Tatenda Chipeperekwa3368d082013-08-30 14:03:15 -070082 // 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;
Jeykumar Sankaran27dee262013-08-01 17:09:54 -070086 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
Tatenda Chipeperekwa7f0c4222013-09-18 10:54:20 -0700100/* 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
Jeykumar Sankaran27dee262013-08-01 17:09:54 -0700161void VirtualDisplay::setAttributes() {
Amara Venkata Mastan Manoj Kumar376d8a82013-03-13 19:18:47 -0700162 if(mHwcContext) {
Tatenda Chipeperekwa7f0c4222013-09-18 10:54:20 -0700163 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;
Tatenda Chipeperekwa3368d082013-08-30 14:03:15 -0700167
Tatenda Chipeperekwa7f0c4222013-09-18 10:54:20 -0700168 initResolution(extW, extH);
Tatenda Chipeperekwa3368d082013-08-30 14:03:15 -0700169
Amara Venkata Mastan Manoj Kumar376d8a82013-03-13 19:18:47 -0700170 if(!qdutils::MDPVersion::getInstance().is8x26()) {
Tatenda Chipeperekwa3368d082013-08-30 14:03:15 -0700171
Tatenda Chipeperekwa7f0c4222013-09-18 10:54:20 -0700172 // maxArea represents the maximum resolution between
173 // primary and virtual display.
174 uint32_t maxArea = max((extW * extH), (priW * priH));
Tatenda Chipeperekwa3368d082013-08-30 14:03:15 -0700175
Tatenda Chipeperekwa7f0c4222013-09-18 10:54:20 -0700176 setToPrimary(maxArea, priW, priH, extW, extH);
177
178 setDownScaleMode(maxArea);
Amara Venkata Mastan Manoj Kumar376d8a82013-03-13 19:18:47 -0700179 }
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 }
Jeykumar Sankaran27dee262013-08-01 17:09:54 -0700185}
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];
Ramkumar Radhakrishnan36bd5272014-01-31 20:03:01 -0800194 snprintf(strDevPath,sizeof(strDevPath), "/dev/graphics/fb%d", fbNum);
Jeykumar Sankaran27dee262013-08-01 17:09:54 -0700195
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};