blob: f6d82767fa126b3e190d11ea2c31f813040f8518 [file] [log] [blame]
Naseer Ahmed7c958d42012-07-31 18:57:03 -07001/*
Tatenda Chipeperekwa95675a72014-12-15 17:06:43 -08002 * Copyright (C) 2012-2015, The Linux Foundation. All rights reserved.
Naseer Ahmed7c958d42012-07-31 18:57:03 -07003 * Not a Contribution, Apache license notifications and license are retained
4 * for attribution purposes only.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
Saurabh Shah4fdde762013-04-30 18:47:33 -070019#include <math.h>
Naseer Ahmed7c958d42012-07-31 18:57:03 -070020#include "hwc_mdpcomp.h"
Naseer Ahmed54821fe2012-11-28 18:44:38 -050021#include <sys/ioctl.h>
Arun Kumar K.R299bcda2014-12-18 19:36:40 -080022#include <dlfcn.h>
Tatenda Chipeperekwaaf2c0042014-09-17 12:55:01 -070023#include "hdmi.h"
Ramkumar Radhakrishnan47573e22012-11-07 11:36:41 -080024#include "qdMetaData.h"
Ramkumar Radhakrishnan288f8c72013-01-15 11:37:54 -080025#include "mdp_version.h"
Saurabh Shah2a4eb1b2013-07-22 16:33:23 -070026#include "hwc_fbupdate.h"
Saurabh Shaha9da08f2013-07-03 13:27:53 -070027#include "hwc_ad.h"
Saurabh Shahacf10202013-02-26 10:15:15 -080028#include <overlayRotator.h>
Sushil Chauhandefd3522014-05-13 18:17:12 -070029#include "hwc_copybit.h"
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -070030#include "qd_utils.h"
Saurabh Shahacf10202013-02-26 10:15:15 -080031
Saurabh Shah85234ec2013-04-12 17:09:00 -070032using namespace overlay;
Saurabh Shahbd2d0832013-04-04 14:33:08 -070033using namespace qdutils;
Saurabh Shahacf10202013-02-26 10:15:15 -080034using namespace overlay::utils;
35namespace ovutils = overlay::utils;
Naseer Ahmed7c958d42012-07-31 18:57:03 -070036
Naseer Ahmed7c958d42012-07-31 18:57:03 -070037namespace qhwc {
38
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -080039//==============MDPComp========================================================
40
Saurabh Shah59562ff2014-09-30 16:13:12 -070041IdleInvalidator *MDPComp::sIdleInvalidator = NULL;
Naseer Ahmed7c958d42012-07-31 18:57:03 -070042bool MDPComp::sIdleFallBack = false;
43bool MDPComp::sDebugLogs = false;
Naseer Ahmed54821fe2012-11-28 18:44:38 -050044bool MDPComp::sEnabled = false;
Jeykumar Sankaran24c199d2013-05-24 09:40:36 -070045bool MDPComp::sEnableMixedMode = true;
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -070046int MDPComp::sSimulationFlags = 0;
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -070047int MDPComp::sMaxPipesPerMixer = 0;
Raj Kamal389d6e32014-08-04 14:43:24 +053048bool MDPComp::sEnableYUVsplit = false;
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -070049bool MDPComp::sSrcSplitEnabled = false;
Saurabh Shahacec8e42014-11-25 11:07:04 -080050int MDPComp::sMaxSecLayers = 1;
Dileep Kumar Reddi4070e932014-09-30 09:00:57 +053051bool MDPComp::enablePartialUpdateForMDP3 = false;
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -070052bool MDPComp::sIsPartialUpdateActive = true;
Arun Kumar K.R299bcda2014-12-18 19:36:40 -080053void *MDPComp::sLibPerfHint = NULL;
54int MDPComp::sPerfLockHandle = 0;
55int (*MDPComp::sPerfLockAcquire)(int, int, int*, int) = NULL;
56int (*MDPComp::sPerfLockRelease)(int value) = NULL;
57int MDPComp::sPerfHintWindow = -1;
58
Saurabh Shah88e4d272013-09-03 13:31:29 -070059MDPComp* MDPComp::getObject(hwc_context_t *ctx, const int& dpy) {
Saurabh Shah60e8bde2014-04-30 14:46:03 -070060 if(qdutils::MDPVersion::getInstance().isSrcSplit()) {
61 sSrcSplitEnabled = true;
62 return new MDPCompSrcSplit(dpy);
63 } else if(isDisplaySplit(ctx, dpy)) {
Saurabh Shah88e4d272013-09-03 13:31:29 -070064 return new MDPCompSplit(dpy);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -080065 }
Saurabh Shah88e4d272013-09-03 13:31:29 -070066 return new MDPCompNonSplit(dpy);
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -080067}
68
Jeykumar Sankaran85977e32013-02-25 17:06:08 -080069MDPComp::MDPComp(int dpy):mDpy(dpy){};
70
Jeykumar Sankaran6850ac62014-05-27 10:07:26 -070071void MDPComp::dump(android::String8& buf, hwc_context_t *ctx)
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -080072{
Jeykumar Sankaran3c6bb042013-08-15 14:01:04 -070073 if(mCurrentFrame.layerCount > MAX_NUM_APP_LAYERS)
74 return;
75
Jeykumar Sankaran85977e32013-02-25 17:06:08 -080076 dumpsys_log(buf,"HWC Map for Dpy: %s \n",
Jeykumar Sankaran27dee262013-08-01 17:09:54 -070077 (mDpy == 0) ? "\"PRIMARY\"" :
78 (mDpy == 1) ? "\"EXTERNAL\"" : "\"VIRTUAL\"");
Saurabh Shahe9bc60f2013-08-29 12:58:06 -070079 dumpsys_log(buf,"CURR_FRAME: layerCount:%2d mdpCount:%2d "
80 "fbCount:%2d \n", mCurrentFrame.layerCount,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -080081 mCurrentFrame.mdpCount, mCurrentFrame.fbCount);
82 dumpsys_log(buf,"needsFBRedraw:%3s pipesUsed:%2d MaxPipesPerMixer: %d \n",
83 (mCurrentFrame.needsRedraw? "YES" : "NO"),
84 mCurrentFrame.mdpCount, sMaxPipesPerMixer);
Jeykumar Sankaran6850ac62014-05-27 10:07:26 -070085 if(isDisplaySplit(ctx, mDpy)) {
86 dumpsys_log(buf, "Programmed ROI's: Left: [%d, %d, %d, %d] "
87 "Right: [%d, %d, %d, %d] \n",
88 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
89 ctx->listStats[mDpy].lRoi.right,
90 ctx->listStats[mDpy].lRoi.bottom,
91 ctx->listStats[mDpy].rRoi.left,ctx->listStats[mDpy].rRoi.top,
92 ctx->listStats[mDpy].rRoi.right,
93 ctx->listStats[mDpy].rRoi.bottom);
94 } else {
95 dumpsys_log(buf, "Programmed ROI: [%d, %d, %d, %d] \n",
96 ctx->listStats[mDpy].lRoi.left,ctx->listStats[mDpy].lRoi.top,
97 ctx->listStats[mDpy].lRoi.right,
98 ctx->listStats[mDpy].lRoi.bottom);
99 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800100 dumpsys_log(buf," --------------------------------------------- \n");
101 dumpsys_log(buf," listIdx | cached? | mdpIndex | comptype | Z \n");
102 dumpsys_log(buf," --------------------------------------------- \n");
103 for(int index = 0; index < mCurrentFrame.layerCount; index++ )
104 dumpsys_log(buf," %7d | %7s | %8d | %9s | %2d \n",
105 index,
106 (mCurrentFrame.isFBComposed[index] ? "YES" : "NO"),
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700107 mCurrentFrame.layerToMDP[index],
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800108 (mCurrentFrame.isFBComposed[index] ?
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700109 (mCurrentFrame.drop[index] ? "DROP" :
110 (mCurrentFrame.needsRedraw ? "GLES" : "CACHE")) : "MDP"),
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800111 (mCurrentFrame.isFBComposed[index] ? mCurrentFrame.fbZ :
112 mCurrentFrame.mdpToLayer[mCurrentFrame.layerToMDP[index]].pipeInfo->zOrder));
113 dumpsys_log(buf,"\n");
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800114}
115
116bool MDPComp::init(hwc_context_t *ctx) {
117
118 if(!ctx) {
119 ALOGE("%s: Invalid hwc context!!",__FUNCTION__);
120 return false;
121 }
122
Saurabh Shah59562ff2014-09-30 16:13:12 -0700123 char property[PROPERTY_VALUE_MAX] = {0};
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800124
125 sEnabled = false;
Dileep Kumar Reddid8e601d2014-10-28 18:20:43 +0530126 if((ctx->mMDP.version >= qdutils::MDP_V4_0) &&
127 (property_get("persist.hwc.mdpcomp.enable", property, NULL) > 0) &&
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800128 (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
129 (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800130 sEnabled = true;
131 }
132
Jeykumar Sankaran24c199d2013-05-24 09:40:36 -0700133 sEnableMixedMode = true;
134 if((property_get("debug.mdpcomp.mixedmode.disable", property, NULL) > 0) &&
135 (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
136 (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
137 sEnableMixedMode = false;
138 }
139
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700140 qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
141
Saurabh Shah2fd8a252014-12-05 13:49:53 -0800142 sMaxPipesPerMixer = (int)mdpVersion.getBlendStages();
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700143 if(property_get("persist.hwc.mdpcomp.maxpermixer", property, "-1") > 0) {
Saurabh Shah85234ec2013-04-12 17:09:00 -0700144 int val = atoi(property);
145 if(val >= 0)
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700146 sMaxPipesPerMixer = min(val, sMaxPipesPerMixer);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800147 }
148
Saurabh Shahacec8e42014-11-25 11:07:04 -0800149 /* Maximum layers allowed to use MDP on secondary panels. If property
150 * doesn't exist, default to 1. Using the property it can be set to 0 or
151 * more.
152 */
153 if(property_get("persist.hwc.maxseclayers", property, "1") > 0) {
154 int val = atoi(property);
155 sMaxSecLayers = (val >= 0) ? val : 1;
156 sMaxSecLayers = min(sMaxSecLayers, sMaxPipesPerMixer);
157 }
158
Naseer Ahmedf40f2c82013-08-14 16:42:40 -0400159 if(ctx->mMDP.panel != MIPI_CMD_PANEL) {
Saurabh Shah59562ff2014-09-30 16:13:12 -0700160 sIdleInvalidator = IdleInvalidator::getInstance();
161 if(sIdleInvalidator->init(timeout_handler, ctx) < 0) {
162 delete sIdleInvalidator;
163 sIdleInvalidator = NULL;
Naseer Ahmedf40f2c82013-08-14 16:42:40 -0400164 }
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800165 }
radhakrishnac9a67412013-09-25 17:40:42 +0530166
Saurabh Shah7c727642014-06-02 15:47:14 -0700167 if(!qdutils::MDPVersion::getInstance().isSrcSplit() &&
Saurabh Shahc46cf9d2014-07-02 15:22:34 -0700168 !qdutils::MDPVersion::getInstance().isRotDownscaleEnabled() &&
Saurabh Shah7c727642014-06-02 15:47:14 -0700169 property_get("persist.mdpcomp.4k2kSplit", property, "0") > 0 &&
170 (!strncmp(property, "1", PROPERTY_VALUE_MAX) ||
171 !strncasecmp(property,"true", PROPERTY_VALUE_MAX))) {
Raj Kamal389d6e32014-08-04 14:43:24 +0530172 sEnableYUVsplit = true;
radhakrishnac9a67412013-09-25 17:40:42 +0530173 }
Sushil Chauhandefd3522014-05-13 18:17:12 -0700174
Dileep Kumar Reddic6ef3472014-09-24 19:07:08 +0530175 bool defaultPTOR = false;
176 //Enable PTOR when "persist.hwc.ptor.enable" is not defined for
177 //8x16 and 8x39 targets by default
178 if((property_get("persist.hwc.ptor.enable", property, NULL) <= 0) &&
179 (qdutils::MDPVersion::getInstance().is8x16() ||
180 qdutils::MDPVersion::getInstance().is8x39())) {
181 defaultPTOR = true;
182 }
183
184 if (defaultPTOR || (!strncasecmp(property, "true", PROPERTY_VALUE_MAX)) ||
185 (!strncmp(property, "1", PROPERTY_VALUE_MAX ))) {
Sushil Chauhandefd3522014-05-13 18:17:12 -0700186 ctx->mCopyBit[HWC_DISPLAY_PRIMARY] = new CopyBit(ctx,
187 HWC_DISPLAY_PRIMARY);
188 }
189
Dileep Kumar Reddi4070e932014-09-30 09:00:57 +0530190 if((property_get("persist.mdp3.partialUpdate", property, NULL) <= 0) &&
191 (ctx->mMDP.version == qdutils::MDP_V3_0_5)) {
192 enablePartialUpdateForMDP3 = true;
193 }
194
195 if(!enablePartialUpdateForMDP3 &&
196 (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
197 (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
198 enablePartialUpdateForMDP3 = true;
199 }
200
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -0800201 sIsPartialUpdateActive = getPartialUpdatePref(ctx);
202
Arun Kumar K.R299bcda2014-12-18 19:36:40 -0800203 if(property_get("persist.mdpcomp_perfhint", property, "-1") > 0) {
204 int val = atoi(property);
205 if(val > 0 && loadPerfLib()) {
206 sPerfHintWindow = val;
207 ALOGI("PerfHintWindow = %d", sPerfHintWindow);
208 }
209 }
210
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700211 return true;
212}
213
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800214void MDPComp::reset(hwc_context_t *ctx) {
215 const int numLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shah2a4eb1b2013-07-22 16:33:23 -0700216 mCurrentFrame.reset(numLayers);
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800217 ctx->mOverlay->clear(mDpy);
218 ctx->mLayerRotMap[mDpy]->clear();
Saurabh Shah2a4eb1b2013-07-22 16:33:23 -0700219}
220
Raj Kamal4393eaa2014-06-06 13:45:20 +0530221void MDPComp::reset() {
Raj Kamalfdfdddf2015-03-16 21:59:25 +0530222 mPrevModeOn = mModeOn;
Raj Kamal4393eaa2014-06-06 13:45:20 +0530223 mModeOn = false;
224}
225
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700226void MDPComp::timeout_handler(void *udata) {
227 struct hwc_context_t* ctx = (struct hwc_context_t*)(udata);
Raj Kamalfdfdddf2015-03-16 21:59:25 +0530228 bool handleTimeout = false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700229
230 if(!ctx) {
231 ALOGE("%s: received empty data in timer callback", __FUNCTION__);
232 return;
233 }
Raj Kamal58b31a02014-12-16 15:53:53 +0530234
235 ctx->mDrawLock.lock();
Raj Kamalfdfdddf2015-03-16 21:59:25 +0530236
237 /* Handle timeout event only if the previous composition
238 on any display is MDP or MIXED*/
239 for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
240 if(ctx->mMDPComp[i])
241 handleTimeout =
242 ctx->mMDPComp[i]->isMDPComp() || handleTimeout;
243 }
244
245 if(!handleTimeout) {
Ramkumar Radhakrishnan92abb4f2014-02-06 21:31:29 -0800246 ALOGD_IF(isDebug(), "%s:Do not handle this timeout", __FUNCTION__);
Raj Kamal58b31a02014-12-16 15:53:53 +0530247 ctx->mDrawLock.unlock();
Ramkumar Radhakrishnan92abb4f2014-02-06 21:31:29 -0800248 return;
249 }
Jesse Hall3be78d92012-08-21 15:12:23 -0700250 if(!ctx->proc) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700251 ALOGE("%s: HWC proc not registered", __FUNCTION__);
Raj Kamal58b31a02014-12-16 15:53:53 +0530252 ctx->mDrawLock.unlock();
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700253 return;
254 }
255 sIdleFallBack = true;
Raj Kamal58b31a02014-12-16 15:53:53 +0530256 ctx->mDrawLock.unlock();
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700257 /* Trigger SF to redraw the current frame */
Jesse Hall3be78d92012-08-21 15:12:23 -0700258 ctx->proc->invalidate(ctx->proc);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700259}
260
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700261void MDPComp::setMaxPipesPerMixer(const uint32_t value) {
262 qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
Saurabh Shah2fd8a252014-12-05 13:49:53 -0800263 uint32_t maxSupported = (int)mdpVersion.getBlendStages();
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700264 if(value > maxSupported) {
265 ALOGW("%s: Input exceeds max value supported. Setting to"
266 "max value: %d", __FUNCTION__, maxSupported);
267 }
268 sMaxPipesPerMixer = min(value, maxSupported);
269}
270
Saurabh Shah59562ff2014-09-30 16:13:12 -0700271void MDPComp::setIdleTimeout(const uint32_t& timeout) {
272 enum { ONE_REFRESH_PERIOD_MS = 17, ONE_BILLION_MS = 1000000000 };
273
274 if(sIdleInvalidator) {
275 if(timeout <= ONE_REFRESH_PERIOD_MS) {
276 //If the specified timeout is < 1 draw cycle worth, "virtually"
277 //disable idle timeout. The ideal way for clients to disable
278 //timeout is to set it to 0
279 sIdleInvalidator->setIdleTimeout(ONE_BILLION_MS);
280 ALOGI("Disabled idle timeout");
281 return;
282 }
283 sIdleInvalidator->setIdleTimeout(timeout);
284 ALOGI("Idle timeout set to %u", timeout);
285 } else {
286 ALOGW("Cannot set idle timeout, IdleInvalidator not enabled");
287 }
288}
289
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800290void MDPComp::setMDPCompLayerFlags(hwc_context_t *ctx,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800291 hwc_display_contents_1_t* list) {
292 LayerProp *layerProp = ctx->layerProp[mDpy];
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800293
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800294 for(int index = 0; index < ctx->listStats[mDpy].numAppLayers; index++) {
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800295 hwc_layer_1_t* layer = &(list->hwLayers[index]);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800296 if(!mCurrentFrame.isFBComposed[index]) {
297 layerProp[index].mFlags |= HWC_MDPCOMP;
298 layer->compositionType = HWC_OVERLAY;
299 layer->hints |= HWC_HINT_CLEAR_FB;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800300 } else {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700301 /* Drop the layer when its already present in FB OR when it lies
302 * outside frame's ROI */
303 if(!mCurrentFrame.needsRedraw || mCurrentFrame.drop[index]) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800304 layer->compositionType = HWC_OVERLAY;
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700305 }
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800306 }
307 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700308}
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500309
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800310void MDPComp::setRedraw(hwc_context_t *ctx,
311 hwc_display_contents_1_t* list) {
312 mCurrentFrame.needsRedraw = false;
313 if(!mCachedFrame.isSameFrame(mCurrentFrame, list) ||
314 (list->flags & HWC_GEOMETRY_CHANGED) ||
315 isSkipPresent(ctx, mDpy)) {
316 mCurrentFrame.needsRedraw = true;
317 }
318}
319
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800320MDPComp::FrameInfo::FrameInfo() {
Saurabh Shahf7fad542014-08-14 10:11:36 -0700321 memset(&mdpToLayer, 0, sizeof(mdpToLayer));
Saurabh Shahaa236822013-04-24 18:07:26 -0700322 reset(0);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800323}
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800324
Saurabh Shahaa236822013-04-24 18:07:26 -0700325void MDPComp::FrameInfo::reset(const int& numLayers) {
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700326 for(int i = 0 ; i < MAX_NUM_BLEND_STAGES; i++ ) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800327 if(mdpToLayer[i].pipeInfo) {
328 delete mdpToLayer[i].pipeInfo;
329 mdpToLayer[i].pipeInfo = NULL;
330 //We dont own the rotator
331 mdpToLayer[i].rot = NULL;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800332 }
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800333 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800334
335 memset(&mdpToLayer, 0, sizeof(mdpToLayer));
336 memset(&layerToMDP, -1, sizeof(layerToMDP));
Saurabh Shahaa236822013-04-24 18:07:26 -0700337 memset(&isFBComposed, 1, sizeof(isFBComposed));
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800338
Saurabh Shahaa236822013-04-24 18:07:26 -0700339 layerCount = numLayers;
340 fbCount = numLayers;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800341 mdpCount = 0;
Saurabh Shah2f3895f2013-05-02 10:13:31 -0700342 needsRedraw = true;
Saurabh Shahd53bc5f2014-02-05 10:17:43 -0800343 fbZ = -1;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800344}
345
Saurabh Shahaa236822013-04-24 18:07:26 -0700346void MDPComp::FrameInfo::map() {
347 // populate layer and MDP maps
348 int mdpIdx = 0;
349 for(int idx = 0; idx < layerCount; idx++) {
350 if(!isFBComposed[idx]) {
351 mdpToLayer[mdpIdx].listIndex = idx;
352 layerToMDP[idx] = mdpIdx++;
353 }
354 }
355}
356
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800357MDPComp::LayerCache::LayerCache() {
358 reset();
359}
360
361void MDPComp::LayerCache::reset() {
Saurabh Shahaa236822013-04-24 18:07:26 -0700362 memset(&hnd, 0, sizeof(hnd));
Prabhanjan Kandula2243aa62013-10-24 12:58:55 +0530363 memset(&isFBComposed, true, sizeof(isFBComposed));
364 memset(&drop, false, sizeof(drop));
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800365 layerCount = 0;
Saurabh Shahaa236822013-04-24 18:07:26 -0700366}
367
368void MDPComp::LayerCache::cacheAll(hwc_display_contents_1_t* list) {
Praveena Pachipulusud9443c72014-02-17 10:42:28 +0530369 const int numAppLayers = (int)list->numHwLayers - 1;
Saurabh Shahaa236822013-04-24 18:07:26 -0700370 for(int i = 0; i < numAppLayers; i++) {
371 hnd[i] = list->hwLayers[i].handle;
372 }
373}
374
375void MDPComp::LayerCache::updateCounts(const FrameInfo& curFrame) {
Saurabh Shahaa236822013-04-24 18:07:26 -0700376 layerCount = curFrame.layerCount;
Prabhanjan Kandula2243aa62013-10-24 12:58:55 +0530377 memcpy(&isFBComposed, &curFrame.isFBComposed, sizeof(isFBComposed));
378 memcpy(&drop, &curFrame.drop, sizeof(drop));
379}
380
Jeykumar Sankaran988d3682013-11-15 11:57:16 -0800381bool MDPComp::LayerCache::isSameFrame(const FrameInfo& curFrame,
382 hwc_display_contents_1_t* list) {
Prabhanjan Kandula2243aa62013-10-24 12:58:55 +0530383 if(layerCount != curFrame.layerCount)
384 return false;
385 for(int i = 0; i < curFrame.layerCount; i++) {
386 if((curFrame.isFBComposed[i] != isFBComposed[i]) ||
387 (curFrame.drop[i] != drop[i])) {
388 return false;
389 }
Jeykumar Sankaran988d3682013-11-15 11:57:16 -0800390 if(curFrame.isFBComposed[i] &&
391 (hnd[i] != list->hwLayers[i].handle)){
392 return false;
393 }
Prabhanjan Kandula2243aa62013-10-24 12:58:55 +0530394 }
395 return true;
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800396}
397
Raj Kamalfdfdddf2015-03-16 21:59:25 +0530398bool MDPComp::LayerCache::isSameFrame(hwc_context_t *ctx, int dpy,
399 hwc_display_contents_1_t* list) {
400
401 if(layerCount != ctx->listStats[dpy].numAppLayers)
402 return false;
403
404 if((list->flags & HWC_GEOMETRY_CHANGED) ||
405 isSkipPresent(ctx, dpy)) {
406 return false;
407 }
408
409 for(int i = 0; i < layerCount; i++) {
410 if(hnd[i] != list->hwLayers[i].handle)
411 return false;
412 }
413
414 return true;
415}
416
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700417bool MDPComp::isSupportedForMDPComp(hwc_context_t *ctx, hwc_layer_1_t* layer) {
418 private_handle_t *hnd = (private_handle_t *)layer->handle;
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800419 if((has90Transform(layer) and (not isRotationDoable(ctx, hnd))) ||
Raj Kamal1179d9c2014-10-28 15:31:35 +0530420 (not isValidDimension(ctx,layer)) ||
421 isSkipLayer(layer)) {
422 //More conditions here, sRGB+Blend etc
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700423 return false;
424 }
425 return true;
426}
427
Sravan Kumar D.V.Nad5d9292013-04-24 14:23:04 +0530428bool MDPComp::isValidDimension(hwc_context_t *ctx, hwc_layer_1_t *layer) {
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800429 private_handle_t *hnd = (private_handle_t *)layer->handle;
430
431 if(!hnd) {
Sushil Chauhan897a9c32013-07-18 11:09:55 -0700432 if (layer->flags & HWC_COLOR_FILL) {
433 // Color layer
434 return true;
435 }
Ramkumar Radhakrishnan0cabf212014-09-08 20:07:49 -0700436 ALOGD_IF(isDebug(), "%s: layer handle is NULL", __FUNCTION__);
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800437 return false;
438 }
439
Naseer Ahmede850a802013-09-06 13:12:52 -0400440 //XXX: Investigate doing this with pixel phase on MDSS
Naseer Ahmede77f8082013-10-10 13:42:48 -0400441 if(!isSecureBuffer(hnd) && isNonIntegralSourceCrop(layer->sourceCropf))
Naseer Ahmede850a802013-09-06 13:12:52 -0400442 return false;
443
Saurabh Shah62e1d732013-09-17 10:44:05 -0700444 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
Saurabh Shah4fdde762013-04-30 18:47:33 -0700445 hwc_rect_t dst = layer->displayFrame;
Saurabh Shahb6810df2014-06-17 16:00:22 -0700446 bool rotated90 = (bool)(layer->transform & HAL_TRANSFORM_ROT_90);
Saurabh Shahe28a4022014-06-13 11:41:13 -0700447 int crop_w = rotated90 ? crop.bottom - crop.top : crop.right - crop.left;
448 int crop_h = rotated90 ? crop.right - crop.left : crop.bottom - crop.top;
Saurabh Shah4fdde762013-04-30 18:47:33 -0700449 int dst_w = dst.right - dst.left;
450 int dst_h = dst.bottom - dst.top;
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800451 float w_scale = ((float)crop_w / (float)dst_w);
452 float h_scale = ((float)crop_h / (float)dst_h);
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530453 MDPVersion& mdpHw = MDPVersion::getInstance();
Saurabh Shah4fdde762013-04-30 18:47:33 -0700454
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800455 /* Workaround for MDP HW limitation in DSI command mode panels where
456 * FPS will not go beyond 30 if buffers on RGB pipes are of width or height
457 * less than 5 pixels
Sravan Kumar D.V.Nad5d9292013-04-24 14:23:04 +0530458 * There also is a HW limilation in MDP, minimum block size is 2x2
459 * Fallback to GPU if height is less than 2.
460 */
Saurabh Shah189f23d2014-09-26 17:21:00 -0700461 if(mdpHw.hasMinCropWidthLimitation() and (crop_w < 5 or crop_h < 5))
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800462 return false;
463
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800464 if((w_scale > 1.0f) || (h_scale > 1.0f)) {
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530465 const uint32_t maxMDPDownscale = mdpHw.getMaxMDPDownscale();
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800466 const float w_dscale = w_scale;
467 const float h_dscale = h_scale;
468
Jeykumar Sankaran1706a772013-11-27 12:55:19 -0800469 if(ctx->mMDP.version >= qdutils::MDSS_V5) {
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700470
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530471 if(!mdpHw.supportsDecimation()) {
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700472 /* On targets that doesnt support Decimation (eg.,8x26)
473 * maximum downscale support is overlay pipe downscale.
474 */
Jeykumar Sankaran39305802014-12-12 17:55:57 -0800475 if(crop_w > (int) mdpHw.getMaxPipeWidth() ||
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530476 w_dscale > maxMDPDownscale ||
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700477 h_dscale > maxMDPDownscale)
Jeykumar Sankaran1706a772013-11-27 12:55:19 -0800478 return false;
479 } else {
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700480 // Decimation on macrotile format layers is not supported.
481 if(isTileRendered(hnd)) {
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530482 /* Bail out if
483 * 1. Src crop > Mixer limit on nonsplit MDPComp
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700484 * 2. exceeds maximum downscale limit
485 */
Jeykumar Sankaran39305802014-12-12 17:55:57 -0800486 if(((crop_w > (int) mdpHw.getMaxPipeWidth()) &&
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530487 !sSrcSplitEnabled) ||
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700488 w_dscale > maxMDPDownscale ||
489 h_dscale > maxMDPDownscale) {
490 return false;
491 }
492 } else if(w_dscale > 64 || h_dscale > 64)
Jeykumar Sankaran1706a772013-11-27 12:55:19 -0800493 return false;
494 }
495 } else { //A-family
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700496 if(w_dscale > maxMDPDownscale || h_dscale > maxMDPDownscale)
Saurabh Shah4fdde762013-04-30 18:47:33 -0700497 return false;
498 }
Saurabh Shah4fdde762013-04-30 18:47:33 -0700499 }
500
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800501 if((w_scale < 1.0f) || (h_scale < 1.0f)) {
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530502 const uint32_t upscale = mdpHw.getMaxMDPUpscale();
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800503 const float w_uscale = 1.0f / w_scale;
504 const float h_uscale = 1.0f / h_scale;
505
506 if(w_uscale > upscale || h_uscale > upscale)
507 return false;
508 }
509
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800510 return true;
511}
512
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800513bool MDPComp::isFrameDoable(hwc_context_t *ctx) {
Saurabh Shahaa236822013-04-24 18:07:26 -0700514 bool ret = true;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800515
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800516 if(!isEnabled()) {
517 ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
Saurabh Shahaa236822013-04-24 18:07:26 -0700518 ret = false;
Raj Kamal068f4572014-04-14 16:14:06 +0530519 } else if((qdutils::MDPVersion::getInstance().is8x26() ||
Prabhanjan Kandula958ffa92014-05-12 14:56:56 +0530520 qdutils::MDPVersion::getInstance().is8x16() ||
521 qdutils::MDPVersion::getInstance().is8x39()) &&
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800522 ctx->mVideoTransFlag &&
523 isSecondaryConnected(ctx)) {
Saurabh Shahd4e65852013-06-17 11:33:53 -0700524 //1 Padding round to shift pipes across mixers
525 ALOGD_IF(isDebug(),"%s: MDP Comp. video transition padding round",
526 __FUNCTION__);
527 ret = false;
Ramkumar Radhakrishnanf26fe9e2014-09-09 13:47:54 -0700528 } else if(qdutils::MDPVersion::getInstance().getTotalPipes() < 8) {
529 /* TODO: freeing up all the resources only for the targets having total
530 number of pipes < 8. Need to analyze number of VIG pipes used
531 for primary in previous draw cycle and accordingly decide
532 whether to fall back to full GPU comp or video only comp
533 */
534 if(isSecondaryConfiguring(ctx)) {
535 ALOGD_IF( isDebug(),"%s: External Display connection is pending",
536 __FUNCTION__);
537 ret = false;
538 } else if(ctx->isPaddingRound) {
539 ALOGD_IF(isDebug(), "%s: padding round invoked for dpy %d",
540 __FUNCTION__,mDpy);
541 ret = false;
542 }
Tatenda Chipeperekwadc8d7082014-11-04 16:41:50 -0800543 } else if (ctx->isDMAStateChanging) {
544 // Bail out if a padding round has been invoked in order to switch DMA
545 // state to block mode. We need this to cater for the case when a layer
546 // requires rotation in the current frame.
547 ALOGD_IF(isDebug(), "%s: padding round invoked to switch DMA state",
548 __FUNCTION__);
549 return false;
Saurabh Shah0ceeb6a2013-04-23 10:46:07 -0700550 }
Tatenda Chipeperekwadc8d7082014-11-04 16:41:50 -0800551
Saurabh Shahaa236822013-04-24 18:07:26 -0700552 return ret;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800553}
554
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800555void MDPCompNonSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect &crop,
556 hwc_rect &dst) {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800557 hwc_rect_t roi = ctx->listStats[mDpy].lRoi;
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800558 dst = getIntersection(dst, roi);
559 crop = dst;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800560}
561
562/* 1) Identify layers that are not visible or lying outside the updating ROI and
563 * drop them from composition.
564 * 2) If we have a scaling layer which needs cropping against generated
565 * ROI, reset ROI to full resolution. */
566bool MDPCompNonSplit::validateAndApplyROI(hwc_context_t *ctx,
567 hwc_display_contents_1_t* list) {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700568 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800569 hwc_rect_t visibleRect = ctx->listStats[mDpy].lRoi;
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800570
571 for(int i = numAppLayers - 1; i >= 0; i--){
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800572 if(!isValidRect(visibleRect)) {
573 mCurrentFrame.drop[i] = true;
574 mCurrentFrame.dropCount++;
Jeykumar Sankaran0b961452014-01-21 17:26:12 -0800575 continue;
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800576 }
577
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700578 const hwc_layer_1_t* layer = &list->hwLayers[i];
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700579 hwc_rect_t dstRect = layer->displayFrame;
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800580 hwc_rect_t res = getIntersection(visibleRect, dstRect);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700581
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700582 if(!isValidRect(res)) {
583 mCurrentFrame.drop[i] = true;
584 mCurrentFrame.dropCount++;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800585 } else {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700586 /* Reset frame ROI when any layer which needs scaling also needs ROI
587 * cropping */
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800588 if(!isSameRect(res, dstRect) && needsScaling (layer)) {
Arpita Banerjeed8965982013-11-08 17:27:33 -0800589 ALOGI("%s: Resetting ROI due to scaling", __FUNCTION__);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700590 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
591 mCurrentFrame.dropCount = 0;
592 return false;
593 }
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800594
Jeykumar Sankaran0b961452014-01-21 17:26:12 -0800595 /* deduct any opaque region from visibleRect */
radhakrishna4efbdd62014-11-03 13:19:27 +0530596 if (layer->blending == HWC_BLENDING_NONE &&
597 layer->planeAlpha == 0xFF)
Jeykumar Sankaran0b961452014-01-21 17:26:12 -0800598 visibleRect = deductRect(visibleRect, res);
599 }
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700600 }
601 return true;
602}
603
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800604/* Calculate ROI for the frame by accounting all the layer's dispalyFrame which
605 * are updating. If DirtyRegion is applicable, calculate it by accounting all
606 * the changing layer's dirtyRegion. */
607void MDPCompNonSplit::generateROI(hwc_context_t *ctx,
608 hwc_display_contents_1_t* list) {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700609 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800610 if(!canPartialUpdate(ctx, list))
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700611 return;
612
613 struct hwc_rect roi = (struct hwc_rect){0, 0, 0, 0};
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800614 hwc_rect fullFrame = (struct hwc_rect) {0, 0,(int)ctx->dpyAttr[mDpy].xres,
615 (int)ctx->dpyAttr[mDpy].yres};
616
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700617 for(int index = 0; index < numAppLayers; index++ ) {
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800618 hwc_layer_1_t* layer = &list->hwLayers[index];
619 if ((mCachedFrame.hnd[index] != layer->handle) ||
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800620 isYuvBuffer((private_handle_t *)layer->handle)) {
Jeykumar Sankaran455678c2014-05-30 10:22:38 -0700621 hwc_rect_t dst = layer->displayFrame;
622 hwc_rect_t updatingRect = dst;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800623
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800624#ifdef QCOM_BSP
Dileep Kumar Reddi7399d5c2014-12-31 18:01:19 +0530625 if(!needsScaling(layer) && !layer->transform &&
626 (!isYuvBuffer((private_handle_t *)layer->handle)))
Jeykumar Sankaran455678c2014-05-30 10:22:38 -0700627 {
628 hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
629 int x_off = dst.left - src.left;
630 int y_off = dst.top - src.top;
631 updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
632 }
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800633#endif
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800634
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800635 roi = getUnion(roi, updatingRect);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700636 }
637 }
638
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800639 /* No layer is updating. Still SF wants a refresh.*/
640 if(!isValidRect(roi))
641 return;
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800642
643 // Align ROI coordinates to panel restrictions
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800644 roi = getSanitizeROI(roi, fullFrame);
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800645
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800646 ctx->listStats[mDpy].lRoi = roi;
647 if(!validateAndApplyROI(ctx, list))
648 resetROI(ctx, mDpy);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700649
650 ALOGD_IF(isDebug(),"%s: generated ROI: [%d, %d, %d, %d]", __FUNCTION__,
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800651 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
652 ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom);
653}
654
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800655void MDPCompSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect &crop,
656 hwc_rect &dst) {
657 hwc_rect roi = getUnion(ctx->listStats[mDpy].lRoi,
658 ctx->listStats[mDpy].rRoi);
659 hwc_rect tmpDst = getIntersection(dst, roi);
660 if(!isSameRect(dst, tmpDst)) {
661 crop.left = crop.left + (tmpDst.left - dst.left);
662 crop.top = crop.top + (tmpDst.top - dst.top);
663 crop.right = crop.left + (tmpDst.right - tmpDst.left);
664 crop.bottom = crop.top + (tmpDst.bottom - tmpDst.top);
665 dst = tmpDst;
666 }
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800667}
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800668
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800669/* 1) Identify layers that are not visible or lying outside BOTH the updating
670 * ROI's and drop them from composition. If a layer is spanning across both
671 * the halves of the screen but needed by only ROI, the non-contributing
672 * half will not be programmed for MDP.
673 * 2) If we have a scaling layer which needs cropping against generated
674 * ROI, reset ROI to full resolution. */
675bool MDPCompSplit::validateAndApplyROI(hwc_context_t *ctx,
676 hwc_display_contents_1_t* list) {
677
678 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
679
680 hwc_rect_t visibleRectL = ctx->listStats[mDpy].lRoi;
681 hwc_rect_t visibleRectR = ctx->listStats[mDpy].rRoi;
682
683 for(int i = numAppLayers - 1; i >= 0; i--){
684 if(!isValidRect(visibleRectL) && !isValidRect(visibleRectR))
685 {
686 mCurrentFrame.drop[i] = true;
687 mCurrentFrame.dropCount++;
688 continue;
689 }
690
691 const hwc_layer_1_t* layer = &list->hwLayers[i];
692 hwc_rect_t dstRect = layer->displayFrame;
693
694 hwc_rect_t l_res = getIntersection(visibleRectL, dstRect);
695 hwc_rect_t r_res = getIntersection(visibleRectR, dstRect);
696 hwc_rect_t res = getUnion(l_res, r_res);
697
698 if(!isValidRect(l_res) && !isValidRect(r_res)) {
699 mCurrentFrame.drop[i] = true;
700 mCurrentFrame.dropCount++;
701 } else {
702 /* Reset frame ROI when any layer which needs scaling also needs ROI
703 * cropping */
704 if(!isSameRect(res, dstRect) && needsScaling (layer)) {
705 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
706 mCurrentFrame.dropCount = 0;
707 return false;
708 }
709
radhakrishna4efbdd62014-11-03 13:19:27 +0530710 if (layer->blending == HWC_BLENDING_NONE &&
711 layer->planeAlpha == 0xFF) {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800712 visibleRectL = deductRect(visibleRectL, l_res);
713 visibleRectR = deductRect(visibleRectR, r_res);
714 }
715 }
716 }
717 return true;
718}
719/* Calculate ROI for the frame by accounting all the layer's dispalyFrame which
720 * are updating. If DirtyRegion is applicable, calculate it by accounting all
721 * the changing layer's dirtyRegion. */
722void MDPCompSplit::generateROI(hwc_context_t *ctx,
723 hwc_display_contents_1_t* list) {
724 if(!canPartialUpdate(ctx, list))
725 return;
726
727 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
728 int lSplit = getLeftSplit(ctx, mDpy);
729
730 int hw_h = (int)ctx->dpyAttr[mDpy].yres;
731 int hw_w = (int)ctx->dpyAttr[mDpy].xres;
732
733 struct hwc_rect l_frame = (struct hwc_rect){0, 0, lSplit, hw_h};
734 struct hwc_rect r_frame = (struct hwc_rect){lSplit, 0, hw_w, hw_h};
735
736 struct hwc_rect l_roi = (struct hwc_rect){0, 0, 0, 0};
737 struct hwc_rect r_roi = (struct hwc_rect){0, 0, 0, 0};
738
739 for(int index = 0; index < numAppLayers; index++ ) {
740 hwc_layer_1_t* layer = &list->hwLayers[index];
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800741 private_handle_t *hnd = (private_handle_t *)layer->handle;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800742 if ((mCachedFrame.hnd[index] != layer->handle) ||
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800743 isYuvBuffer(hnd)) {
Jeykumar Sankaran71e597c2014-05-07 16:23:14 -0700744 hwc_rect_t dst = layer->displayFrame;
745 hwc_rect_t updatingRect = dst;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800746
747#ifdef QCOM_BSP
748 if(!needsScaling(layer) && !layer->transform)
Jeykumar Sankaran71e597c2014-05-07 16:23:14 -0700749 {
750 hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
751 int x_off = dst.left - src.left;
752 int y_off = dst.top - src.top;
753 updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
754 }
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800755#endif
756
757 hwc_rect_t l_dst = getIntersection(l_frame, updatingRect);
758 if(isValidRect(l_dst))
759 l_roi = getUnion(l_roi, l_dst);
760
761 hwc_rect_t r_dst = getIntersection(r_frame, updatingRect);
762 if(isValidRect(r_dst))
763 r_roi = getUnion(r_roi, r_dst);
764 }
765 }
766
Jeykumar Sankarana40a9342014-04-25 09:37:10 -0700767 /* For panels that cannot accept commands in both the interfaces, we cannot
768 * send two ROI's (for each half). We merge them into single ROI and split
769 * them across lSplit for MDP mixer use. The ROI's will be merged again
770 * finally before udpating the panel in the driver. */
771 if(qdutils::MDPVersion::getInstance().needsROIMerge()) {
772 hwc_rect_t temp_roi = getUnion(l_roi, r_roi);
773 l_roi = getIntersection(temp_roi, l_frame);
774 r_roi = getIntersection(temp_roi, r_frame);
775 }
776
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800777 /* No layer is updating. Still SF wants a refresh. */
778 if(!isValidRect(l_roi) && !isValidRect(r_roi))
779 return;
780
781 l_roi = getSanitizeROI(l_roi, l_frame);
782 r_roi = getSanitizeROI(r_roi, r_frame);
783
784 ctx->listStats[mDpy].lRoi = l_roi;
785 ctx->listStats[mDpy].rRoi = r_roi;
786
787 if(!validateAndApplyROI(ctx, list))
788 resetROI(ctx, mDpy);
789
790 ALOGD_IF(isDebug(),"%s: generated L_ROI: [%d, %d, %d, %d]"
791 "R_ROI: [%d, %d, %d, %d]", __FUNCTION__,
792 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
793 ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom,
794 ctx->listStats[mDpy].rRoi.left, ctx->listStats[mDpy].rRoi.top,
795 ctx->listStats[mDpy].rRoi.right, ctx->listStats[mDpy].rRoi.bottom);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700796}
797
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800798/* Checks for conditions where all the layers marked for MDP comp cannot be
799 * bypassed. On such conditions we try to bypass atleast YUV layers */
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800800bool MDPComp::tryFullFrame(hwc_context_t *ctx,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800801 hwc_display_contents_1_t* list){
802
Saurabh Shahaa236822013-04-24 18:07:26 -0700803 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800804
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -0700805 // Fall back to video only composition, if AIV video mode is enabled
806 if(ctx->listStats[mDpy].mAIVVideoMode) {
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -0700807 ALOGD_IF(isDebug(), "%s: AIV Video Mode enabled dpy %d",
808 __FUNCTION__, mDpy);
809 return false;
810 }
811
Praveena Pachipulusu47346c22014-12-04 11:06:41 +0530812 /* No Idle fall back if secure display or secure RGB layers are present
813 * or if there is only a single layer being composed */
814 if(sIdleFallBack && !ctx->listStats[mDpy].secureUI &&
815 !ctx->listStats[mDpy].secureRGBCount &&
816 (ctx->listStats[mDpy].numAppLayers > 1)) {
Saurabh Shah2d998a92013-05-14 17:55:58 -0700817 ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
818 return false;
819 }
820
Ramkumar Radhakrishnanf26fe9e2014-09-09 13:47:54 -0700821 // if secondary is configuring or Padding round, fall back to video only
822 // composition and release all assigned non VIG pipes from primary.
823 if(isSecondaryConfiguring(ctx)) {
824 ALOGD_IF( isDebug(),"%s: External Display connection is pending",
825 __FUNCTION__);
826 return false;
827 } else if(ctx->isPaddingRound) {
828 ALOGD_IF(isDebug(), "%s: padding round invoked for dpy %d",
829 __FUNCTION__,mDpy);
830 return false;
831 }
832
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -0500833 // No MDP composition for 3D
834 if(needs3DComposition(ctx, mDpy))
835 return false;
836
Tatenda Chipeperekwacb2a2432014-08-06 17:45:58 -0700837 // check for action safe flag and MDP scaling mode which requires scaling.
Ramkumar Radhakrishnan4af1ef02013-12-12 11:53:08 -0800838 if(ctx->dpyAttr[mDpy].mActionSafePresent
Tatenda Chipeperekwacb2a2432014-08-06 17:45:58 -0700839 || ctx->dpyAttr[mDpy].mMDPScalingMode) {
Ramkumar Radhakrishnan4af1ef02013-12-12 11:53:08 -0800840 ALOGD_IF(isDebug(), "%s: Scaling needed for this frame",__FUNCTION__);
841 return false;
842 }
843
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800844 for(int i = 0; i < numAppLayers; ++i) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800845 hwc_layer_1_t* layer = &list->hwLayers[i];
846 private_handle_t *hnd = (private_handle_t *)layer->handle;
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -0800847
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800848 if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700849 if(!canUseRotator(ctx, mDpy)) {
850 ALOGD_IF(isDebug(), "%s: Can't use rotator for dpy %d",
851 __FUNCTION__, mDpy);
Amara Venkata Mastan Manoj Kumar9d373c02013-08-20 14:30:09 -0700852 return false;
853 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800854 }
Prabhanjan Kandula9fb032a2013-06-18 17:37:22 +0530855
856 //For 8x26 with panel width>1k, if RGB layer needs HFLIP fail mdp comp
857 // may not need it if Gfx pre-rotation can handle all flips & rotations
Saurabh Shahcad57772014-12-01 14:19:51 -0800858 MDPVersion& mdpHw = MDPVersion::getInstance();
Sushil Chauhanfda00fc2014-03-20 11:08:41 -0700859 int transform = (layer->flags & HWC_COLOR_FILL) ? 0 : layer->transform;
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530860 if( mdpHw.is8x26() && (ctx->dpyAttr[mDpy].xres > 1024) &&
861 (transform & HWC_TRANSFORM_FLIP_H) && (!isYuvBuffer(hnd)))
862 return false;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800863 }
Saurabh Shahaa236822013-04-24 18:07:26 -0700864
Saurabh Shaha9da08f2013-07-03 13:27:53 -0700865 if(ctx->mAD->isDoable()) {
866 return false;
867 }
868
Saurabh Shahaa236822013-04-24 18:07:26 -0700869 //If all above hard conditions are met we can do full or partial MDP comp.
870 bool ret = false;
871 if(fullMDPComp(ctx, list)) {
872 ret = true;
Sushil Chauhandefd3522014-05-13 18:17:12 -0700873 } else if(fullMDPCompWithPTOR(ctx, list)) {
874 ret = true;
Jeykumar Sankaran24c199d2013-05-24 09:40:36 -0700875 } else if(partialMDPComp(ctx, list)) {
Saurabh Shahaa236822013-04-24 18:07:26 -0700876 ret = true;
877 }
Prabhanjan Kandula21918db2013-11-26 15:51:58 +0530878
Saurabh Shahaa236822013-04-24 18:07:26 -0700879 return ret;
880}
881
882bool MDPComp::fullMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -0700883
884 if(sSimulationFlags & MDPCOMP_AVOID_FULL_MDP)
885 return false;
886
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700887 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
888 for(int i = 0; i < numAppLayers; i++) {
889 hwc_layer_1_t* layer = &list->hwLayers[i];
Jeykumar Sankaran880da832014-04-18 10:22:35 -0700890 if(not mCurrentFrame.drop[i] and
891 not isSupportedForMDPComp(ctx, layer)) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700892 ALOGD_IF(isDebug(), "%s: Unsupported layer in list",__FUNCTION__);
893 return false;
894 }
895 }
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800896
Saurabh Shahaa236822013-04-24 18:07:26 -0700897 mCurrentFrame.fbCount = 0;
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700898 memcpy(&mCurrentFrame.isFBComposed, &mCurrentFrame.drop,
899 sizeof(mCurrentFrame.isFBComposed));
900 mCurrentFrame.mdpCount = mCurrentFrame.layerCount - mCurrentFrame.fbCount -
901 mCurrentFrame.dropCount;
Saurabh Shahaa236822013-04-24 18:07:26 -0700902
Raj Kamal389d6e32014-08-04 14:43:24 +0530903 if(sEnableYUVsplit){
Saurabh Shah3d4b8042013-12-10 15:19:17 -0800904 adjustForSourceSplit(ctx, list);
radhakrishnac9a67412013-09-25 17:40:42 +0530905 }
906
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800907 if(!postHeuristicsHandling(ctx, list)) {
908 ALOGD_IF(isDebug(), "post heuristic handling failed");
909 reset(ctx);
Saurabh Shah8c5c8522013-08-29 17:32:49 -0700910 return false;
911 }
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -0700912 ALOGD_IF(sSimulationFlags,"%s: FULL_MDP_COMP SUCCEEDED",
913 __FUNCTION__);
Saurabh Shahaa236822013-04-24 18:07:26 -0700914 return true;
915}
916
Sushil Chauhandefd3522014-05-13 18:17:12 -0700917/* Full MDP Composition with Peripheral Tiny Overlap Removal.
918 * MDP bandwidth limitations can be avoided, if the overlap region
919 * covered by the smallest layer at a higher z-order, gets composed
920 * by Copybit on a render buffer, which can be queued to MDP.
921 */
922bool MDPComp::fullMDPCompWithPTOR(hwc_context_t *ctx,
923 hwc_display_contents_1_t* list) {
924
925 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
926 const int stagesForMDP = min(sMaxPipesPerMixer,
927 ctx->mOverlay->availablePipes(mDpy, Overlay::MIXER_DEFAULT));
928
929 // Hard checks where we cannot use this mode
Sushil Chauhanbfc2de02014-07-24 11:52:58 -0700930 if (mDpy || !ctx->mCopyBit[mDpy]) {
Sushil Chauhandefd3522014-05-13 18:17:12 -0700931 ALOGD_IF(isDebug(), "%s: Feature not supported!", __FUNCTION__);
932 return false;
933 }
934
935 // Frame level checks
936 if ((numAppLayers > stagesForMDP) || isSkipPresent(ctx, mDpy) ||
937 isYuvPresent(ctx, mDpy) || mCurrentFrame.dropCount ||
938 isSecurePresent(ctx, mDpy)) {
939 ALOGD_IF(isDebug(), "%s: Frame not supported!", __FUNCTION__);
940 return false;
941 }
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -0700942 // MDP comp checks
943 for(int i = 0; i < numAppLayers; i++) {
Sushil Chauhandefd3522014-05-13 18:17:12 -0700944 hwc_layer_1_t* layer = &list->hwLayers[i];
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -0700945 if(not isSupportedForMDPComp(ctx, layer)) {
946 ALOGD_IF(isDebug(), "%s: Unsupported layer in list",__FUNCTION__);
947 return false;
Sushil Chauhandefd3522014-05-13 18:17:12 -0700948 }
949 }
950
Sushil Chauhandefd3522014-05-13 18:17:12 -0700951 /* We cannot use this composition mode, if:
952 1. A below layer needs scaling.
953 2. Overlap is not peripheral to display.
954 3. Overlap or a below layer has 90 degree transform.
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -0700955 4. Overlap area > (1/3 * FrameBuffer) area, based on Perf inputs.
Sushil Chauhandefd3522014-05-13 18:17:12 -0700956 */
957
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -0700958 int minLayerIndex[MAX_PTOR_LAYERS] = { -1, -1};
959 hwc_rect_t overlapRect[MAX_PTOR_LAYERS];
960 memset(overlapRect, 0, sizeof(overlapRect));
961 int layerPixelCount, minPixelCount = 0;
962 int numPTORLayersFound = 0;
963 for (int i = numAppLayers-1; (i >= 0 &&
964 numPTORLayersFound < MAX_PTOR_LAYERS); i--) {
Sushil Chauhandefd3522014-05-13 18:17:12 -0700965 hwc_layer_1_t* layer = &list->hwLayers[i];
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -0700966 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
Sushil Chauhandefd3522014-05-13 18:17:12 -0700967 hwc_rect_t dispFrame = layer->displayFrame;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -0700968 layerPixelCount = (crop.right - crop.left) * (crop.bottom - crop.top);
969 // PTOR layer should be peripheral and cannot have transform
970 if (!isPeripheral(dispFrame, ctx->mViewFrame[mDpy]) ||
971 has90Transform(layer)) {
972 continue;
973 }
974 if((3 * (layerPixelCount + minPixelCount)) >
975 ((int)ctx->dpyAttr[mDpy].xres * (int)ctx->dpyAttr[mDpy].yres)) {
976 // Overlap area > (1/3 * FrameBuffer) area, based on Perf inputs.
977 continue;
978 }
Sushil Chauhan875a92e2014-07-25 12:20:23 -0700979 bool found = false;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -0700980 for (int j = i-1; j >= 0; j--) {
981 // Check if the layers below this layer qualifies for PTOR comp
982 hwc_layer_1_t* layer = &list->hwLayers[j];
983 hwc_rect_t disFrame = layer->displayFrame;
Sushil Chauhan875a92e2014-07-25 12:20:23 -0700984 // Layer below PTOR is intersecting and has 90 degree transform or
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -0700985 // needs scaling cannot be supported.
Sushil Chauhan875a92e2014-07-25 12:20:23 -0700986 if (isValidRect(getIntersection(dispFrame, disFrame))) {
987 if (has90Transform(layer) || needsScaling(layer)) {
988 found = false;
989 break;
990 }
991 found = true;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -0700992 }
993 }
994 // Store the minLayer Index
995 if(found) {
996 minLayerIndex[numPTORLayersFound] = i;
997 overlapRect[numPTORLayersFound] = list->hwLayers[i].displayFrame;
998 minPixelCount += layerPixelCount;
999 numPTORLayersFound++;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001000 }
1001 }
1002
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001003 // No overlap layers
1004 if (!numPTORLayersFound)
1005 return false;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001006
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001007 // Store the displayFrame and the sourceCrops of the layers
1008 hwc_rect_t displayFrame[numAppLayers];
1009 hwc_rect_t sourceCrop[numAppLayers];
1010 for(int i = 0; i < numAppLayers; i++) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001011 hwc_layer_1_t* layer = &list->hwLayers[i];
1012 displayFrame[i] = layer->displayFrame;
1013 sourceCrop[i] = integerizeSourceCrop(layer->sourceCropf);
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001014 }
Sushil Chauhandefd3522014-05-13 18:17:12 -07001015
Prabhanjan Kandula9889a202014-09-04 21:50:35 +05301016 /**
1017 * It's possible that 2 PTOR layers might have overlapping.
1018 * In such case, remove the intersection(again if peripheral)
1019 * from the lower PTOR layer to avoid overlapping.
1020 * If intersection is not on peripheral then compromise
1021 * by reducing number of PTOR layers.
1022 **/
1023 hwc_rect_t commonRect = getIntersection(overlapRect[0], overlapRect[1]);
1024 if(isValidRect(commonRect)) {
1025 overlapRect[1] = deductRect(overlapRect[1], commonRect);
1026 list->hwLayers[minLayerIndex[1]].displayFrame = overlapRect[1];
1027 }
1028
1029 ctx->mPtorInfo.count = numPTORLayersFound;
1030 for(int i = 0; i < MAX_PTOR_LAYERS; i++) {
1031 ctx->mPtorInfo.layerIndex[i] = minLayerIndex[i];
1032 }
1033
1034 if (!ctx->mCopyBit[mDpy]->prepareOverlap(ctx, list)) {
1035 // reset PTOR
1036 ctx->mPtorInfo.count = 0;
1037 if(isValidRect(commonRect)) {
1038 // If PTORs are intersecting restore displayframe of PTOR[1]
1039 // before returning, as we have modified it above.
1040 list->hwLayers[minLayerIndex[1]].displayFrame =
1041 displayFrame[minLayerIndex[1]];
1042 }
1043 return false;
1044 }
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001045 private_handle_t *renderBuf = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
1046 Whf layerWhf[numPTORLayersFound]; // To store w,h,f of PTOR layers
1047
Xu Yangcda012c2014-07-30 21:57:21 +08001048 // Store the blending mode, planeAlpha, and transform of PTOR layers
1049 int32_t blending[numPTORLayersFound];
1050 uint8_t planeAlpha[numPTORLayersFound];
1051 uint32_t transform[numPTORLayersFound];
1052
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001053 for(int j = 0; j < numPTORLayersFound; j++) {
1054 int index = ctx->mPtorInfo.layerIndex[j];
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001055
1056 // Update src crop of PTOR layer
1057 hwc_layer_1_t* layer = &list->hwLayers[index];
1058 layer->sourceCropf.left = (float)ctx->mPtorInfo.displayFrame[j].left;
1059 layer->sourceCropf.top = (float)ctx->mPtorInfo.displayFrame[j].top;
1060 layer->sourceCropf.right = (float)ctx->mPtorInfo.displayFrame[j].right;
1061 layer->sourceCropf.bottom =(float)ctx->mPtorInfo.displayFrame[j].bottom;
1062
1063 // Store & update w, h, format of PTOR layer
1064 private_handle_t *hnd = (private_handle_t *)layer->handle;
1065 Whf whf(hnd->width, hnd->height, hnd->format, hnd->size);
1066 layerWhf[j] = whf;
1067 hnd->width = renderBuf->width;
1068 hnd->height = renderBuf->height;
1069 hnd->format = renderBuf->format;
1070
Xu Yangcda012c2014-07-30 21:57:21 +08001071 // Store & update blending mode, planeAlpha and transform of PTOR layer
1072 blending[j] = layer->blending;
1073 planeAlpha[j] = layer->planeAlpha;
1074 transform[j] = layer->transform;
1075 layer->blending = HWC_BLENDING_NONE;
1076 layer->planeAlpha = 0xFF;
1077 layer->transform = 0;
1078
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001079 // Remove overlap from crop & displayFrame of below layers
1080 for (int i = 0; i < index && index !=-1; i++) {
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001081 layer = &list->hwLayers[i];
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001082 if(!isValidRect(getIntersection(layer->displayFrame,
1083 overlapRect[j]))) {
1084 continue;
1085 }
1086 // Update layer attributes
1087 hwc_rect_t srcCrop = integerizeSourceCrop(layer->sourceCropf);
1088 hwc_rect_t destRect = deductRect(layer->displayFrame,
Dileep Kumar Reddi72058b82014-11-11 16:03:03 +05301089 getIntersection(layer->displayFrame, overlapRect[j]));
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001090 qhwc::calculate_crop_rects(srcCrop, layer->displayFrame, destRect,
1091 layer->transform);
1092 layer->sourceCropf.left = (float)srcCrop.left;
1093 layer->sourceCropf.top = (float)srcCrop.top;
1094 layer->sourceCropf.right = (float)srcCrop.right;
1095 layer->sourceCropf.bottom = (float)srcCrop.bottom;
1096 }
Sushil Chauhandefd3522014-05-13 18:17:12 -07001097 }
1098
1099 mCurrentFrame.mdpCount = numAppLayers;
1100 mCurrentFrame.fbCount = 0;
1101 mCurrentFrame.fbZ = -1;
1102
Dileep Kumar Reddi72058b82014-11-11 16:03:03 +05301103 for (int j = 0; j < numAppLayers; j++) {
1104 if(isValidRect(list->hwLayers[j].displayFrame)) {
1105 mCurrentFrame.isFBComposed[j] = false;
1106 } else {
1107 mCurrentFrame.mdpCount--;
1108 mCurrentFrame.drop[j] = true;
1109 }
1110 }
Sushil Chauhandefd3522014-05-13 18:17:12 -07001111
1112 bool result = postHeuristicsHandling(ctx, list);
1113
1114 // Restore layer attributes
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001115 for(int i = 0; i < numAppLayers; i++) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001116 hwc_layer_1_t* layer = &list->hwLayers[i];
1117 layer->displayFrame = displayFrame[i];
1118 layer->sourceCropf.left = (float)sourceCrop[i].left;
1119 layer->sourceCropf.top = (float)sourceCrop[i].top;
1120 layer->sourceCropf.right = (float)sourceCrop[i].right;
1121 layer->sourceCropf.bottom = (float)sourceCrop[i].bottom;
1122 }
1123
Xu Yangcda012c2014-07-30 21:57:21 +08001124 // Restore w,h,f, blending attributes, and transform of PTOR layers
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001125 for (int i = 0; i < numPTORLayersFound; i++) {
1126 int idx = ctx->mPtorInfo.layerIndex[i];
Xu Yangcda012c2014-07-30 21:57:21 +08001127 hwc_layer_1_t* layer = &list->hwLayers[idx];
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001128 private_handle_t *hnd = (private_handle_t *)list->hwLayers[idx].handle;
1129 hnd->width = layerWhf[i].w;
1130 hnd->height = layerWhf[i].h;
1131 hnd->format = layerWhf[i].format;
Xu Yangcda012c2014-07-30 21:57:21 +08001132 layer->blending = blending[i];
1133 layer->planeAlpha = planeAlpha[i];
1134 layer->transform = transform[i];
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001135 }
1136
Sushil Chauhandefd3522014-05-13 18:17:12 -07001137 if (!result) {
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001138 // reset PTOR
1139 ctx->mPtorInfo.count = 0;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001140 reset(ctx);
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001141 } else {
1142 ALOGD_IF(isDebug(), "%s: PTOR Indexes: %d and %d", __FUNCTION__,
1143 ctx->mPtorInfo.layerIndex[0], ctx->mPtorInfo.layerIndex[1]);
Sushil Chauhandefd3522014-05-13 18:17:12 -07001144 }
1145
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001146 ALOGD_IF(isDebug(), "%s: Postheuristics %s!", __FUNCTION__,
1147 (result ? "successful" : "failed"));
Sushil Chauhandefd3522014-05-13 18:17:12 -07001148 return result;
1149}
1150
Saurabh Shahaa236822013-04-24 18:07:26 -07001151bool MDPComp::partialMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list)
1152{
Jeykumar Sankaran24c199d2013-05-24 09:40:36 -07001153 if(!sEnableMixedMode) {
1154 //Mixed mode is disabled. No need to even try caching.
1155 return false;
1156 }
1157
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001158 bool ret = false;
Raj Kamal1179d9c2014-10-28 15:31:35 +05301159 if(isSkipPresent(ctx, mDpy) or list->flags & HWC_GEOMETRY_CHANGED) {
1160 //Try load based first
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001161 ret = loadBasedComp(ctx, list) or
Saurabh Shahf2de00f2013-12-11 17:52:53 -08001162 cacheBasedComp(ctx, list);
1163 } else {
1164 ret = cacheBasedComp(ctx, list) or
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001165 loadBasedComp(ctx, list);
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001166 }
1167
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001168 return ret;
1169}
1170
1171bool MDPComp::cacheBasedComp(hwc_context_t *ctx,
1172 hwc_display_contents_1_t* list) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001173 if(sSimulationFlags & MDPCOMP_AVOID_CACHE_MDP)
1174 return false;
1175
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001176 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shahaa236822013-04-24 18:07:26 -07001177 mCurrentFrame.reset(numAppLayers);
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001178 updateLayerCache(ctx, list, mCurrentFrame);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001179
1180 //If an MDP marked layer is unsupported cannot do partial MDP Comp
1181 for(int i = 0; i < numAppLayers; i++) {
1182 if(!mCurrentFrame.isFBComposed[i]) {
1183 hwc_layer_1_t* layer = &list->hwLayers[i];
1184 if(not isSupportedForMDPComp(ctx, layer)) {
1185 ALOGD_IF(isDebug(), "%s: Unsupported layer in list",
1186 __FUNCTION__);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001187 reset(ctx);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001188 return false;
1189 }
1190 }
1191 }
1192
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001193 updateYUV(ctx, list, false /*secure only*/, mCurrentFrame);
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001194 /* mark secure RGB layers for MDP comp */
1195 updateSecureRGB(ctx, list);
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301196 bool ret = markLayersForCaching(ctx, list); //sets up fbZ also
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001197 if(!ret) {
1198 ALOGD_IF(isDebug(),"%s: batching failed, dpy %d",__FUNCTION__, mDpy);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001199 reset(ctx);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001200 return false;
1201 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001202
1203 int mdpCount = mCurrentFrame.mdpCount;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001204
Raj Kamal389d6e32014-08-04 14:43:24 +05301205 if(sEnableYUVsplit){
Saurabh Shah3d4b8042013-12-10 15:19:17 -08001206 adjustForSourceSplit(ctx, list);
radhakrishnac9a67412013-09-25 17:40:42 +05301207 }
1208
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001209 if(!postHeuristicsHandling(ctx, list)) {
1210 ALOGD_IF(isDebug(), "post heuristic handling failed");
1211 reset(ctx);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07001212 return false;
1213 }
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001214 ALOGD_IF(sSimulationFlags,"%s: CACHE_MDP_COMP SUCCEEDED",
1215 __FUNCTION__);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07001216
Saurabh Shahaa236822013-04-24 18:07:26 -07001217 return true;
1218}
1219
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001220bool MDPComp::loadBasedComp(hwc_context_t *ctx,
Saurabh Shahb772ae32013-11-18 15:40:02 -08001221 hwc_display_contents_1_t* list) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001222 if(sSimulationFlags & MDPCOMP_AVOID_LOAD_MDP)
1223 return false;
1224
Arun Kumar K.R2aa44c62014-01-21 23:08:28 -08001225 if(not isLoadBasedCompDoable(ctx)) {
Saurabh Shahf2de00f2013-12-11 17:52:53 -08001226 return false;
1227 }
1228
Saurabh Shahb772ae32013-11-18 15:40:02 -08001229 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001230 const int numNonDroppedLayers = numAppLayers - mCurrentFrame.dropCount;
1231 const int stagesForMDP = min(sMaxPipesPerMixer,
1232 ctx->mOverlay->availablePipes(mDpy, Overlay::MIXER_DEFAULT));
Saurabh Shahf2de00f2013-12-11 17:52:53 -08001233
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001234 int mdpBatchSize = stagesForMDP - 1; //1 stage for FB
1235 int fbBatchSize = numNonDroppedLayers - mdpBatchSize;
1236 int lastMDPSupportedIndex = numAppLayers;
1237 int dropCount = 0;
Saurabh Shahb772ae32013-11-18 15:40:02 -08001238
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001239 //Find the minimum MDP batch size
1240 for(int i = 0; i < numAppLayers;i++) {
1241 if(mCurrentFrame.drop[i]) {
1242 dropCount++;
Jeykumar Sankaran846e2792014-01-23 21:59:58 -08001243 continue;
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001244 }
1245 hwc_layer_1_t* layer = &list->hwLayers[i];
1246 if(not isSupportedForMDPComp(ctx, layer)) {
1247 lastMDPSupportedIndex = i;
1248 mdpBatchSize = min(i - dropCount, stagesForMDP - 1);
1249 fbBatchSize = numNonDroppedLayers - mdpBatchSize;
Jeykumar Sankaran846e2792014-01-23 21:59:58 -08001250 break;
Saurabh Shahb772ae32013-11-18 15:40:02 -08001251 }
Saurabh Shahb772ae32013-11-18 15:40:02 -08001252 }
1253
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001254 ALOGD_IF(isDebug(), "%s:Before optimizing fbBatch, mdpbatch %d, fbbatch %d "
1255 "dropped %d", __FUNCTION__, mdpBatchSize, fbBatchSize,
1256 mCurrentFrame.dropCount);
1257
1258 //Start at a point where the fb batch should at least have 2 layers, for
1259 //this mode to be justified.
1260 while(fbBatchSize < 2) {
1261 ++fbBatchSize;
1262 --mdpBatchSize;
Jeykumar Sankaran846e2792014-01-23 21:59:58 -08001263 }
Saurabh Shahb772ae32013-11-18 15:40:02 -08001264
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001265 //If there are no layers for MDP, this mode doesnt make sense.
1266 if(mdpBatchSize < 1) {
1267 ALOGD_IF(isDebug(), "%s: No MDP layers after optimizing for fbBatch",
1268 __FUNCTION__);
Saurabh Shahb772ae32013-11-18 15:40:02 -08001269 return false;
1270 }
1271
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001272 mCurrentFrame.reset(numAppLayers);
1273
1274 //Try with successively smaller mdp batch sizes until we succeed or reach 1
1275 while(mdpBatchSize > 0) {
1276 //Mark layers for MDP comp
1277 int mdpBatchLeft = mdpBatchSize;
1278 for(int i = 0; i < lastMDPSupportedIndex and mdpBatchLeft; i++) {
1279 if(mCurrentFrame.drop[i]) {
1280 continue;
1281 }
1282 mCurrentFrame.isFBComposed[i] = false;
1283 --mdpBatchLeft;
1284 }
1285
1286 mCurrentFrame.fbZ = mdpBatchSize;
1287 mCurrentFrame.fbCount = fbBatchSize;
1288 mCurrentFrame.mdpCount = mdpBatchSize;
1289
1290 ALOGD_IF(isDebug(), "%s:Trying with: mdpbatch %d fbbatch %d dropped %d",
1291 __FUNCTION__, mdpBatchSize, fbBatchSize,
1292 mCurrentFrame.dropCount);
1293
1294 if(postHeuristicsHandling(ctx, list)) {
1295 ALOGD_IF(isDebug(), "%s: Postheuristics handling succeeded",
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001296 __FUNCTION__);
1297 ALOGD_IF(sSimulationFlags,"%s: LOAD_MDP_COMP SUCCEEDED",
1298 __FUNCTION__);
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001299 return true;
1300 }
1301
1302 reset(ctx);
1303 --mdpBatchSize;
1304 ++fbBatchSize;
1305 }
1306
1307 return false;
Saurabh Shahb772ae32013-11-18 15:40:02 -08001308}
1309
Arun Kumar K.R2aa44c62014-01-21 23:08:28 -08001310bool MDPComp::isLoadBasedCompDoable(hwc_context_t *ctx) {
Prabhanjan Kandula3dbbd882013-12-11 14:43:46 +05301311 if(mDpy or isSecurePresent(ctx, mDpy) or
1312 isYuvPresent(ctx, mDpy)) {
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001313 return false;
1314 }
1315 return true;
1316}
1317
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001318bool MDPComp::canPartialUpdate(hwc_context_t *ctx,
1319 hwc_display_contents_1_t* list){
1320 if(!qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() ||
1321 isSkipPresent(ctx, mDpy) || (list->flags & HWC_GEOMETRY_CHANGED) ||
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07001322 !sIsPartialUpdateActive || mDpy ) {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001323 return false;
1324 }
Jeykumar Sankaran4dd10ab2014-07-02 12:23:09 -07001325 if(ctx->listStats[mDpy].secureUI)
1326 return false;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001327 return true;
1328}
1329
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001330bool MDPComp::tryVideoOnly(hwc_context_t *ctx,
1331 hwc_display_contents_1_t* list) {
1332 const bool secureOnly = true;
1333 return videoOnlyComp(ctx, list, not secureOnly) or
1334 videoOnlyComp(ctx, list, secureOnly);
1335}
1336
1337bool MDPComp::videoOnlyComp(hwc_context_t *ctx,
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001338 hwc_display_contents_1_t* list, bool secureOnly) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001339 if(sSimulationFlags & MDPCOMP_AVOID_VIDEO_ONLY)
1340 return false;
Praveena Pachipulusu47346c22014-12-04 11:06:41 +05301341
Saurabh Shahaa236822013-04-24 18:07:26 -07001342 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Praveena Pachipulusu47346c22014-12-04 11:06:41 +05301343 if(!isSecurePresent(ctx, mDpy)) {
1344 /* Bail out if we are processing only secured video layers
1345 * and we dont have any */
1346 if(secureOnly) {
1347 ALOGD_IF(isDebug(),"%s: No Secure Video Layers", __FUNCTION__);
1348 return false;
1349 }
1350 /* No Idle fall back for secure video layers and if there is only
1351 * single layer being composed. */
1352 if(sIdleFallBack && (ctx->listStats[mDpy].numAppLayers > 1)) {
1353 ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
1354 return false;
1355 }
1356 }
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001357
Saurabh Shahaa236822013-04-24 18:07:26 -07001358 mCurrentFrame.reset(numAppLayers);
Jeykumar Sankaraneb3a5e22014-04-08 16:07:55 -07001359 mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001360 updateYUV(ctx, list, secureOnly, mCurrentFrame);
Saurabh Shah4fdde762013-04-30 18:47:33 -07001361 int mdpCount = mCurrentFrame.mdpCount;
Saurabh Shahaa236822013-04-24 18:07:26 -07001362
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001363 if(!isYuvPresent(ctx, mDpy) or (mdpCount == 0)) {
1364 reset(ctx);
Saurabh Shahaa236822013-04-24 18:07:26 -07001365 return false;
1366 }
1367
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001368 if(mCurrentFrame.fbCount)
1369 mCurrentFrame.fbZ = mCurrentFrame.mdpCount;
Saurabh Shah4fdde762013-04-30 18:47:33 -07001370
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05001371 if(sEnableYUVsplit || needs3DComposition(ctx, mDpy)){
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001372 adjustForSourceSplit(ctx, list);
1373 }
1374
1375 if(!postHeuristicsHandling(ctx, list)) {
1376 ALOGD_IF(isDebug(), "post heuristic handling failed");
Justin Philip37ab9a82015-01-06 11:55:12 +05301377 if(errno == ENOBUFS) {
1378 ALOGD_IF(isDebug(), "SMP Allocation failed");
1379 //On SMP allocation failure in video only comp add padding round
1380 ctx->isPaddingRound = true;
1381 }
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001382 reset(ctx);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07001383 return false;
1384 }
1385
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001386 ALOGD_IF(sSimulationFlags,"%s: VIDEO_ONLY_COMP SUCCEEDED",
1387 __FUNCTION__);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001388 return true;
1389}
1390
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001391/* if tryFullFrame fails, try to push all video and secure RGB layers to MDP */
1392bool MDPComp::tryMDPOnlyLayers(hwc_context_t *ctx,
1393 hwc_display_contents_1_t* list) {
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001394 // Fall back to video only composition, if AIV video mode is enabled
1395 if(ctx->listStats[mDpy].mAIVVideoMode) {
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07001396 ALOGD_IF(isDebug(), "%s: AIV Video Mode enabled dpy %d",
1397 __FUNCTION__, mDpy);
1398 return false;
1399 }
1400
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05001401 // No MDP composition for 3D
1402 if(needs3DComposition(ctx,mDpy))
1403 return false;
1404
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001405 const bool secureOnly = true;
1406 return mdpOnlyLayersComp(ctx, list, not secureOnly) or
1407 mdpOnlyLayersComp(ctx, list, secureOnly);
1408
1409}
1410
1411bool MDPComp::mdpOnlyLayersComp(hwc_context_t *ctx,
1412 hwc_display_contents_1_t* list, bool secureOnly) {
1413
1414 if(sSimulationFlags & MDPCOMP_AVOID_MDP_ONLY_LAYERS)
1415 return false;
1416
Praveena Pachipulusu47346c22014-12-04 11:06:41 +05301417 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
1418 if(!isSecurePresent(ctx, mDpy) && !ctx->listStats[mDpy].secureUI) {
1419 /* Bail out if we are processing only secured video/ui layers
1420 * and we dont have any */
1421 if(secureOnly) {
1422 ALOGD_IF(isDebug(), "%s: No secure video/ui layers");
1423 return false;
1424 }
1425 /* No Idle fall back for secure video/ui layers and if there is only
1426 * single layer being composed. */
1427 if(sIdleFallBack && (ctx->listStats[mDpy].numAppLayers > 1)) {
1428 ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
1429 return false;
1430 }
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001431 }
1432
Tatenda Chipeperekwa95675a72014-12-15 17:06:43 -08001433 /* Bail out if we dont have any secure RGB layers */
1434 if (!ctx->listStats[mDpy].secureRGBCount) {
1435 reset(ctx);
1436 return false;
1437 }
1438
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001439 mCurrentFrame.reset(numAppLayers);
1440 mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
1441
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001442 updateYUV(ctx, list, secureOnly, mCurrentFrame);
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001443 /* mark secure RGB layers for MDP comp */
1444 updateSecureRGB(ctx, list);
1445
1446 if(mCurrentFrame.mdpCount == 0) {
1447 reset(ctx);
1448 return false;
1449 }
1450
1451 /* find the maximum batch of layers to be marked for framebuffer */
1452 bool ret = markLayersForCaching(ctx, list); //sets up fbZ also
1453 if(!ret) {
1454 ALOGD_IF(isDebug(),"%s: batching failed, dpy %d",__FUNCTION__, mDpy);
1455 reset(ctx);
1456 return false;
1457 }
1458
1459 if(sEnableYUVsplit){
1460 adjustForSourceSplit(ctx, list);
1461 }
1462
1463 if(!postHeuristicsHandling(ctx, list)) {
1464 ALOGD_IF(isDebug(), "post heuristic handling failed");
1465 reset(ctx);
1466 return false;
1467 }
1468
1469 ALOGD_IF(sSimulationFlags,"%s: MDP_ONLY_LAYERS_COMP SUCCEEDED",
1470 __FUNCTION__);
1471 return true;
1472}
1473
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001474/* Checks for conditions where YUV layers cannot be bypassed */
1475bool MDPComp::isYUVDoable(hwc_context_t* ctx, hwc_layer_1_t* layer) {
Ramkumar Radhakrishnana70981a2013-08-28 11:33:53 -07001476 if(isSkipLayer(layer)) {
Saurabh Shahe2474082013-05-15 16:32:13 -07001477 ALOGD_IF(isDebug(), "%s: Video marked SKIP dpy %d", __FUNCTION__, mDpy);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001478 return false;
1479 }
1480
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08001481 if(has90Transform(layer) && !canUseRotator(ctx, mDpy)) {
Amara Venkata Mastan Manoj Kumar9d373c02013-08-20 14:30:09 -07001482 ALOGD_IF(isDebug(), "%s: no free DMA pipe",__FUNCTION__);
1483 return false;
1484 }
1485
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001486 if(isSecuring(ctx, layer)) {
1487 ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
1488 return false;
1489 }
1490
Saurabh Shah4fdde762013-04-30 18:47:33 -07001491 if(!isValidDimension(ctx, layer)) {
1492 ALOGD_IF(isDebug(), "%s: Buffer is of invalid width",
1493 __FUNCTION__);
1494 return false;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001495 }
Saurabh Shah4fdde762013-04-30 18:47:33 -07001496
Naseer Ahmeddc61a972013-07-10 17:50:54 -04001497 if(layer->planeAlpha < 0xFF) {
1498 ALOGD_IF(isDebug(), "%s: Cannot handle YUV layer with plane alpha\
1499 in video only mode",
1500 __FUNCTION__);
1501 return false;
1502 }
1503
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001504 return true;
1505}
1506
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001507/* Checks for conditions where Secure RGB layers cannot be bypassed */
1508bool MDPComp::isSecureRGBDoable(hwc_context_t* ctx, hwc_layer_1_t* layer) {
1509 if(isSkipLayer(layer)) {
1510 ALOGD_IF(isDebug(), "%s: Secure RGB layer marked SKIP dpy %d",
1511 __FUNCTION__, mDpy);
1512 return false;
1513 }
1514
1515 if(isSecuring(ctx, layer)) {
1516 ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
1517 return false;
1518 }
1519
1520 if(not isSupportedForMDPComp(ctx, layer)) {
1521 ALOGD_IF(isDebug(), "%s: Unsupported secure RGB layer",
1522 __FUNCTION__);
1523 return false;
1524 }
1525 return true;
1526}
1527
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301528/* starts at fromIndex and check for each layer to find
1529 * if it it has overlapping with any Updating layer above it in zorder
1530 * till the end of the batch. returns true if it finds any intersection */
1531bool MDPComp::canPushBatchToTop(const hwc_display_contents_1_t* list,
1532 int fromIndex, int toIndex) {
1533 for(int i = fromIndex; i < toIndex; i++) {
1534 if(mCurrentFrame.isFBComposed[i] && !mCurrentFrame.drop[i]) {
1535 if(intersectingUpdatingLayers(list, i+1, toIndex, i)) {
1536 return false;
1537 }
1538 }
1539 }
1540 return true;
1541}
1542
1543/* Checks if given layer at targetLayerIndex has any
1544 * intersection with all the updating layers in beween
1545 * fromIndex and toIndex. Returns true if it finds intersectiion */
1546bool MDPComp::intersectingUpdatingLayers(const hwc_display_contents_1_t* list,
1547 int fromIndex, int toIndex, int targetLayerIndex) {
1548 for(int i = fromIndex; i <= toIndex; i++) {
1549 if(!mCurrentFrame.isFBComposed[i]) {
1550 if(areLayersIntersecting(&list->hwLayers[i],
1551 &list->hwLayers[targetLayerIndex])) {
1552 return true;
1553 }
1554 }
1555 }
1556 return false;
1557}
1558
1559int MDPComp::getBatch(hwc_display_contents_1_t* list,
1560 int& maxBatchStart, int& maxBatchEnd,
1561 int& maxBatchCount) {
1562 int i = 0;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301563 int fbZOrder =-1;
Jeykumar Sankaran9502f352014-01-20 12:25:32 -08001564 int droppedLayerCt = 0;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301565 while (i < mCurrentFrame.layerCount) {
1566 int batchCount = 0;
1567 int batchStart = i;
1568 int batchEnd = i;
Jeykumar Sankaran9502f352014-01-20 12:25:32 -08001569 /* Adjust batch Z order with the dropped layers so far */
1570 int fbZ = batchStart - droppedLayerCt;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301571 int firstZReverseIndex = -1;
Prabhanjan Kandula0ed2cc92013-12-06 12:39:04 +05301572 int updatingLayersAbove = 0;//Updating layer count in middle of batch
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301573 while(i < mCurrentFrame.layerCount) {
1574 if(!mCurrentFrame.isFBComposed[i]) {
1575 if(!batchCount) {
1576 i++;
1577 break;
1578 }
1579 updatingLayersAbove++;
1580 i++;
1581 continue;
1582 } else {
1583 if(mCurrentFrame.drop[i]) {
1584 i++;
Jeykumar Sankaran9502f352014-01-20 12:25:32 -08001585 droppedLayerCt++;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301586 continue;
1587 } else if(updatingLayersAbove <= 0) {
1588 batchCount++;
1589 batchEnd = i;
1590 i++;
1591 continue;
1592 } else { //Layer is FBComposed, not a drop & updatingLayer > 0
1593
1594 // We have a valid updating layer already. If layer-i not
1595 // have overlapping with all updating layers in between
1596 // batch-start and i, then we can add layer i to batch.
1597 if(!intersectingUpdatingLayers(list, batchStart, i-1, i)) {
1598 batchCount++;
1599 batchEnd = i;
1600 i++;
1601 continue;
1602 } else if(canPushBatchToTop(list, batchStart, i)) {
1603 //If All the non-updating layers with in this batch
1604 //does not have intersection with the updating layers
1605 //above in z-order, then we can safely move the batch to
1606 //higher z-order. Increment fbZ as it is moving up.
1607 if( firstZReverseIndex < 0) {
1608 firstZReverseIndex = i;
1609 }
1610 batchCount++;
1611 batchEnd = i;
1612 fbZ += updatingLayersAbove;
1613 i++;
1614 updatingLayersAbove = 0;
1615 continue;
1616 } else {
1617 //both failed.start the loop again from here.
1618 if(firstZReverseIndex >= 0) {
1619 i = firstZReverseIndex;
1620 }
1621 break;
1622 }
1623 }
1624 }
1625 }
1626 if(batchCount > maxBatchCount) {
1627 maxBatchCount = batchCount;
1628 maxBatchStart = batchStart;
1629 maxBatchEnd = batchEnd;
1630 fbZOrder = fbZ;
1631 }
1632 }
1633 return fbZOrder;
1634}
1635
1636bool MDPComp::markLayersForCaching(hwc_context_t* ctx,
1637 hwc_display_contents_1_t* list) {
1638 /* Idea is to keep as many non-updating(cached) layers in FB and
1639 * send rest of them through MDP. This is done in 2 steps.
1640 * 1. Find the maximum contiguous batch of non-updating layers.
1641 * 2. See if we can improve this batch size for caching by adding
1642 * opaque layers around the batch, if they don't have
1643 * any overlapping with the updating layers in between.
1644 * NEVER mark an updating layer for caching.
1645 * But cached ones can be marked for MDP */
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001646
1647 int maxBatchStart = -1;
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001648 int maxBatchEnd = -1;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001649 int maxBatchCount = 0;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301650 int fbZ = -1;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001651
Saurabh Shahd53bc5f2014-02-05 10:17:43 -08001652 /* Nothing is cached. No batching needed */
1653 if(mCurrentFrame.fbCount == 0) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001654 return true;
Saurabh Shahaa236822013-04-24 18:07:26 -07001655 }
Saurabh Shahd53bc5f2014-02-05 10:17:43 -08001656
1657 /* No MDP comp layers, try to use other comp modes */
1658 if(mCurrentFrame.mdpCount == 0) {
1659 return false;
Saurabh Shahaa236822013-04-24 18:07:26 -07001660 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001661
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301662 fbZ = getBatch(list, maxBatchStart, maxBatchEnd, maxBatchCount);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001663
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301664 /* reset rest of the layers lying inside ROI for MDP comp */
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001665 for(int i = 0; i < mCurrentFrame.layerCount; i++) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001666 hwc_layer_1_t* layer = &list->hwLayers[i];
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001667 if((i < maxBatchStart || i > maxBatchEnd) &&
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301668 mCurrentFrame.isFBComposed[i]){
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001669 if(!mCurrentFrame.drop[i]){
1670 //If an unsupported layer is being attempted to
1671 //be pulled out we should fail
1672 if(not isSupportedForMDPComp(ctx, layer)) {
1673 return false;
1674 }
1675 mCurrentFrame.isFBComposed[i] = false;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001676 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001677 }
1678 }
1679
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301680 // update the frame data
1681 mCurrentFrame.fbZ = fbZ;
1682 mCurrentFrame.fbCount = maxBatchCount;
Saurabh Shahaa236822013-04-24 18:07:26 -07001683 mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001684 mCurrentFrame.fbCount - mCurrentFrame.dropCount;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001685
1686 ALOGD_IF(isDebug(),"%s: cached count: %d",__FUNCTION__,
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301687 mCurrentFrame.fbCount);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001688
1689 return true;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001690}
Saurabh Shah85234ec2013-04-12 17:09:00 -07001691
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001692void MDPComp::updateLayerCache(hwc_context_t* ctx,
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001693 hwc_display_contents_1_t* list, FrameInfo& frame) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001694 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001695 int fbCount = 0;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001696
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001697 for(int i = 0; i < numAppLayers; i++) {
1698 if (mCachedFrame.hnd[i] == list->hwLayers[i].handle) {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001699 if(!frame.drop[i])
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001700 fbCount++;
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001701 frame.isFBComposed[i] = true;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001702 } else {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001703 frame.isFBComposed[i] = false;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001704 }
1705 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001706
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001707 frame.fbCount = fbCount;
1708 frame.mdpCount = frame.layerCount - frame.fbCount
1709 - frame.dropCount;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001710
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001711 ALOGD_IF(isDebug(),"%s: MDP count: %d FB count %d drop count: %d",
1712 __FUNCTION__, frame.mdpCount, frame.fbCount, frame.dropCount);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001713}
1714
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001715// drop other non-AIV layers from external display list.
1716void MDPComp::dropNonAIVLayers(hwc_context_t* ctx,
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07001717 hwc_display_contents_1_t* list) {
1718 for (size_t i = 0; i < (size_t)ctx->listStats[mDpy].numAppLayers; i++) {
1719 hwc_layer_1_t * layer = &list->hwLayers[i];
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001720 if(!(isAIVVideoLayer(layer) || isAIVCCLayer(layer))) {
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07001721 mCurrentFrame.dropCount++;
1722 mCurrentFrame.drop[i] = true;
1723 }
1724 }
1725 mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
1726 mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
1727 mCurrentFrame.fbCount - mCurrentFrame.dropCount;
1728 ALOGD_IF(isDebug(),"%s: fb count: %d mdp count %d drop count %d",
1729 __FUNCTION__, mCurrentFrame.fbCount, mCurrentFrame.mdpCount,
1730 mCurrentFrame.dropCount);
1731}
1732
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001733void MDPComp::updateYUV(hwc_context_t* ctx, hwc_display_contents_1_t* list,
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001734 bool secureOnly, FrameInfo& frame) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001735 int nYuvCount = ctx->listStats[mDpy].yuvCount;
1736 for(int index = 0;index < nYuvCount; index++){
1737 int nYuvIndex = ctx->listStats[mDpy].yuvIndices[index];
1738 hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
1739
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001740 if(mCurrentFrame.drop[nYuvIndex]) {
1741 continue;
1742 }
1743
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001744 if(!isYUVDoable(ctx, layer)) {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001745 if(!frame.isFBComposed[nYuvIndex]) {
1746 frame.isFBComposed[nYuvIndex] = true;
1747 frame.fbCount++;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001748 }
1749 } else {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001750 if(frame.isFBComposed[nYuvIndex]) {
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001751 private_handle_t *hnd = (private_handle_t *)layer->handle;
1752 if(!secureOnly || isSecureBuffer(hnd)) {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001753 frame.isFBComposed[nYuvIndex] = false;
1754 frame.fbCount--;
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001755 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001756 }
1757 }
1758 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001759
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001760 frame.mdpCount = frame.layerCount - frame.fbCount - frame.dropCount;
1761 ALOGD_IF(isDebug(),"%s: fb count: %d",__FUNCTION__, frame.fbCount);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001762}
1763
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001764void MDPComp::updateSecureRGB(hwc_context_t* ctx,
1765 hwc_display_contents_1_t* list) {
1766 int nSecureRGBCount = ctx->listStats[mDpy].secureRGBCount;
1767 for(int index = 0;index < nSecureRGBCount; index++){
1768 int nSecureRGBIndex = ctx->listStats[mDpy].secureRGBIndices[index];
1769 hwc_layer_1_t* layer = &list->hwLayers[nSecureRGBIndex];
1770
1771 if(!isSecureRGBDoable(ctx, layer)) {
1772 if(!mCurrentFrame.isFBComposed[nSecureRGBIndex]) {
1773 mCurrentFrame.isFBComposed[nSecureRGBIndex] = true;
1774 mCurrentFrame.fbCount++;
1775 }
1776 } else {
1777 if(mCurrentFrame.isFBComposed[nSecureRGBIndex]) {
1778 mCurrentFrame.isFBComposed[nSecureRGBIndex] = false;
1779 mCurrentFrame.fbCount--;
1780 }
1781 }
1782 }
1783
1784 mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
1785 mCurrentFrame.fbCount - mCurrentFrame.dropCount;
1786 ALOGD_IF(isDebug(),"%s: fb count: %d",__FUNCTION__,
1787 mCurrentFrame.fbCount);
1788}
1789
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001790hwc_rect_t MDPComp::getUpdatingFBRect(hwc_context_t *ctx,
1791 hwc_display_contents_1_t* list){
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001792 hwc_rect_t fbRect = (struct hwc_rect){0, 0, 0, 0};
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001793
1794 /* Update only the region of FB needed for composition */
1795 for(int i = 0; i < mCurrentFrame.layerCount; i++ ) {
1796 if(mCurrentFrame.isFBComposed[i] && !mCurrentFrame.drop[i]) {
1797 hwc_layer_1_t* layer = &list->hwLayers[i];
1798 hwc_rect_t dst = layer->displayFrame;
1799 fbRect = getUnion(fbRect, dst);
1800 }
1801 }
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08001802 trimAgainstROI(ctx, fbRect, fbRect);
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001803 return fbRect;
1804}
1805
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001806bool MDPComp::postHeuristicsHandling(hwc_context_t *ctx,
1807 hwc_display_contents_1_t* list) {
1808
1809 //Capability checks
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08001810 if(!resourceCheck(ctx, list)) {
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001811 ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
1812 return false;
1813 }
1814
1815 //Limitations checks
1816 if(!hwLimitationsCheck(ctx, list)) {
1817 ALOGD_IF(isDebug(), "%s: HW limitations",__FUNCTION__);
1818 return false;
1819 }
1820
Saurabh Shah3d4b8042013-12-10 15:19:17 -08001821 //Configure framebuffer first if applicable
1822 if(mCurrentFrame.fbZ >= 0) {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001823 hwc_rect_t fbRect = getUpdatingFBRect(ctx, list);
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001824 if(!ctx->mFBUpdate[mDpy]->prepare(ctx, list, fbRect, mCurrentFrame.fbZ))
1825 {
Saurabh Shah3d4b8042013-12-10 15:19:17 -08001826 ALOGD_IF(isDebug(), "%s configure framebuffer failed",
1827 __FUNCTION__);
1828 return false;
1829 }
1830 }
1831
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001832 mCurrentFrame.map();
1833
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001834 if(!allocLayerPipes(ctx, list)) {
1835 ALOGD_IF(isDebug(), "%s: Unable to allocate MDP pipes", __FUNCTION__);
Saurabh Shahaa236822013-04-24 18:07:26 -07001836 return false;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001837 }
1838
1839 for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
Saurabh Shahaa236822013-04-24 18:07:26 -07001840 index++) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001841 if(!mCurrentFrame.isFBComposed[index]) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001842 int mdpIndex = mCurrentFrame.layerToMDP[index];
1843 hwc_layer_1_t* layer = &list->hwLayers[index];
1844
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301845 //Leave fbZ for framebuffer. CACHE/GLES layers go here.
1846 if(mdpNextZOrder == mCurrentFrame.fbZ) {
1847 mdpNextZOrder++;
1848 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001849 MdpPipeInfo* cur_pipe = mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
1850 cur_pipe->zOrder = mdpNextZOrder++;
1851
radhakrishnac9a67412013-09-25 17:40:42 +05301852 private_handle_t *hnd = (private_handle_t *)layer->handle;
Raj Kamal389d6e32014-08-04 14:43:24 +05301853 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
radhakrishnac9a67412013-09-25 17:40:42 +05301854 if(configure4k2kYuv(ctx, layer,
1855 mCurrentFrame.mdpToLayer[mdpIndex])
1856 != 0 ){
1857 ALOGD_IF(isDebug(), "%s: Failed to configure split pipes \
1858 for layer %d",__FUNCTION__, index);
1859 return false;
1860 }
1861 else{
1862 mdpNextZOrder++;
1863 }
1864 continue;
1865 }
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05001866 if(needs3DComposition(ctx,mDpy) && get3DFormat(hnd) != HAL_NO_3D) {
1867 mdpNextZOrder++;
1868 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001869 if(configure(ctx, layer, mCurrentFrame.mdpToLayer[mdpIndex]) != 0 ){
1870 ALOGD_IF(isDebug(), "%s: Failed to configure overlay for \
radhakrishnac9a67412013-09-25 17:40:42 +05301871 layer %d",__FUNCTION__, index);
Saurabh Shahaa236822013-04-24 18:07:26 -07001872 return false;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001873 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001874 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001875 }
1876
Saurabh Shaha36be922013-12-16 18:18:39 -08001877 if(!ctx->mOverlay->validateAndSet(mDpy, ctx->dpyAttr[mDpy].fd)) {
1878 ALOGD_IF(isDebug(), "%s: Failed to validate and set overlay for dpy %d"
1879 ,__FUNCTION__, mDpy);
1880 return false;
1881 }
1882
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001883 setRedraw(ctx, list);
Saurabh Shahaa236822013-04-24 18:07:26 -07001884 return true;
1885}
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001886
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08001887bool MDPComp::resourceCheck(hwc_context_t* ctx,
1888 hwc_display_contents_1_t* list) {
Saurabh Shah173f4242013-11-20 09:50:12 -08001889 const bool fbUsed = mCurrentFrame.fbCount;
1890 if(mCurrentFrame.mdpCount > sMaxPipesPerMixer - fbUsed) {
1891 ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
1892 return false;
1893 }
Saurabh Shahacec8e42014-11-25 11:07:04 -08001894
1895 //Will benefit cases where a video has non-updating background.
1896 if((mDpy > HWC_DISPLAY_PRIMARY) and
1897 (mCurrentFrame.mdpCount > sMaxSecLayers)) {
1898 ALOGD_IF(isDebug(), "%s: Exceeds max secondary pipes",__FUNCTION__);
1899 return false;
1900 }
1901
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08001902 // Init rotCount to number of rotate sessions used by other displays
1903 int rotCount = ctx->mRotMgr->getNumActiveSessions();
1904 // Count the number of rotator sessions required for current display
1905 for (int index = 0; index < mCurrentFrame.layerCount; index++) {
1906 if(!mCurrentFrame.isFBComposed[index]) {
1907 hwc_layer_1_t* layer = &list->hwLayers[index];
1908 private_handle_t *hnd = (private_handle_t *)layer->handle;
1909 if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
1910 rotCount++;
1911 }
1912 }
1913 }
1914 // if number of layers to rotate exceeds max rotator sessions, bail out.
1915 if(rotCount > RotMgr::MAX_ROT_SESS) {
1916 ALOGD_IF(isDebug(), "%s: Exceeds max rotator sessions %d",
1917 __FUNCTION__, mDpy);
1918 return false;
1919 }
Saurabh Shah173f4242013-11-20 09:50:12 -08001920 return true;
1921}
1922
Prabhanjan Kandula21918db2013-11-26 15:51:58 +05301923bool MDPComp::hwLimitationsCheck(hwc_context_t* ctx,
1924 hwc_display_contents_1_t* list) {
1925
1926 //A-family hw limitation:
1927 //If a layer need alpha scaling, MDP can not support.
1928 if(ctx->mMDP.version < qdutils::MDSS_V5) {
1929 for(int i = 0; i < mCurrentFrame.layerCount; ++i) {
1930 if(!mCurrentFrame.isFBComposed[i] &&
1931 isAlphaScaled( &list->hwLayers[i])) {
1932 ALOGD_IF(isDebug(), "%s:frame needs alphaScaling",__FUNCTION__);
1933 return false;
1934 }
1935 }
1936 }
1937
1938 // On 8x26 & 8974 hw, we have a limitation of downscaling+blending.
1939 //If multiple layers requires downscaling and also they are overlapping
1940 //fall back to GPU since MDSS can not handle it.
1941 if(qdutils::MDPVersion::getInstance().is8x74v2() ||
1942 qdutils::MDPVersion::getInstance().is8x26()) {
1943 for(int i = 0; i < mCurrentFrame.layerCount-1; ++i) {
1944 hwc_layer_1_t* botLayer = &list->hwLayers[i];
1945 if(!mCurrentFrame.isFBComposed[i] &&
1946 isDownscaleRequired(botLayer)) {
1947 //if layer-i is marked for MDP and needs downscaling
1948 //check if any MDP layer on top of i & overlaps with layer-i
1949 for(int j = i+1; j < mCurrentFrame.layerCount; ++j) {
1950 hwc_layer_1_t* topLayer = &list->hwLayers[j];
1951 if(!mCurrentFrame.isFBComposed[j] &&
1952 isDownscaleRequired(topLayer)) {
1953 hwc_rect_t r = getIntersection(botLayer->displayFrame,
1954 topLayer->displayFrame);
1955 if(isValidRect(r))
1956 return false;
1957 }
1958 }
1959 }
1960 }
1961 }
1962 return true;
1963}
1964
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08001965// Checks only if videos or single layer(RGB) is updating
1966// which is used for setting dynamic fps or perf hint for single
1967// layer video playback
1968bool MDPComp::onlyVideosUpdating(hwc_context_t *ctx,
1969 hwc_display_contents_1_t* list) {
1970 bool support = false;
1971 FrameInfo frame;
1972 frame.reset(mCurrentFrame.layerCount);
1973 memset(&frame.drop, 0, sizeof(frame.drop));
1974 frame.dropCount = 0;
1975 ALOGD_IF(isDebug(), "%s: Update Cache and YUVInfo", __FUNCTION__);
1976 updateLayerCache(ctx, list, frame);
1977 updateYUV(ctx, list, false /*secure only*/, frame);
1978 // There are only updating YUV layers or there is single RGB
1979 // Layer(Youtube)
1980 if((ctx->listStats[mDpy].yuvCount == frame.mdpCount) ||
1981 (frame.layerCount == 1)) {
1982 support = true;
1983 }
1984 return support;
1985}
1986
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05301987void MDPComp::setDynRefreshRate(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
1988 //For primary display, set the dynamic refreshrate
1989 if(!mDpy && qdutils::MDPVersion::getInstance().isDynFpsSupported() &&
1990 ctx->mUseMetaDataRefreshRate) {
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05301991 uint32_t refreshRate = ctx->dpyAttr[mDpy].refreshRate;
1992 MDPVersion& mdpHw = MDPVersion::getInstance();
1993 if(sIdleFallBack) {
1994 //Set minimum panel refresh rate during idle timeout
1995 refreshRate = mdpHw.getMinFpsSupported();
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08001996 } else if(onlyVideosUpdating(ctx, list)) {
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05301997 //Set the new fresh rate, if there is only one updating YUV layer
1998 //or there is one single RGB layer with this request
1999 refreshRate = ctx->listStats[mDpy].refreshRateRequest;
2000 }
2001 setRefreshRate(ctx, mDpy, refreshRate);
2002 }
2003}
2004
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002005int MDPComp::prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002006 int ret = 0;
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07002007 char property[PROPERTY_VALUE_MAX];
2008
Raj Kamal4393eaa2014-06-06 13:45:20 +05302009 if(!ctx || !list) {
2010 ALOGE("%s: Invalid context or list",__FUNCTION__);
2011 mCachedFrame.reset();
2012 return -1;
2013 }
2014
2015 const int numLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shah286cf122014-09-08 14:13:08 -07002016 if(mDpy == HWC_DISPLAY_PRIMARY) {
2017 sSimulationFlags = 0;
2018 if(property_get("debug.hwc.simulate", property, NULL) > 0) {
2019 int currentFlags = atoi(property);
2020 if(currentFlags != sSimulationFlags) {
2021 sSimulationFlags = currentFlags;
2022 ALOGI("%s: Simulation Flag read: 0x%x (%d)", __FUNCTION__,
2023 sSimulationFlags, sSimulationFlags);
2024 }
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07002025 }
2026 }
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002027 // reset PTOR
2028 if(!mDpy)
2029 memset(&(ctx->mPtorInfo), 0, sizeof(ctx->mPtorInfo));
Ramkumar Radhakrishnanc5893f12013-06-06 19:43:53 -07002030
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302031 //reset old data
2032 mCurrentFrame.reset(numLayers);
2033 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
2034 mCurrentFrame.dropCount = 0;
2035
Raj Kamal9ed3d6b2014-02-07 16:15:17 +05302036 //Do not cache the information for next draw cycle.
2037 if(numLayers > MAX_NUM_APP_LAYERS or (!numLayers)) {
2038 ALOGI("%s: Unsupported layer count for mdp composition",
2039 __FUNCTION__);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002040 mCachedFrame.reset();
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302041#ifdef DYNAMIC_FPS
2042 setDynRefreshRate(ctx, list);
2043#endif
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002044 return -1;
2045 }
2046
Ramkumar Radhakrishnana70981a2013-08-28 11:33:53 -07002047 // Detect the start of animation and fall back to GPU only once to cache
2048 // all the layers in FB and display FB content untill animation completes.
2049 if(ctx->listStats[mDpy].isDisplayAnimating) {
2050 mCurrentFrame.needsRedraw = false;
2051 if(ctx->mAnimationState[mDpy] == ANIMATION_STOPPED) {
2052 mCurrentFrame.needsRedraw = true;
2053 ctx->mAnimationState[mDpy] = ANIMATION_STARTED;
2054 }
2055 setMDPCompLayerFlags(ctx, list);
2056 mCachedFrame.updateCounts(mCurrentFrame);
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302057#ifdef DYNAMIC_FPS
2058 setDynRefreshRate(ctx, list);
2059#endif
Ramkumar Radhakrishnana70981a2013-08-28 11:33:53 -07002060 ret = -1;
2061 return ret;
2062 } else {
2063 ctx->mAnimationState[mDpy] = ANIMATION_STOPPED;
2064 }
2065
Raj Kamalfdfdddf2015-03-16 21:59:25 +05302066 if(!mDpy and !isSecondaryConnected(ctx) and !mPrevModeOn and
2067 mCachedFrame.isSameFrame(ctx,mDpy,list)) {
2068
2069 ALOGD_IF(isDebug(),"%s: Avoid new composition",__FUNCTION__);
2070 mCurrentFrame.needsRedraw = false;
2071 setMDPCompLayerFlags(ctx, list);
2072 mCachedFrame.updateCounts(mCurrentFrame);
2073#ifdef DYNAMIC_FPS
2074 setDynRefreshRate(ctx, list);
2075#endif
2076 return -1;
2077
2078 }
2079
Saurabh Shahb39f8152013-08-22 10:21:44 -07002080 //Hard conditions, if not met, cannot do MDP comp
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002081 if(isFrameDoable(ctx)) {
2082 generateROI(ctx, list);
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07002083 // if AIV Video mode is enabled, drop all non AIV layers from the
2084 // external display list.
2085 if(ctx->listStats[mDpy].mAIVVideoMode) {
2086 dropNonAIVLayers(ctx, list);
2087 }
Saurabh Shahb39f8152013-08-22 10:21:44 -07002088
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07002089 // if tryFullFrame fails, try to push all video and secure RGB layers
2090 // to MDP for composition.
2091 mModeOn = tryFullFrame(ctx, list) || tryMDPOnlyLayers(ctx, list) ||
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07002092 tryVideoOnly(ctx, list);
Raj Kamal4393eaa2014-06-06 13:45:20 +05302093 if(mModeOn) {
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002094 setMDPCompLayerFlags(ctx, list);
2095 } else {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08002096 resetROI(ctx, mDpy);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002097 reset(ctx);
2098 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
2099 mCurrentFrame.dropCount = 0;
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002100 ret = -1;
Saurabh Shah286cf122014-09-08 14:13:08 -07002101 ALOGE_IF(sSimulationFlags && (mDpy == HWC_DISPLAY_PRIMARY),
2102 "MDP Composition Strategies Failed");
Saurabh Shahb39f8152013-08-22 10:21:44 -07002103 }
2104 } else {
Dileep Kumar Reddi4070e932014-09-30 09:00:57 +05302105 if ((ctx->mMDP.version == qdutils::MDP_V3_0_5) && ctx->mCopyBit[mDpy] &&
2106 enablePartialUpdateForMDP3) {
2107 generateROI(ctx, list);
2108 for(int i = 0; i < ctx->listStats[mDpy].numAppLayers; i++) {
2109 ctx->copybitDrop[i] = mCurrentFrame.drop[i];
2110 }
2111 }
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002112 ALOGD_IF( isDebug(),"%s: MDP Comp not possible for this frame",
2113 __FUNCTION__);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002114 ret = -1;
Saurabh Shahb39f8152013-08-22 10:21:44 -07002115 }
Saurabh Shahb39f8152013-08-22 10:21:44 -07002116
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002117 if(isDebug()) {
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002118 ALOGD("GEOMETRY change: %d",
2119 (list->flags & HWC_GEOMETRY_CHANGED));
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002120 android::String8 sDump("");
Jeykumar Sankaran6850ac62014-05-27 10:07:26 -07002121 dump(sDump, ctx);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002122 ALOGD("%s",sDump.string());
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002123 }
2124
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07002125#ifdef DYNAMIC_FPS
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302126 setDynRefreshRate(ctx, list);
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07002127#endif
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08002128 setPerfHint(ctx, list);
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07002129
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002130 mCachedFrame.cacheAll(list);
2131 mCachedFrame.updateCounts(mCurrentFrame);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002132 return ret;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002133}
2134
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002135bool MDPComp::allocSplitVGPipes(hwc_context_t *ctx, int index) {
radhakrishnac9a67412013-09-25 17:40:42 +05302136
2137 bool bRet = true;
radhakrishnac9a67412013-09-25 17:40:42 +05302138 int mdpIndex = mCurrentFrame.layerToMDP[index];
2139 PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
2140 info.pipeInfo = new MdpYUVPipeInfo;
2141 info.rot = NULL;
2142 MdpYUVPipeInfo& pipe_info = *(MdpYUVPipeInfo*)info.pipeInfo;
radhakrishnac9a67412013-09-25 17:40:42 +05302143
2144 pipe_info.lIndex = ovutils::OV_INVALID;
2145 pipe_info.rIndex = ovutils::OV_INVALID;
2146
Saurabh Shahc62f3982014-03-05 14:28:26 -08002147 Overlay::PipeSpecs pipeSpecs;
2148 pipeSpecs.formatClass = Overlay::FORMAT_YUV;
2149 pipeSpecs.needsScaling = true;
2150 pipeSpecs.dpy = mDpy;
2151 pipeSpecs.fb = false;
2152
2153 pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
radhakrishnac9a67412013-09-25 17:40:42 +05302154 if(pipe_info.lIndex == ovutils::OV_INVALID){
2155 bRet = false;
2156 ALOGD_IF(isDebug(),"%s: allocating first VG pipe failed",
2157 __FUNCTION__);
2158 }
Saurabh Shahc62f3982014-03-05 14:28:26 -08002159 pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
radhakrishnac9a67412013-09-25 17:40:42 +05302160 if(pipe_info.rIndex == ovutils::OV_INVALID){
2161 bRet = false;
2162 ALOGD_IF(isDebug(),"%s: allocating second VG pipe failed",
2163 __FUNCTION__);
2164 }
2165 return bRet;
2166}
Sushil Chauhandefd3522014-05-13 18:17:12 -07002167
2168int MDPComp::drawOverlap(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
2169 int fd = -1;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002170 if (ctx->mPtorInfo.isActive()) {
2171 fd = ctx->mCopyBit[mDpy]->drawOverlap(ctx, list);
Sushil Chauhandefd3522014-05-13 18:17:12 -07002172 if (fd < 0) {
2173 ALOGD_IF(isDebug(),"%s: failed", __FUNCTION__);
Sushil Chauhandefd3522014-05-13 18:17:12 -07002174 }
2175 }
2176 return fd;
2177}
Arun Kumar K.R2aa44c62014-01-21 23:08:28 -08002178//=============MDPCompNonSplit==================================================
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002179
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002180void MDPCompNonSplit::adjustForSourceSplit(hwc_context_t *ctx,
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302181 hwc_display_contents_1_t* list) {
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002182 //If 4k2k Yuv layer split is possible, and if
2183 //fbz is above 4k2k layer, increment fb zorder by 1
2184 //as we split 4k2k layer and increment zorder for right half
2185 //of the layer
Shalaj Jaina70b4352014-06-15 13:47:47 -07002186 if(!ctx)
2187 return;
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002188 if(mCurrentFrame.fbZ >= 0) {
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302189 for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
2190 index++) {
2191 if(!mCurrentFrame.isFBComposed[index]) {
2192 if(mdpNextZOrder == mCurrentFrame.fbZ) {
2193 mdpNextZOrder++;
2194 }
2195 mdpNextZOrder++;
2196 hwc_layer_1_t* layer = &list->hwLayers[index];
2197 private_handle_t *hnd = (private_handle_t *)layer->handle;
Raj Kamal389d6e32014-08-04 14:43:24 +05302198 if(isYUVSplitNeeded(hnd)) {
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302199 if(mdpNextZOrder <= mCurrentFrame.fbZ)
2200 mCurrentFrame.fbZ += 1;
2201 mdpNextZOrder++;
2202 //As we split 4kx2k yuv layer and program to 2 VG pipes
2203 //(if available) increase mdpcount by 1.
2204 mCurrentFrame.mdpCount++;
2205 }
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002206 }
2207 }
2208 }
radhakrishnac9a67412013-09-25 17:40:42 +05302209}
2210
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002211/*
2212 * Configures pipe(s) for MDP composition
2213 */
Saurabh Shah88e4d272013-09-03 13:31:29 -07002214int MDPCompNonSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002215 PipeLayerPair& PipeLayerPair) {
Saurabh Shah88e4d272013-09-03 13:31:29 -07002216 MdpPipeInfoNonSplit& mdp_info =
2217 *(static_cast<MdpPipeInfoNonSplit*>(PipeLayerPair.pipeInfo));
Justin Philipd6166602014-08-12 13:42:21 +05302218 eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shahacf10202013-02-26 10:15:15 -08002219 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Saurabh Shahacf10202013-02-26 10:15:15 -08002220 eDest dest = mdp_info.index;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002221
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002222 ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipe: %d",
2223 __FUNCTION__, layer, zOrder, dest);
2224
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002225 return configureNonSplit(ctx, layer, mDpy, mdpFlags, zOrder, dest,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002226 &PipeLayerPair.rot);
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002227}
2228
Saurabh Shah88e4d272013-09-03 13:31:29 -07002229bool MDPCompNonSplit::allocLayerPipes(hwc_context_t *ctx,
Saurabh Shahe51f8ca2013-05-06 17:26:16 -07002230 hwc_display_contents_1_t* list) {
2231 for(int index = 0; index < mCurrentFrame.layerCount; index++) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002232
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002233 if(mCurrentFrame.isFBComposed[index]) continue;
Saurabh Shahe51f8ca2013-05-06 17:26:16 -07002234
Jeykumar Sankarancf537002013-01-21 21:19:15 -08002235 hwc_layer_1_t* layer = &list->hwLayers[index];
2236 private_handle_t *hnd = (private_handle_t *)layer->handle;
Raj Kamal389d6e32014-08-04 14:43:24 +05302237 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002238 if(allocSplitVGPipes(ctx, index)){
radhakrishnac9a67412013-09-25 17:40:42 +05302239 continue;
2240 }
2241 }
2242
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002243 int mdpIndex = mCurrentFrame.layerToMDP[index];
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002244 PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
Saurabh Shah88e4d272013-09-03 13:31:29 -07002245 info.pipeInfo = new MdpPipeInfoNonSplit;
Saurabh Shahacf10202013-02-26 10:15:15 -08002246 info.rot = NULL;
Saurabh Shah88e4d272013-09-03 13:31:29 -07002247 MdpPipeInfoNonSplit& pipe_info = *(MdpPipeInfoNonSplit*)info.pipeInfo;
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -08002248
Saurabh Shahc62f3982014-03-05 14:28:26 -08002249 Overlay::PipeSpecs pipeSpecs;
2250 pipeSpecs.formatClass = isYuvBuffer(hnd) ?
2251 Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
2252 pipeSpecs.needsScaling = qhwc::needsScaling(layer) or
2253 (qdutils::MDPVersion::getInstance().is8x26() and
2254 ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres > 1024);
2255 pipeSpecs.dpy = mDpy;
2256 pipeSpecs.fb = false;
Xu Yang1e686f62014-04-08 13:56:47 +08002257 pipeSpecs.numActiveDisplays = ctx->numActiveDisplays;
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -08002258
Saurabh Shahc62f3982014-03-05 14:28:26 -08002259 pipe_info.index = ctx->mOverlay->getPipe(pipeSpecs);
2260
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002261 if(pipe_info.index == ovutils::OV_INVALID) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002262 ALOGD_IF(isDebug(), "%s: Unable to get pipe", __FUNCTION__);
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002263 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002264 }
2265 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002266 return true;
2267}
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002268
radhakrishnac9a67412013-09-25 17:40:42 +05302269int MDPCompNonSplit::configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
2270 PipeLayerPair& PipeLayerPair) {
2271 MdpYUVPipeInfo& mdp_info =
2272 *(static_cast<MdpYUVPipeInfo*>(PipeLayerPair.pipeInfo));
2273 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Justin Philipd6166602014-08-12 13:42:21 +05302274 eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
radhakrishnac9a67412013-09-25 17:40:42 +05302275 eDest lDest = mdp_info.lIndex;
2276 eDest rDest = mdp_info.rIndex;
2277
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002278 return configureSourceSplit(ctx, layer, mDpy, mdpFlagsL, zOrder,
radhakrishnac9a67412013-09-25 17:40:42 +05302279 lDest, rDest, &PipeLayerPair.rot);
2280}
2281
Saurabh Shah88e4d272013-09-03 13:31:29 -07002282bool MDPCompNonSplit::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002283
Raj Kamal4393eaa2014-06-06 13:45:20 +05302284 if(!isEnabled() or !mModeOn) {
2285 ALOGD_IF(isDebug(),"%s: MDP Comp not enabled/configured", __FUNCTION__);
Prabhanjan Kandula08222fc2013-07-10 17:20:59 +05302286 return true;
2287 }
2288
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002289 overlay::Overlay& ov = *ctx->mOverlay;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002290 LayerProp *layerProp = ctx->layerProp[mDpy];
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002291
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002292 int numHwLayers = ctx->listStats[mDpy].numAppLayers;
2293 for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ )
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002294 {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002295 if(mCurrentFrame.isFBComposed[i]) continue;
2296
Naseer Ahmed5b6708a2012-08-02 13:46:08 -07002297 hwc_layer_1_t *layer = &list->hwLayers[i];
Saurabh Shahacf10202013-02-26 10:15:15 -08002298 private_handle_t *hnd = (private_handle_t *)layer->handle;
2299 if(!hnd) {
Sushil Chauhan897a9c32013-07-18 11:09:55 -07002300 if (!(layer->flags & HWC_COLOR_FILL)) {
2301 ALOGE("%s handle null", __FUNCTION__);
2302 return false;
2303 }
2304 // No PLAY for Color layer
2305 layerProp[i].mFlags &= ~HWC_MDPCOMP;
2306 continue;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002307 }
2308
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002309 int mdpIndex = mCurrentFrame.layerToMDP[i];
2310
Raj Kamal389d6e32014-08-04 14:43:24 +05302311 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit)
radhakrishnac9a67412013-09-25 17:40:42 +05302312 {
2313 MdpYUVPipeInfo& pipe_info =
2314 *(MdpYUVPipeInfo*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
2315 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
2316 ovutils::eDest indexL = pipe_info.lIndex;
2317 ovutils::eDest indexR = pipe_info.rIndex;
2318 int fd = hnd->fd;
Praveena Pachipulusud9443c72014-02-17 10:42:28 +05302319 uint32_t offset = (uint32_t)hnd->offset;
radhakrishnac9a67412013-09-25 17:40:42 +05302320 if(rot) {
2321 rot->queueBuffer(fd, offset);
2322 fd = rot->getDstMemId();
2323 offset = rot->getDstOffset();
2324 }
2325 if(indexL != ovutils::OV_INVALID) {
2326 ovutils::eDest destL = (ovutils::eDest)indexL;
2327 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2328 using pipe: %d", __FUNCTION__, layer, hnd, indexL );
2329 if (!ov.queueBuffer(fd, offset, destL)) {
2330 ALOGE("%s: queueBuffer failed for display:%d",
2331 __FUNCTION__, mDpy);
2332 return false;
2333 }
2334 }
2335
2336 if(indexR != ovutils::OV_INVALID) {
2337 ovutils::eDest destR = (ovutils::eDest)indexR;
2338 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2339 using pipe: %d", __FUNCTION__, layer, hnd, indexR );
2340 if (!ov.queueBuffer(fd, offset, destR)) {
2341 ALOGE("%s: queueBuffer failed for display:%d",
2342 __FUNCTION__, mDpy);
2343 return false;
2344 }
2345 }
2346 }
2347 else{
2348 MdpPipeInfoNonSplit& pipe_info =
Saurabh Shah88e4d272013-09-03 13:31:29 -07002349 *(MdpPipeInfoNonSplit*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
radhakrishnac9a67412013-09-25 17:40:42 +05302350 ovutils::eDest dest = pipe_info.index;
2351 if(dest == ovutils::OV_INVALID) {
2352 ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, dest);
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002353 return false;
radhakrishnac9a67412013-09-25 17:40:42 +05302354 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002355
radhakrishnac9a67412013-09-25 17:40:42 +05302356 if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
2357 continue;
2358 }
2359
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002360 int fd = hnd->fd;
2361 uint32_t offset = (uint32_t)hnd->offset;
2362 int index = ctx->mPtorInfo.getPTORArrayIndex(i);
2363 if (!mDpy && (index != -1)) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07002364 hnd = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002365 fd = hnd->fd;
Sushil Chauhan875a92e2014-07-25 12:20:23 -07002366 offset = 0;
Sushil Chauhandefd3522014-05-13 18:17:12 -07002367 }
2368
radhakrishnac9a67412013-09-25 17:40:42 +05302369 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2370 using pipe: %d", __FUNCTION__, layer,
2371 hnd, dest );
2372
radhakrishnac9a67412013-09-25 17:40:42 +05302373 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
2374 if(rot) {
2375 if(!rot->queueBuffer(fd, offset))
2376 return false;
2377 fd = rot->getDstMemId();
2378 offset = rot->getDstOffset();
2379 }
2380
2381 if (!ov.queueBuffer(fd, offset, dest)) {
2382 ALOGE("%s: queueBuffer failed for display:%d ",
2383 __FUNCTION__, mDpy);
2384 return false;
2385 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002386 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002387
2388 layerProp[i].mFlags &= ~HWC_MDPCOMP;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002389 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002390 return true;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002391}
2392
Saurabh Shah88e4d272013-09-03 13:31:29 -07002393//=============MDPCompSplit===================================================
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002394
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002395void MDPCompSplit::adjustForSourceSplit(hwc_context_t *ctx,
radhakrishnac9a67412013-09-25 17:40:42 +05302396 hwc_display_contents_1_t* list){
2397 //if 4kx2k yuv layer is totally present in either in left half
2398 //or right half then try splitting the yuv layer to avoid decimation
radhakrishnac9a67412013-09-25 17:40:42 +05302399 const int lSplit = getLeftSplit(ctx, mDpy);
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302400 if(mCurrentFrame.fbZ >= 0) {
2401 for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
2402 index++) {
2403 if(!mCurrentFrame.isFBComposed[index]) {
2404 if(mdpNextZOrder == mCurrentFrame.fbZ) {
2405 mdpNextZOrder++;
2406 }
2407 mdpNextZOrder++;
2408 hwc_layer_1_t* layer = &list->hwLayers[index];
2409 private_handle_t *hnd = (private_handle_t *)layer->handle;
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002410 if(isYUVSplitNeeded(hnd) ||
2411 (needs3DComposition(ctx,mDpy) &&
2412 get3DFormat(hnd) != HAL_NO_3D)) {
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302413 hwc_rect_t dst = layer->displayFrame;
2414 if((dst.left > lSplit) || (dst.right < lSplit)) {
2415 mCurrentFrame.mdpCount += 1;
2416 }
2417 if(mdpNextZOrder <= mCurrentFrame.fbZ)
2418 mCurrentFrame.fbZ += 1;
2419 mdpNextZOrder++;
2420 }
2421 }
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002422 }
radhakrishnac9a67412013-09-25 17:40:42 +05302423 }
2424}
2425
Saurabh Shah88e4d272013-09-03 13:31:29 -07002426bool MDPCompSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
Saurabh Shahc62f3982014-03-05 14:28:26 -08002427 MdpPipeInfoSplit& pipe_info) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002428
Saurabh Shahc62f3982014-03-05 14:28:26 -08002429 const int lSplit = getLeftSplit(ctx, mDpy);
2430 private_handle_t *hnd = (private_handle_t *)layer->handle;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002431 hwc_rect_t dst = layer->displayFrame;
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002432 pipe_info.lIndex = ovutils::OV_INVALID;
2433 pipe_info.rIndex = ovutils::OV_INVALID;
2434
Saurabh Shahc62f3982014-03-05 14:28:26 -08002435 Overlay::PipeSpecs pipeSpecs;
2436 pipeSpecs.formatClass = isYuvBuffer(hnd) ?
2437 Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
2438 pipeSpecs.needsScaling = qhwc::needsScalingWithSplit(ctx, layer, mDpy);
2439 pipeSpecs.dpy = mDpy;
2440 pipeSpecs.mixer = Overlay::MIXER_LEFT;
2441 pipeSpecs.fb = false;
2442
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08002443 // Acquire pipe only for the updating half
2444 hwc_rect_t l_roi = ctx->listStats[mDpy].lRoi;
2445 hwc_rect_t r_roi = ctx->listStats[mDpy].rRoi;
2446
2447 if (dst.left < lSplit && isValidRect(getIntersection(dst, l_roi))) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002448 pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002449 if(pipe_info.lIndex == ovutils::OV_INVALID)
2450 return false;
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002451 }
2452
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08002453 if(dst.right > lSplit && isValidRect(getIntersection(dst, r_roi))) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002454 pipeSpecs.mixer = Overlay::MIXER_RIGHT;
2455 pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002456 if(pipe_info.rIndex == ovutils::OV_INVALID)
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002457 return false;
2458 }
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002459
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002460 return true;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002461}
2462
Saurabh Shah88e4d272013-09-03 13:31:29 -07002463bool MDPCompSplit::allocLayerPipes(hwc_context_t *ctx,
Saurabh Shahe51f8ca2013-05-06 17:26:16 -07002464 hwc_display_contents_1_t* list) {
2465 for(int index = 0 ; index < mCurrentFrame.layerCount; index++) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002466
Saurabh Shahe51f8ca2013-05-06 17:26:16 -07002467 if(mCurrentFrame.isFBComposed[index]) continue;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002468
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002469 hwc_layer_1_t* layer = &list->hwLayers[index];
2470 private_handle_t *hnd = (private_handle_t *)layer->handle;
radhakrishnac9a67412013-09-25 17:40:42 +05302471 hwc_rect_t dst = layer->displayFrame;
2472 const int lSplit = getLeftSplit(ctx, mDpy);
Raj Kamal389d6e32014-08-04 14:43:24 +05302473 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
radhakrishnac9a67412013-09-25 17:40:42 +05302474 if((dst.left > lSplit)||(dst.right < lSplit)){
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002475 if(allocSplitVGPipes(ctx, index)){
radhakrishnac9a67412013-09-25 17:40:42 +05302476 continue;
2477 }
2478 }
2479 }
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002480 //XXX: Check for forced 2D composition
2481 if(needs3DComposition(ctx, mDpy) && get3DFormat(hnd) != HAL_NO_3D)
2482 if(allocSplitVGPipes(ctx,index))
2483 continue;
2484
Saurabh Shah0d65dbe2013-06-06 18:33:16 -07002485 int mdpIndex = mCurrentFrame.layerToMDP[index];
2486 PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
Saurabh Shah88e4d272013-09-03 13:31:29 -07002487 info.pipeInfo = new MdpPipeInfoSplit;
Saurabh Shah9e3adb22013-03-26 11:16:27 -07002488 info.rot = NULL;
Saurabh Shah88e4d272013-09-03 13:31:29 -07002489 MdpPipeInfoSplit& pipe_info = *(MdpPipeInfoSplit*)info.pipeInfo;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002490
Saurabh Shahc62f3982014-03-05 14:28:26 -08002491 if(!acquireMDPPipes(ctx, layer, pipe_info)) {
2492 ALOGD_IF(isDebug(), "%s: Unable to get pipe for type",
2493 __FUNCTION__);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002494 return false;
2495 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002496 }
2497 return true;
2498}
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002499
radhakrishnac9a67412013-09-25 17:40:42 +05302500int MDPCompSplit::configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
2501 PipeLayerPair& PipeLayerPair) {
2502 const int lSplit = getLeftSplit(ctx, mDpy);
2503 hwc_rect_t dst = layer->displayFrame;
2504 if((dst.left > lSplit)||(dst.right < lSplit)){
2505 MdpYUVPipeInfo& mdp_info =
2506 *(static_cast<MdpYUVPipeInfo*>(PipeLayerPair.pipeInfo));
2507 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Justin Philipd6166602014-08-12 13:42:21 +05302508 eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
radhakrishnac9a67412013-09-25 17:40:42 +05302509 eDest lDest = mdp_info.lIndex;
2510 eDest rDest = mdp_info.rIndex;
2511
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002512 return configureSourceSplit(ctx, layer, mDpy, mdpFlagsL, zOrder,
radhakrishnac9a67412013-09-25 17:40:42 +05302513 lDest, rDest, &PipeLayerPair.rot);
2514 }
2515 else{
2516 return configure(ctx, layer, PipeLayerPair);
2517 }
2518}
2519
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002520/*
2521 * Configures pipe(s) for MDP composition
2522 */
Saurabh Shah88e4d272013-09-03 13:31:29 -07002523int MDPCompSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
Saurabh Shah67a38c32013-06-10 16:23:15 -07002524 PipeLayerPair& PipeLayerPair) {
Saurabh Shah88e4d272013-09-03 13:31:29 -07002525 MdpPipeInfoSplit& mdp_info =
2526 *(static_cast<MdpPipeInfoSplit*>(PipeLayerPair.pipeInfo));
Saurabh Shahacf10202013-02-26 10:15:15 -08002527 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Justin Philipd6166602014-08-12 13:42:21 +05302528 eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shahacf10202013-02-26 10:15:15 -08002529 eDest lDest = mdp_info.lIndex;
2530 eDest rDest = mdp_info.rIndex;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002531
2532 ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
Jeykumar Sankaran39305802014-12-12 17:55:57 -08002533 "dest_pipeR: %d",__FUNCTION__, layer, zOrder, lDest, rDest);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002534
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002535 return configureSplit(ctx, layer, mDpy, mdpFlagsL, zOrder, lDest,
Jeykumar Sankaran39305802014-12-12 17:55:57 -08002536 rDest, &PipeLayerPair.rot);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002537}
2538
Saurabh Shah88e4d272013-09-03 13:31:29 -07002539bool MDPCompSplit::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002540
Raj Kamal4393eaa2014-06-06 13:45:20 +05302541 if(!isEnabled() or !mModeOn) {
2542 ALOGD_IF(isDebug(),"%s: MDP Comp not enabled/configured", __FUNCTION__);
Prabhanjan Kandula08222fc2013-07-10 17:20:59 +05302543 return true;
2544 }
2545
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002546 overlay::Overlay& ov = *ctx->mOverlay;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002547 LayerProp *layerProp = ctx->layerProp[mDpy];
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002548
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002549 int numHwLayers = ctx->listStats[mDpy].numAppLayers;
2550 for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ )
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002551 {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002552 if(mCurrentFrame.isFBComposed[i]) continue;
2553
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002554 hwc_layer_1_t *layer = &list->hwLayers[i];
Saurabh Shahacf10202013-02-26 10:15:15 -08002555 private_handle_t *hnd = (private_handle_t *)layer->handle;
2556 if(!hnd) {
2557 ALOGE("%s handle null", __FUNCTION__);
2558 return false;
2559 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002560
2561 if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
2562 continue;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002563 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002564
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002565 int mdpIndex = mCurrentFrame.layerToMDP[i];
2566
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002567 if((isYUVSplitNeeded(hnd) && sEnableYUVsplit) ||
2568 (needs3DComposition(ctx, mDpy) && get3DFormat(hnd) != HAL_NO_3D))
radhakrishnac9a67412013-09-25 17:40:42 +05302569 {
2570 MdpYUVPipeInfo& pipe_info =
2571 *(MdpYUVPipeInfo*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
2572 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
2573 ovutils::eDest indexL = pipe_info.lIndex;
2574 ovutils::eDest indexR = pipe_info.rIndex;
2575 int fd = hnd->fd;
Praveena Pachipulusud9443c72014-02-17 10:42:28 +05302576 uint32_t offset = (uint32_t)hnd->offset;
radhakrishnac9a67412013-09-25 17:40:42 +05302577 if(rot) {
2578 rot->queueBuffer(fd, offset);
2579 fd = rot->getDstMemId();
2580 offset = rot->getDstOffset();
2581 }
2582 if(indexL != ovutils::OV_INVALID) {
2583 ovutils::eDest destL = (ovutils::eDest)indexL;
2584 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2585 using pipe: %d", __FUNCTION__, layer, hnd, indexL );
2586 if (!ov.queueBuffer(fd, offset, destL)) {
2587 ALOGE("%s: queueBuffer failed for display:%d",
2588 __FUNCTION__, mDpy);
2589 return false;
2590 }
2591 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002592
radhakrishnac9a67412013-09-25 17:40:42 +05302593 if(indexR != ovutils::OV_INVALID) {
2594 ovutils::eDest destR = (ovutils::eDest)indexR;
2595 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2596 using pipe: %d", __FUNCTION__, layer, hnd, indexR );
2597 if (!ov.queueBuffer(fd, offset, destR)) {
2598 ALOGE("%s: queueBuffer failed for display:%d",
2599 __FUNCTION__, mDpy);
2600 return false;
2601 }
Saurabh Shaha9da08f2013-07-03 13:27:53 -07002602 }
2603 }
radhakrishnac9a67412013-09-25 17:40:42 +05302604 else{
2605 MdpPipeInfoSplit& pipe_info =
2606 *(MdpPipeInfoSplit*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
2607 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
Saurabh Shaha9da08f2013-07-03 13:27:53 -07002608
radhakrishnac9a67412013-09-25 17:40:42 +05302609 ovutils::eDest indexL = pipe_info.lIndex;
2610 ovutils::eDest indexR = pipe_info.rIndex;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002611
radhakrishnac9a67412013-09-25 17:40:42 +05302612 int fd = hnd->fd;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002613 uint32_t offset = (uint32_t)hnd->offset;
2614 int index = ctx->mPtorInfo.getPTORArrayIndex(i);
2615 if (!mDpy && (index != -1)) {
2616 hnd = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
2617 fd = hnd->fd;
Sushil Chauhan875a92e2014-07-25 12:20:23 -07002618 offset = 0;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002619 }
radhakrishnac9a67412013-09-25 17:40:42 +05302620
Tatenda Chipeperekwa88fe6352014-04-14 10:36:06 -07002621 if(ctx->mAD->draw(ctx, fd, offset)) {
2622 fd = ctx->mAD->getDstFd();
2623 offset = ctx->mAD->getDstOffset();
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002624 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002625
radhakrishnac9a67412013-09-25 17:40:42 +05302626 if(rot) {
2627 rot->queueBuffer(fd, offset);
2628 fd = rot->getDstMemId();
2629 offset = rot->getDstOffset();
2630 }
2631
2632 //************* play left mixer **********
2633 if(indexL != ovutils::OV_INVALID) {
2634 ovutils::eDest destL = (ovutils::eDest)indexL;
2635 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2636 using pipe: %d", __FUNCTION__, layer, hnd, indexL );
2637 if (!ov.queueBuffer(fd, offset, destL)) {
2638 ALOGE("%s: queueBuffer failed for left mixer",
2639 __FUNCTION__);
2640 return false;
2641 }
2642 }
2643
2644 //************* play right mixer **********
2645 if(indexR != ovutils::OV_INVALID) {
2646 ovutils::eDest destR = (ovutils::eDest)indexR;
2647 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2648 using pipe: %d", __FUNCTION__, layer, hnd, indexR );
2649 if (!ov.queueBuffer(fd, offset, destR)) {
2650 ALOGE("%s: queueBuffer failed for right mixer",
2651 __FUNCTION__);
2652 return false;
2653 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002654 }
2655 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002656
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002657 layerProp[i].mFlags &= ~HWC_MDPCOMP;
2658 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002659
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002660 return true;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002661}
Saurabh Shahab47c692014-02-12 18:45:57 -08002662
2663//================MDPCompSrcSplit==============================================
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08002664
2665bool MDPCompSrcSplit::validateAndApplyROI(hwc_context_t *ctx,
2666 hwc_display_contents_1_t* list) {
2667 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
2668 hwc_rect_t visibleRect = ctx->listStats[mDpy].lRoi;
2669
2670 for(int i = numAppLayers - 1; i >= 0; i--) {
2671 if(!isValidRect(visibleRect)) {
2672 mCurrentFrame.drop[i] = true;
2673 mCurrentFrame.dropCount++;
2674 continue;
2675 }
2676
2677 const hwc_layer_1_t* layer = &list->hwLayers[i];
2678 hwc_rect_t dstRect = layer->displayFrame;
2679 hwc_rect_t res = getIntersection(visibleRect, dstRect);
2680
2681 if(!isValidRect(res)) {
2682 mCurrentFrame.drop[i] = true;
2683 mCurrentFrame.dropCount++;
2684 } else {
2685 /* Reset frame ROI when any layer which needs scaling also needs ROI
2686 * cropping */
2687 if(!isSameRect(res, dstRect) && needsScaling (layer)) {
2688 ALOGI("%s: Resetting ROI due to scaling", __FUNCTION__);
2689 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
2690 mCurrentFrame.dropCount = 0;
2691 return false;
2692 }
2693
2694 /* deduct any opaque region from visibleRect */
2695 if (layer->blending == HWC_BLENDING_NONE &&
2696 layer->planeAlpha == 0xFF)
2697 visibleRect = deductRect(visibleRect, res);
2698 }
2699 }
2700 return true;
2701}
2702
2703/*
2704 * HW Limitation: ping pong split can always split the ping pong output
2705 * equally across two DSI's. So the ROI programmed should be of equal width
2706 * for both the halves
2707 */
2708void MDPCompSrcSplit::generateROI(hwc_context_t *ctx,
2709 hwc_display_contents_1_t* list) {
2710 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
2711
2712
2713 if(!canPartialUpdate(ctx, list))
2714 return;
2715
2716 struct hwc_rect roi = (struct hwc_rect){0, 0, 0, 0};
2717 hwc_rect fullFrame = (struct hwc_rect) {0, 0,(int)ctx->dpyAttr[mDpy].xres,
2718 (int)ctx->dpyAttr[mDpy].yres};
2719
2720 for(int index = 0; index < numAppLayers; index++ ) {
2721 hwc_layer_1_t* layer = &list->hwLayers[index];
2722
2723 // If we have a RGB layer which needs rotation, no partial update
2724 if(!isYuvBuffer((private_handle_t *)layer->handle) && layer->transform)
2725 return;
2726
2727 if ((mCachedFrame.hnd[index] != layer->handle) ||
2728 isYuvBuffer((private_handle_t *)layer->handle)) {
2729 hwc_rect_t dst = layer->displayFrame;
2730 hwc_rect_t updatingRect = dst;
2731
2732#ifdef QCOM_BSP
2733 if(!needsScaling(layer) && !layer->transform)
2734 {
2735 hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
2736 int x_off = dst.left - src.left;
2737 int y_off = dst.top - src.top;
2738 updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
2739 }
2740#endif
2741
2742 roi = getUnion(roi, updatingRect);
2743 }
2744 }
2745
2746 /* No layer is updating. Still SF wants a refresh.*/
2747 if(!isValidRect(roi))
2748 return;
2749
2750 roi = expandROIFromMidPoint(roi, fullFrame);
2751
2752 hwc_rect lFrame = fullFrame;
2753 lFrame.right /= 2;
2754 hwc_rect lRoi = getIntersection(roi, lFrame);
2755
2756 // Align ROI coordinates to panel restrictions
2757 lRoi = getSanitizeROI(lRoi, lFrame);
2758
2759 hwc_rect rFrame = fullFrame;
2760 rFrame.left = lFrame.right;
2761 hwc_rect rRoi = getIntersection(roi, rFrame);
2762
2763 // Align ROI coordinates to panel restrictions
2764 rRoi = getSanitizeROI(rRoi, rFrame);
2765
2766 roi = getUnion(lRoi, rRoi);
2767
2768 ctx->listStats[mDpy].lRoi = roi;
2769 if(!validateAndApplyROI(ctx, list))
2770 resetROI(ctx, mDpy);
2771
2772 ALOGD_IF(isDebug(),"%s: generated ROI: [%d, %d, %d, %d] [%d, %d, %d, %d]",
2773 __FUNCTION__,
2774 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
2775 ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom,
2776 ctx->listStats[mDpy].rRoi.left, ctx->listStats[mDpy].rRoi.top,
2777 ctx->listStats[mDpy].rRoi.right, ctx->listStats[mDpy].rRoi.bottom);
2778}
2779
Saurabh Shahab47c692014-02-12 18:45:57 -08002780bool MDPCompSrcSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
Saurabh Shahc62f3982014-03-05 14:28:26 -08002781 MdpPipeInfoSplit& pipe_info) {
Saurabh Shahab47c692014-02-12 18:45:57 -08002782 private_handle_t *hnd = (private_handle_t *)layer->handle;
2783 hwc_rect_t dst = layer->displayFrame;
2784 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
2785 pipe_info.lIndex = ovutils::OV_INVALID;
2786 pipe_info.rIndex = ovutils::OV_INVALID;
2787
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08002788 if(qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() && !mDpy)
2789 trimAgainstROI(ctx,crop, dst);
2790
Saurabh Shahab47c692014-02-12 18:45:57 -08002791 //If 2 pipes are staged on a single stage of a mixer, then the left pipe
2792 //should have a higher priority than the right one. Pipe priorities are
2793 //starting with VG0, VG1 ... , RGB0 ..., DMA1
Saurabh Shahab47c692014-02-12 18:45:57 -08002794
Saurabh Shahc62f3982014-03-05 14:28:26 -08002795 Overlay::PipeSpecs pipeSpecs;
2796 pipeSpecs.formatClass = isYuvBuffer(hnd) ?
2797 Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
2798 pipeSpecs.needsScaling = qhwc::needsScaling(layer);
2799 pipeSpecs.dpy = mDpy;
2800 pipeSpecs.fb = false;
2801
Saurabh Shahab47c692014-02-12 18:45:57 -08002802 //1 pipe by default for a layer
Saurabh Shahc62f3982014-03-05 14:28:26 -08002803 pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahab47c692014-02-12 18:45:57 -08002804 if(pipe_info.lIndex == ovutils::OV_INVALID) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002805 return false;
Saurabh Shahab47c692014-02-12 18:45:57 -08002806 }
2807
Saurabh Shahea7a01d2014-05-22 17:45:36 -07002808 /* Use 2 pipes IF
2809 a) Layer's crop width is > 2048 or
2810 b) Layer's dest width > 2048 or
2811 c) On primary, driver has indicated with caps to split always. This is
2812 based on an empirically derived value of panel height. Applied only
2813 if the layer's width is > mixer's width
2814 */
2815
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +05302816 MDPVersion& mdpHw = MDPVersion::getInstance();
Saurabh Shahea7a01d2014-05-22 17:45:36 -07002817 bool primarySplitAlways = (mDpy == HWC_DISPLAY_PRIMARY) and
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +05302818 mdpHw.isSrcSplitAlways();
Saurabh Shah514759d2014-11-11 18:02:24 -08002819 const uint32_t lSplit = getLeftSplit(ctx, mDpy);
2820 const uint32_t dstWidth = dst.right - dst.left;
2821 const uint32_t dstHeight = dst.bottom - dst.top;
Saurabh Shah05f4e222015-02-05 14:36:22 -08002822 uint32_t cropWidth = has90Transform(layer) ? crop.bottom - crop.top :
Saurabh Shah189f23d2014-09-26 17:21:00 -07002823 crop.right - crop.left;
Saurabh Shah05f4e222015-02-05 14:36:22 -08002824 uint32_t cropHeight = has90Transform(layer) ? crop.right - crop.left :
Saurabh Shah514759d2014-11-11 18:02:24 -08002825 crop.bottom - crop.top;
2826 //Approximation to actual clock, ignoring the common factors in pipe and
2827 //mixer cases like line_time
2828 const uint32_t layerClock = getLayerClock(dstWidth, dstHeight, cropHeight);
2829 const uint32_t mixerClock = lSplit;
Saurabh Shahea7a01d2014-05-22 17:45:36 -07002830
Saurabh Shah05f4e222015-02-05 14:36:22 -08002831 const uint32_t downscale = getRotDownscale(ctx, layer);
2832 if(downscale) {
2833 cropWidth /= downscale;
2834 cropHeight /= downscale;
2835 }
2836
Jeykumar Sankaran39305802014-12-12 17:55:57 -08002837 if(dstWidth > mdpHw.getMaxPipeWidth() or
2838 cropWidth > mdpHw.getMaxPipeWidth() or
Saurabh Shah514759d2014-11-11 18:02:24 -08002839 (primarySplitAlways and
2840 (cropWidth > lSplit or layerClock > mixerClock))) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002841 pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahab47c692014-02-12 18:45:57 -08002842 if(pipe_info.rIndex == ovutils::OV_INVALID) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002843 return false;
Saurabh Shahdd8237a2014-02-28 14:29:09 -08002844 }
2845
Jeykumar Sankaran89e23ab2015-01-28 15:57:46 -08002846 if(ctx->mOverlay->needsPrioritySwap(pipe_info.lIndex,
2847 pipe_info.rIndex)) {
Saurabh Shahdd8237a2014-02-28 14:29:09 -08002848 qhwc::swap(pipe_info.lIndex, pipe_info.rIndex);
Saurabh Shahab47c692014-02-12 18:45:57 -08002849 }
2850 }
2851
2852 return true;
2853}
2854
Saurabh Shahab47c692014-02-12 18:45:57 -08002855int MDPCompSrcSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
2856 PipeLayerPair& PipeLayerPair) {
2857 private_handle_t *hnd = (private_handle_t *)layer->handle;
2858 if(!hnd) {
2859 ALOGE("%s: layer handle is NULL", __FUNCTION__);
2860 return -1;
2861 }
2862 MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
2863 MdpPipeInfoSplit& mdp_info =
2864 *(static_cast<MdpPipeInfoSplit*>(PipeLayerPair.pipeInfo));
2865 Rotator **rot = &PipeLayerPair.rot;
2866 eZorder z = static_cast<eZorder>(mdp_info.zOrder);
Saurabh Shahab47c692014-02-12 18:45:57 -08002867 eDest lDest = mdp_info.lIndex;
2868 eDest rDest = mdp_info.rIndex;
2869 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
2870 hwc_rect_t dst = layer->displayFrame;
2871 int transform = layer->transform;
2872 eTransform orient = static_cast<eTransform>(transform);
Saurabh Shahab47c692014-02-12 18:45:57 -08002873 int rotFlags = ROT_FLAGS_NONE;
Sushil Chauhan65e26302015-01-14 10:48:57 -08002874 uint32_t format = ovutils::getMdpFormat(hnd->format, hnd->flags);
Saurabh Shahab47c692014-02-12 18:45:57 -08002875 Whf whf(getWidth(hnd), getHeight(hnd), format, hnd->size);
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002876 eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shahab47c692014-02-12 18:45:57 -08002877
2878 ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
2879 "dest_pipeR: %d",__FUNCTION__, layer, z, lDest, rDest);
2880
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08002881 if(qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() && !mDpy) {
2882 /* MDP driver crops layer coordinates against ROI in Non-Split
2883 * and Split MDP comp. But HWC needs to crop them for source split.
2884 * Reason: 1) Source split is efficient only when the final effective
2885 * load is distributed evenly across mixers.
2886 * 2) We have to know the effective width of the layer that
2887 * the ROI needs to find the no. of pipes the layer needs.
2888 */
2889 trimAgainstROI(ctx, crop, dst);
2890 }
2891
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002892 if(needs3DComposition(ctx, mDpy) &&
2893 get3DFormat(hnd) != HAL_NO_3D){
2894 return configure3DVideo(ctx, layer, mDpy, mdpFlags, z, lDest,
2895 rDest, &PipeLayerPair.rot);
2896 }
2897
Saurabh Shahab47c692014-02-12 18:45:57 -08002898 // Handle R/B swap
2899 if (layer->flags & HWC_FORMAT_RB_SWAP) {
2900 if (hnd->format == HAL_PIXEL_FORMAT_RGBA_8888)
2901 whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRA_8888);
2902 else if (hnd->format == HAL_PIXEL_FORMAT_RGBX_8888)
2903 whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
2904 }
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07002905 // update source crop and destination position of AIV video layer.
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07002906 if(ctx->listStats[mDpy].mAIVVideoMode && isYuvBuffer(hnd)) {
2907 updateCoordinates(ctx, crop, dst, mDpy);
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07002908 }
Ramkumar Radhakrishnana5c72872014-08-28 19:04:18 -07002909 /* Calculate the external display position based on MDP downscale,
2910 ActionSafe, and extorientation features. */
2911 calcExtDisplayPosition(ctx, hnd, mDpy, crop, dst, transform, orient);
Saurabh Shahab47c692014-02-12 18:45:57 -08002912
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07002913 int downscale = getRotDownscale(ctx, layer);
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07002914 setMdpFlags(ctx, layer, mdpFlags, downscale, transform);
Saurabh Shahab47c692014-02-12 18:45:57 -08002915
2916 if(lDest != OV_INVALID && rDest != OV_INVALID) {
2917 //Enable overfetch
Saurabh Shah97e2d802014-04-14 18:03:54 -07002918 setMdpFlags(mdpFlags, OV_MDSS_MDP_DUAL_PIPE);
Saurabh Shahab47c692014-02-12 18:45:57 -08002919 }
2920
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07002921 if((has90Transform(layer) or downscale) and isRotationDoable(ctx, hnd)) {
Saurabh Shahab47c692014-02-12 18:45:57 -08002922 (*rot) = ctx->mRotMgr->getNext();
2923 if((*rot) == NULL) return -1;
Saurabh Shah39240c92014-03-31 10:31:42 -07002924 ctx->mLayerRotMap[mDpy]->add(layer, *rot);
Saurabh Shah1bd5b6f2014-05-19 12:23:13 -07002925 //If the video is using a single pipe, enable BWC
2926 if(rDest == OV_INVALID) {
Saurabh Shahcd018352014-11-11 13:54:19 -08002927 BwcPM::setBwc(ctx, mDpy, hnd, crop, dst, transform, downscale,
2928 mdpFlags);
Saurabh Shah1bd5b6f2014-05-19 12:23:13 -07002929 }
Saurabh Shahab47c692014-02-12 18:45:57 -08002930 //Configure rotator for pre-rotation
Saurabh Shah97e2d802014-04-14 18:03:54 -07002931 if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale) < 0) {
Saurabh Shahab47c692014-02-12 18:45:57 -08002932 ALOGE("%s: configRotator failed!", __FUNCTION__);
2933 return -1;
2934 }
Saurabh Shah8ec9b5e2014-06-30 14:37:17 -07002935 updateSource(orient, whf, crop, *rot);
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07002936 rotFlags |= ovutils::ROT_PREROTATED;
Saurabh Shahab47c692014-02-12 18:45:57 -08002937 }
2938
2939 //If 2 pipes being used, divide layer into half, crop and dst
2940 hwc_rect_t cropL = crop;
2941 hwc_rect_t cropR = crop;
2942 hwc_rect_t dstL = dst;
2943 hwc_rect_t dstR = dst;
2944 if(lDest != OV_INVALID && rDest != OV_INVALID) {
2945 cropL.right = (crop.right + crop.left) / 2;
2946 cropR.left = cropL.right;
2947 sanitizeSourceCrop(cropL, cropR, hnd);
2948
Saurabh Shahb729b192014-08-15 18:04:24 -07002949 bool cropSwap = false;
Saurabh Shahab47c692014-02-12 18:45:57 -08002950 //Swap crops on H flip since 2 pipes are being used
2951 if((orient & OVERLAY_TRANSFORM_FLIP_H) && (*rot) == NULL) {
2952 hwc_rect_t tmp = cropL;
2953 cropL = cropR;
2954 cropR = tmp;
Saurabh Shahb729b192014-08-15 18:04:24 -07002955 cropSwap = true;
Saurabh Shahab47c692014-02-12 18:45:57 -08002956 }
2957
Saurabh Shahb729b192014-08-15 18:04:24 -07002958 //cropSwap trick: If the src and dst widths are both odd, let us say
2959 //2507, then splitting both into half would cause left width to be 1253
2960 //and right 1254. If crop is swapped because of H flip, this will cause
2961 //left crop width to be 1254, whereas left dst width remains 1253, thus
2962 //inducing a scaling that is unaccounted for. To overcome that we add 1
2963 //to the dst width if there is a cropSwap. So if the original width was
2964 //2507, the left dst width will be 1254. Even if the original width was
2965 //even for ex: 2508, the left dst width will still remain 1254.
2966 dstL.right = (dst.right + dst.left + cropSwap) / 2;
Saurabh Shahab47c692014-02-12 18:45:57 -08002967 dstR.left = dstL.right;
2968 }
2969
2970 //For the mdp, since either we are pre-rotating or MDP does flips
2971 orient = OVERLAY_TRANSFORM_0;
2972 transform = 0;
2973
2974 //configure left pipe
2975 if(lDest != OV_INVALID) {
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002976 PipeArgs pargL(mdpFlags, whf, z,
Saurabh Shahab47c692014-02-12 18:45:57 -08002977 static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
2978 (ovutils::eBlending) getBlending(layer->blending));
2979
2980 if(configMdp(ctx->mOverlay, pargL, orient,
2981 cropL, dstL, metadata, lDest) < 0) {
2982 ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
2983 return -1;
2984 }
2985 }
2986
2987 //configure right pipe
2988 if(rDest != OV_INVALID) {
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002989 PipeArgs pargR(mdpFlags, whf, z,
Saurabh Shahab47c692014-02-12 18:45:57 -08002990 static_cast<eRotFlags>(rotFlags),
2991 layer->planeAlpha,
2992 (ovutils::eBlending) getBlending(layer->blending));
2993 if(configMdp(ctx->mOverlay, pargR, orient,
2994 cropR, dstR, metadata, rDest) < 0) {
2995 ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
2996 return -1;
2997 }
2998 }
2999
3000 return 0;
3001}
3002
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -08003003bool MDPComp::getPartialUpdatePref(hwc_context_t *ctx) {
3004 Locker::Autolock _l(ctx->mDrawLock);
3005 const int fbNum = Overlay::getFbForDpy(Overlay::DPY_PRIMARY);
3006 char path[MAX_SYSFS_FILE_PATH];
3007 snprintf (path, sizeof(path), "sys/class/graphics/fb%d/dyn_pu", fbNum);
3008 int fd = open(path, O_RDONLY);
3009 if(fd < 0) {
3010 ALOGE("%s: Failed to open sysfd node: %s", __FUNCTION__, path);
3011 return -1;
3012 }
3013 char value[4];
3014 ssize_t size_read = read(fd, value, sizeof(value)-1);
3015 if(size_read <= 0) {
3016 ALOGE("%s: Failed to read sysfd node: %s", __FUNCTION__, path);
3017 close(fd);
3018 return -1;
3019 }
3020 close(fd);
3021 value[size_read] = '\0';
3022 return atoi(value);
3023}
3024
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003025int MDPComp::setPartialUpdatePref(hwc_context_t *ctx, bool enable) {
3026 Locker::Autolock _l(ctx->mDrawLock);
3027 const int fbNum = Overlay::getFbForDpy(Overlay::DPY_PRIMARY);
3028 char path[MAX_SYSFS_FILE_PATH];
3029 snprintf (path, sizeof(path), "sys/class/graphics/fb%d/dyn_pu", fbNum);
3030 int fd = open(path, O_WRONLY);
3031 if(fd < 0) {
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -08003032 ALOGE("%s: Failed to open sysfd node: %s", __FUNCTION__, path);
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003033 return -1;
3034 }
3035 char value[4];
3036 snprintf(value, sizeof(value), "%d", (int)enable);
3037 ssize_t ret = write(fd, value, strlen(value));
3038 if(ret <= 0) {
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -08003039 ALOGE("%s: Failed to write to sysfd nodes: %s", __FUNCTION__, path);
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003040 close(fd);
3041 return -1;
3042 }
3043 close(fd);
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003044 return 0;
3045}
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08003046
3047bool MDPComp::loadPerfLib() {
3048 char perfLibPath[PROPERTY_VALUE_MAX] = {0};
3049 bool success = false;
3050 if((property_get("ro.vendor.extension_library", perfLibPath, NULL) <= 0)) {
3051 ALOGE("vendor library not set in ro.vendor.extension_library");
3052 return false;
3053 }
3054
3055 sLibPerfHint = dlopen(perfLibPath, RTLD_NOW);
3056 if(sLibPerfHint) {
3057 *(void **)&sPerfLockAcquire = dlsym(sLibPerfHint, "perf_lock_acq");
3058 *(void **)&sPerfLockRelease = dlsym(sLibPerfHint, "perf_lock_rel");
3059 if (!sPerfLockAcquire || !sPerfLockRelease) {
3060 ALOGE("Failed to load symbols for perfLock");
3061 dlclose(sLibPerfHint);
3062 sLibPerfHint = NULL;
3063 return false;
3064 }
3065 success = true;
3066 ALOGI("Successfully Loaded perf hint API's");
3067 } else {
3068 ALOGE("Failed to open %s : %s", perfLibPath, dlerror());
3069 }
3070 return success;
3071}
3072
3073void MDPComp::setPerfHint(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
3074 if ((sPerfHintWindow < 0) || mDpy || !sLibPerfHint) {
3075 return;
3076 }
3077 static int count = sPerfHintWindow;
3078 static int perflockFlag = 0;
3079
3080 /* Send hint to mpctl when single layer is updated
3081 * for a successful number of windows. Hint release
3082 * happens immediately upon multiple layer update.
3083 */
3084 if (onlyVideosUpdating(ctx, list)) {
3085 if(count) {
3086 count--;
3087 }
3088 } else {
3089 if (perflockFlag) {
3090 perflockFlag = 0;
3091 sPerfLockRelease(sPerfLockHandle);
3092 }
3093 count = sPerfHintWindow;
3094 }
3095 if (count == 0 && !perflockFlag) {
3096 int perfHint = 0x4501; // 45-display layer hint, 01-Enable
3097 sPerfLockHandle = sPerfLockAcquire(0 /*handle*/, 0/*duration*/,
3098 &perfHint, sizeof(perfHint)/sizeof(int));
Arun Kumar K.R8b927022015-02-24 12:34:21 -08003099 if(sPerfLockHandle > 0) {
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08003100 perflockFlag = 1;
3101 }
3102 }
3103}
3104
Naseer Ahmed7c958d42012-07-31 18:57:03 -07003105}; //namespace
3106