blob: 44d060380ac7151876bb2601a83896939e488c95 [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"
Tatenda Chipeperekwaf080b792014-03-05 19:32:33 -080050#include "qd_utils.h"
Jeykumar Sankaran27dee262013-08-01 17:09:54 -070051
52using namespace android;
Tatenda Chipeperekwace8d5c42014-08-13 10:53:49 -070053using namespace qdutils;
Jeykumar Sankaran27dee262013-08-01 17:09:54 -070054
55namespace qhwc {
56
Jeykumar Sankaran27dee262013-08-01 17:09:54 -070057int VirtualDisplay::configure() {
58 if(!openFrameBuffer())
59 return -1;
60
61 if(ioctl(mFd, FBIOGET_VSCREENINFO, &mVInfo) < 0) {
62 ALOGD("%s: FBIOGET_VSCREENINFO failed with %s", __FUNCTION__,
63 strerror(errno));
64 return -1;
65 }
66 setAttributes();
67 return 0;
68}
69
Amara Venkata Mastan Manoj Kumar376d8a82013-03-13 19:18:47 -070070void VirtualDisplay::getAttributes(int& width, int& height) {
71 width = mVInfo.xres;
72 height = mVInfo.yres;
73}
74
Jeykumar Sankaran27dee262013-08-01 17:09:54 -070075int VirtualDisplay::teardown() {
76 closeFrameBuffer();
77 memset(&mVInfo, 0, sizeof(mVInfo));
Tatenda Chipeperekwa3368d082013-08-30 14:03:15 -070078 // Reset the resolution when we close the fb for this device. We need
79 // this to distinguish between an ONLINE and RESUME event.
80 mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].xres = 0;
81 mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].yres = 0;
Jeykumar Sankaran27dee262013-08-01 17:09:54 -070082 return 0;
83}
84
85VirtualDisplay::VirtualDisplay(hwc_context_t* ctx):mFd(-1),
86 mHwcContext(ctx)
87{
88 memset(&mVInfo, 0, sizeof(mVInfo));
89}
90
91VirtualDisplay::~VirtualDisplay()
92{
93 closeFrameBuffer();
94}
95
Tatenda Chipeperekwa7f0c4222013-09-18 10:54:20 -070096/* Initializes the resolution attributes of the virtual display
97 that are reported to SurfaceFlinger.
98 Cases:
99 1. ONLINE event - initialize to frame buffer resolution
100 2. RESUME event - retain original resolution
101*/
102void VirtualDisplay::initResolution(uint32_t &extW, uint32_t &extH) {
103 // On ONLINE event, display resolution attributes are 0.
104 if(extW == 0 || extH == 0){
105 extW = mVInfo.xres;
106 extH = mVInfo.yres;
107 }
108}
109
110/* Sets the virtual resolution to match that of the primary
111 display in the event that the virtual display currently
112 connected has a lower resolution. NB: we always report the
113 highest available resolution to SurfaceFlinger.
114*/
115void VirtualDisplay::setToPrimary(uint32_t maxArea,
116 uint32_t priW,
117 uint32_t priH,
118 uint32_t &extW,
119 uint32_t &extH) {
120 // for eg., primary in 1600p and WFD in 1080p
121 // we wont use downscale feature because MAX MDP
122 // writeback resolution supported is 1080p (tracked
Tatenda Chipeperekwace8d5c42014-08-13 10:53:49 -0700123 // by SUPPORTED_DOWNSCALE_AREA).
Tatenda Chipeperekwa7f0c4222013-09-18 10:54:20 -0700124 if((maxArea == (priW * priH))
Tatenda Chipeperekwace8d5c42014-08-13 10:53:49 -0700125 && (maxArea <= SUPPORTED_DOWNSCALE_AREA)) {
Tatenda Chipeperekwaf080b792014-03-05 19:32:33 -0800126 // tmpW and tmpH will hold the primary dimensions before we
127 // update the aspect ratio if necessary.
128 uint32_t tmpW = priW;
129 uint32_t tmpH = priH;
Tatenda Chipeperekwa7f0c4222013-09-18 10:54:20 -0700130 // If WFD is in landscape, assign the higher dimension
131 // to WFD's xres.
132 if(priH > priW) {
Tatenda Chipeperekwaf080b792014-03-05 19:32:33 -0800133 tmpW = priH;
134 tmpH = priW;
Tatenda Chipeperekwa7f0c4222013-09-18 10:54:20 -0700135 }
Tatenda Chipeperekwaf080b792014-03-05 19:32:33 -0800136 // The aspect ratios of the external and primary displays
137 // can be different. As a result, directly assigning primary
138 // resolution could lead to an incorrect final image.
139 // We get around this by calculating a new resolution by
140 // keeping aspect ratio intact.
141 hwc_rect r = {0, 0, 0, 0};
Tatenda Chipeperekwace8d5c42014-08-13 10:53:49 -0700142 qdutils::getAspectRatioPosition(tmpW, tmpH, extW, extH, r);
Tatenda Chipeperekwaf080b792014-03-05 19:32:33 -0800143 extW = r.right - r.left;
144 extH = r.bottom - r.top;
Tatenda Chipeperekwa7f0c4222013-09-18 10:54:20 -0700145 }
146}
147
148/* Set External Display MDP Downscale mode indicator. Only set to
149 TRUE for the following scenarios:
150 1. Valid DRC scenarios i.e. when the original WFD resolution
151 is greater than the new/requested resolution in mVInfo.
152 2. WFD down scale path i.e. when WFD resolution is lower than
153 primary resolution.
154 Furthermore, downscale mode is only valid when downscaling from
Tatenda Chipeperekwace8d5c42014-08-13 10:53:49 -0700155 SUPPORTED_DOWNSCALE_AREA to a lower resolution.
156 (SUPPORTED_DOWNSCALE_AREA represents the maximum resolution that
Tatenda Chipeperekwa7f0c4222013-09-18 10:54:20 -0700157 we can configure to the virtual display)
158*/
159void VirtualDisplay::setDownScaleMode(uint32_t maxArea) {
160 if((maxArea > (mVInfo.xres * mVInfo.yres))
Tatenda Chipeperekwace8d5c42014-08-13 10:53:49 -0700161 && (maxArea <= SUPPORTED_DOWNSCALE_AREA)) {
Tatenda Chipeperekwa7f0c4222013-09-18 10:54:20 -0700162 mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].mDownScaleMode = true;
163 }else {
164 mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].mDownScaleMode = false;
165 }
166}
167
Jeykumar Sankaran27dee262013-08-01 17:09:54 -0700168void VirtualDisplay::setAttributes() {
Amara Venkata Mastan Manoj Kumar376d8a82013-03-13 19:18:47 -0700169 if(mHwcContext) {
Tatenda Chipeperekwa7f0c4222013-09-18 10:54:20 -0700170 uint32_t &extW = mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].xres;
171 uint32_t &extH = mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].yres;
172 uint32_t priW = mHwcContext->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
173 uint32_t priH = mHwcContext->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
Tatenda Chipeperekwa3368d082013-08-30 14:03:15 -0700174
Tatenda Chipeperekwa5d14c712014-02-20 19:07:01 -0800175 // Dynamic Resolution Change depends on MDP downscaling.
176 // MDP downscale property will be ignored to exercise DRC use case.
177 // If DRC is in progress, ext WxH will have non-zero values.
Tatenda Chipeperekwa94a09b62014-04-08 11:41:37 -0700178 bool isDRC = (extW > mVInfo.xres) && (extH > mVInfo.yres);
179
180 initResolution(extW, extH);
Tatenda Chipeperekwa5d14c712014-02-20 19:07:01 -0800181
Raj Kamal068f4572014-04-14 16:14:06 +0530182 if(mHwcContext->mOverlay->isUIScalingOnExternalSupported()
Tatenda Chipeperekwa5d14c712014-02-20 19:07:01 -0800183 && (mHwcContext->mMDPDownscaleEnabled || isDRC)) {
Tatenda Chipeperekwa3368d082013-08-30 14:03:15 -0700184
Tatenda Chipeperekwa7f0c4222013-09-18 10:54:20 -0700185 // maxArea represents the maximum resolution between
186 // primary and virtual display.
187 uint32_t maxArea = max((extW * extH), (priW * priH));
Tatenda Chipeperekwa3368d082013-08-30 14:03:15 -0700188
Tatenda Chipeperekwa7f0c4222013-09-18 10:54:20 -0700189 setToPrimary(maxArea, priW, priH, extW, extH);
190
191 setDownScaleMode(maxArea);
Amara Venkata Mastan Manoj Kumar376d8a82013-03-13 19:18:47 -0700192 }
Arun Kumar K.Rdb7d83a2014-06-25 00:53:34 -0700193 //Initialize the display viewFrame info
194 mHwcContext->mViewFrame[HWC_DISPLAY_VIRTUAL].left = 0;
195 mHwcContext->mViewFrame[HWC_DISPLAY_VIRTUAL].top = 0;
196 mHwcContext->mViewFrame[HWC_DISPLAY_VIRTUAL].right =
197 (int)mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].xres;
198 mHwcContext->mViewFrame[HWC_DISPLAY_VIRTUAL].bottom =
199 (int)mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].yres;
Amara Venkata Mastan Manoj Kumar376d8a82013-03-13 19:18:47 -0700200 mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].vsync_period =
201 1000000000l /60;
202 ALOGD_IF(DEBUG,"%s: Setting Virtual Attr: res(%d x %d)",__FUNCTION__,
203 mVInfo.xres, mVInfo.yres);
204 }
Jeykumar Sankaran27dee262013-08-01 17:09:54 -0700205}
206
207bool VirtualDisplay::openFrameBuffer()
208{
209 if (mFd == -1) {
210 int fbNum = overlay::Overlay::getInstance()->
211 getFbForDpy(HWC_DISPLAY_VIRTUAL);
212
Tatenda Chipeperekwace8d5c42014-08-13 10:53:49 -0700213 char strDevPath[qdutils::MAX_SYSFS_FILE_PATH];
Ramkumar Radhakrishnan36bd5272014-01-31 20:03:01 -0800214 snprintf(strDevPath,sizeof(strDevPath), "/dev/graphics/fb%d", fbNum);
Jeykumar Sankaran27dee262013-08-01 17:09:54 -0700215
216 mFd = open(strDevPath, O_RDWR);
217 if(mFd < 0) {
218 ALOGE("%s: Unable to open %s ", __FUNCTION__,strDevPath);
219 return -1;
220 }
221
222 mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].fd = mFd;
223 }
224 return 1;
225}
226
227bool VirtualDisplay::closeFrameBuffer()
228{
229 if(mFd >= 0) {
230 if(close(mFd) < 0 ) {
231 ALOGE("%s: Unable to close FD(%d)", __FUNCTION__, mFd);
232 return -1;
233 }
234 mFd = -1;
235 mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].fd = mFd;
236 }
237 return 1;
238}
239};