blob: 1df423d834d74064ba16cc06b4a34d6de1d59f0e [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"
Arun Kumar K.R299bcda2014-12-18 19:36:40 -080021#include <dlfcn.h>
Tatenda Chipeperekwaaf2c0042014-09-17 12:55:01 -070022#include "hdmi.h"
Ramkumar Radhakrishnan47573e22012-11-07 11:36:41 -080023#include "qdMetaData.h"
Ramkumar Radhakrishnan288f8c72013-01-15 11:37:54 -080024#include "mdp_version.h"
Saurabh Shah2a4eb1b2013-07-22 16:33:23 -070025#include "hwc_fbupdate.h"
Saurabh Shaha9da08f2013-07-03 13:27:53 -070026#include "hwc_ad.h"
Saurabh Shahacf10202013-02-26 10:15:15 -080027#include <overlayRotator.h>
Arun Kumar K.R00b84792015-03-27 11:28:36 -070028#include <overlayCursor.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;
radhakrishna35e33072015-04-08 17:20:43 +053058float MDPComp::sDownscaleThreshold = 1.0;
Arun Kumar K.R299bcda2014-12-18 19:36:40 -080059
Saurabh Shah8cc77712015-03-31 10:48:51 -070060enum AllocOrder { FORMAT_YUV, FORMAT_RGB, FORMAT_MAX };
61
Saurabh Shah88e4d272013-09-03 13:31:29 -070062MDPComp* MDPComp::getObject(hwc_context_t *ctx, const int& dpy) {
Saurabh Shah60e8bde2014-04-30 14:46:03 -070063 if(qdutils::MDPVersion::getInstance().isSrcSplit()) {
64 sSrcSplitEnabled = true;
65 return new MDPCompSrcSplit(dpy);
66 } else if(isDisplaySplit(ctx, dpy)) {
Saurabh Shah88e4d272013-09-03 13:31:29 -070067 return new MDPCompSplit(dpy);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -080068 }
Saurabh Shah88e4d272013-09-03 13:31:29 -070069 return new MDPCompNonSplit(dpy);
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -080070}
71
Saurabh Shahac279de2015-05-21 18:56:58 -070072MDPComp::MDPComp(int dpy) : mDpy(dpy), mModeOn(false), mPrevModeOn(false) {
73};
Jeykumar Sankaran85977e32013-02-25 17:06:08 -080074
Jeykumar Sankaran6850ac62014-05-27 10:07:26 -070075void MDPComp::dump(android::String8& buf, hwc_context_t *ctx)
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -080076{
Jeykumar Sankaran3c6bb042013-08-15 14:01:04 -070077 if(mCurrentFrame.layerCount > MAX_NUM_APP_LAYERS)
78 return;
79
Jeykumar Sankaran85977e32013-02-25 17:06:08 -080080 dumpsys_log(buf,"HWC Map for Dpy: %s \n",
Jeykumar Sankaran27dee262013-08-01 17:09:54 -070081 (mDpy == 0) ? "\"PRIMARY\"" :
82 (mDpy == 1) ? "\"EXTERNAL\"" : "\"VIRTUAL\"");
Saurabh Shahe9bc60f2013-08-29 12:58:06 -070083 dumpsys_log(buf,"CURR_FRAME: layerCount:%2d mdpCount:%2d "
Arun Kumar K.R00b84792015-03-27 11:28:36 -070084 "fbCount:%2d dropCount:%2d\n", mCurrentFrame.layerCount,
85 mCurrentFrame.mdpCount, mCurrentFrame.fbCount, mCurrentFrame.dropCount);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -080086 dumpsys_log(buf,"needsFBRedraw:%3s pipesUsed:%2d MaxPipesPerMixer: %d \n",
87 (mCurrentFrame.needsRedraw? "YES" : "NO"),
88 mCurrentFrame.mdpCount, sMaxPipesPerMixer);
Jeykumar Sankaran6850ac62014-05-27 10:07:26 -070089 if(isDisplaySplit(ctx, mDpy)) {
90 dumpsys_log(buf, "Programmed ROI's: Left: [%d, %d, %d, %d] "
91 "Right: [%d, %d, %d, %d] \n",
92 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
93 ctx->listStats[mDpy].lRoi.right,
94 ctx->listStats[mDpy].lRoi.bottom,
95 ctx->listStats[mDpy].rRoi.left,ctx->listStats[mDpy].rRoi.top,
96 ctx->listStats[mDpy].rRoi.right,
97 ctx->listStats[mDpy].rRoi.bottom);
98 } else {
99 dumpsys_log(buf, "Programmed ROI: [%d, %d, %d, %d] \n",
100 ctx->listStats[mDpy].lRoi.left,ctx->listStats[mDpy].lRoi.top,
101 ctx->listStats[mDpy].lRoi.right,
102 ctx->listStats[mDpy].lRoi.bottom);
103 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800104 dumpsys_log(buf," --------------------------------------------- \n");
105 dumpsys_log(buf," listIdx | cached? | mdpIndex | comptype | Z \n");
106 dumpsys_log(buf," --------------------------------------------- \n");
107 for(int index = 0; index < mCurrentFrame.layerCount; index++ )
108 dumpsys_log(buf," %7d | %7s | %8d | %9s | %2d \n",
109 index,
110 (mCurrentFrame.isFBComposed[index] ? "YES" : "NO"),
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700111 mCurrentFrame.layerToMDP[index],
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800112 (mCurrentFrame.isFBComposed[index] ?
Arun Kumar K.R00b84792015-03-27 11:28:36 -0700113 (mCurrentFrame.drop[index] ?
114 ((mCurrentFrame.hwCursorIndex == index) ? "CURSOR": "DROP"):
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700115 (mCurrentFrame.needsRedraw ? "GLES" : "CACHE")) : "MDP"),
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800116 (mCurrentFrame.isFBComposed[index] ? mCurrentFrame.fbZ :
117 mCurrentFrame.mdpToLayer[mCurrentFrame.layerToMDP[index]].pipeInfo->zOrder));
118 dumpsys_log(buf,"\n");
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800119}
120
121bool MDPComp::init(hwc_context_t *ctx) {
122
123 if(!ctx) {
124 ALOGE("%s: Invalid hwc context!!",__FUNCTION__);
125 return false;
126 }
127
Saurabh Shah59562ff2014-09-30 16:13:12 -0700128 char property[PROPERTY_VALUE_MAX] = {0};
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800129
130 sEnabled = false;
Dileep Kumar Reddid8e601d2014-10-28 18:20:43 +0530131 if((ctx->mMDP.version >= qdutils::MDP_V4_0) &&
132 (property_get("persist.hwc.mdpcomp.enable", property, NULL) > 0) &&
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800133 (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
134 (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800135 sEnabled = true;
136 }
137
Jeykumar Sankaran24c199d2013-05-24 09:40:36 -0700138 sEnableMixedMode = true;
139 if((property_get("debug.mdpcomp.mixedmode.disable", property, NULL) > 0) &&
140 (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
141 (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
142 sEnableMixedMode = false;
143 }
144
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700145 qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
146
Saurabh Shah2fd8a252014-12-05 13:49:53 -0800147 sMaxPipesPerMixer = (int)mdpVersion.getBlendStages();
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700148 if(property_get("persist.hwc.mdpcomp.maxpermixer", property, "-1") > 0) {
Saurabh Shah85234ec2013-04-12 17:09:00 -0700149 int val = atoi(property);
150 if(val >= 0)
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700151 sMaxPipesPerMixer = min(val, sMaxPipesPerMixer);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800152 }
153
Saurabh Shahacec8e42014-11-25 11:07:04 -0800154 /* Maximum layers allowed to use MDP on secondary panels. If property
155 * doesn't exist, default to 1. Using the property it can be set to 0 or
156 * more.
157 */
158 if(property_get("persist.hwc.maxseclayers", property, "1") > 0) {
159 int val = atoi(property);
160 sMaxSecLayers = (val >= 0) ? val : 1;
161 sMaxSecLayers = min(sMaxSecLayers, sMaxPipesPerMixer);
162 }
163
Naseer Ahmedf40f2c82013-08-14 16:42:40 -0400164 if(ctx->mMDP.panel != MIPI_CMD_PANEL) {
Saurabh Shah59562ff2014-09-30 16:13:12 -0700165 sIdleInvalidator = IdleInvalidator::getInstance();
166 if(sIdleInvalidator->init(timeout_handler, ctx) < 0) {
167 delete sIdleInvalidator;
168 sIdleInvalidator = NULL;
Naseer Ahmedf40f2c82013-08-14 16:42:40 -0400169 }
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800170 }
radhakrishnac9a67412013-09-25 17:40:42 +0530171
Saurabh Shah7c727642014-06-02 15:47:14 -0700172 if(!qdutils::MDPVersion::getInstance().isSrcSplit() &&
Saurabh Shahc46cf9d2014-07-02 15:22:34 -0700173 !qdutils::MDPVersion::getInstance().isRotDownscaleEnabled() &&
Saurabh Shah7c727642014-06-02 15:47:14 -0700174 property_get("persist.mdpcomp.4k2kSplit", property, "0") > 0 &&
175 (!strncmp(property, "1", PROPERTY_VALUE_MAX) ||
176 !strncasecmp(property,"true", PROPERTY_VALUE_MAX))) {
Raj Kamal389d6e32014-08-04 14:43:24 +0530177 sEnableYUVsplit = true;
radhakrishnac9a67412013-09-25 17:40:42 +0530178 }
Sushil Chauhandefd3522014-05-13 18:17:12 -0700179
Dileep Kumar Reddic6ef3472014-09-24 19:07:08 +0530180 bool defaultPTOR = false;
181 //Enable PTOR when "persist.hwc.ptor.enable" is not defined for
Prabhanjan Kandulafc541b32015-03-30 20:56:16 +0530182 //Bear family targets by default
Dileep Kumar Reddic6ef3472014-09-24 19:07:08 +0530183 if((property_get("persist.hwc.ptor.enable", property, NULL) <= 0) &&
184 (qdutils::MDPVersion::getInstance().is8x16() ||
Prabhanjan Kandulafc541b32015-03-30 20:56:16 +0530185 qdutils::MDPVersion::getInstance().is8x39() ||
186 qdutils::MDPVersion::getInstance().is8x52())) {
Dileep Kumar Reddic6ef3472014-09-24 19:07:08 +0530187 defaultPTOR = true;
188 }
189
190 if (defaultPTOR || (!strncasecmp(property, "true", PROPERTY_VALUE_MAX)) ||
191 (!strncmp(property, "1", PROPERTY_VALUE_MAX ))) {
Sushil Chauhandefd3522014-05-13 18:17:12 -0700192 ctx->mCopyBit[HWC_DISPLAY_PRIMARY] = new CopyBit(ctx,
193 HWC_DISPLAY_PRIMARY);
194 }
195
Dileep Kumar Reddi4070e932014-09-30 09:00:57 +0530196 if((property_get("persist.mdp3.partialUpdate", property, NULL) <= 0) &&
197 (ctx->mMDP.version == qdutils::MDP_V3_0_5)) {
198 enablePartialUpdateForMDP3 = true;
199 }
200
201 if(!enablePartialUpdateForMDP3 &&
202 (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
203 (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
204 enablePartialUpdateForMDP3 = true;
205 }
206
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -0800207 sIsPartialUpdateActive = getPartialUpdatePref(ctx);
208
Arun Kumar K.R299bcda2014-12-18 19:36:40 -0800209 if(property_get("persist.mdpcomp_perfhint", property, "-1") > 0) {
210 int val = atoi(property);
211 if(val > 0 && loadPerfLib()) {
212 sPerfHintWindow = val;
213 ALOGI("PerfHintWindow = %d", sPerfHintWindow);
214 }
215 }
216
radhakrishna35e33072015-04-08 17:20:43 +0530217 if(property_get("persist.hwc.downscale_threshold", property, "1.0") > 0) {
218 sDownscaleThreshold = (float)atof(property);
219 }
220
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700221 return true;
222}
223
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800224void MDPComp::reset(hwc_context_t *ctx) {
225 const int numLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shah2a4eb1b2013-07-22 16:33:23 -0700226 mCurrentFrame.reset(numLayers);
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800227 ctx->mOverlay->clear(mDpy);
228 ctx->mLayerRotMap[mDpy]->clear();
Saurabh Shah2a4eb1b2013-07-22 16:33:23 -0700229}
230
Raj Kamal4393eaa2014-06-06 13:45:20 +0530231void MDPComp::reset() {
Raj Kamalfdfdddf2015-03-16 21:59:25 +0530232 mPrevModeOn = mModeOn;
Raj Kamal4393eaa2014-06-06 13:45:20 +0530233 mModeOn = false;
234}
235
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700236void MDPComp::timeout_handler(void *udata) {
237 struct hwc_context_t* ctx = (struct hwc_context_t*)(udata);
Raj Kamalfdfdddf2015-03-16 21:59:25 +0530238 bool handleTimeout = false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700239
240 if(!ctx) {
241 ALOGE("%s: received empty data in timer callback", __FUNCTION__);
242 return;
243 }
Raj Kamal58b31a02014-12-16 15:53:53 +0530244
245 ctx->mDrawLock.lock();
Raj Kamalfdfdddf2015-03-16 21:59:25 +0530246
247 /* Handle timeout event only if the previous composition
248 on any display is MDP or MIXED*/
249 for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
250 if(ctx->mMDPComp[i])
251 handleTimeout =
252 ctx->mMDPComp[i]->isMDPComp() || handleTimeout;
253 }
254
255 if(!handleTimeout) {
Ramkumar Radhakrishnan92abb4f2014-02-06 21:31:29 -0800256 ALOGD_IF(isDebug(), "%s:Do not handle this timeout", __FUNCTION__);
Raj Kamal58b31a02014-12-16 15:53:53 +0530257 ctx->mDrawLock.unlock();
Ramkumar Radhakrishnan92abb4f2014-02-06 21:31:29 -0800258 return;
259 }
Jesse Hall3be78d92012-08-21 15:12:23 -0700260 if(!ctx->proc) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700261 ALOGE("%s: HWC proc not registered", __FUNCTION__);
Raj Kamal58b31a02014-12-16 15:53:53 +0530262 ctx->mDrawLock.unlock();
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700263 return;
264 }
265 sIdleFallBack = true;
Raj Kamal58b31a02014-12-16 15:53:53 +0530266 ctx->mDrawLock.unlock();
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700267 /* Trigger SF to redraw the current frame */
Jesse Hall3be78d92012-08-21 15:12:23 -0700268 ctx->proc->invalidate(ctx->proc);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700269}
270
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700271void MDPComp::setMaxPipesPerMixer(const uint32_t value) {
272 qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
Saurabh Shah2fd8a252014-12-05 13:49:53 -0800273 uint32_t maxSupported = (int)mdpVersion.getBlendStages();
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700274 if(value > maxSupported) {
275 ALOGW("%s: Input exceeds max value supported. Setting to"
276 "max value: %d", __FUNCTION__, maxSupported);
277 }
278 sMaxPipesPerMixer = min(value, maxSupported);
279}
280
Saurabh Shah59562ff2014-09-30 16:13:12 -0700281void MDPComp::setIdleTimeout(const uint32_t& timeout) {
282 enum { ONE_REFRESH_PERIOD_MS = 17, ONE_BILLION_MS = 1000000000 };
283
284 if(sIdleInvalidator) {
285 if(timeout <= ONE_REFRESH_PERIOD_MS) {
286 //If the specified timeout is < 1 draw cycle worth, "virtually"
287 //disable idle timeout. The ideal way for clients to disable
288 //timeout is to set it to 0
289 sIdleInvalidator->setIdleTimeout(ONE_BILLION_MS);
290 ALOGI("Disabled idle timeout");
291 return;
292 }
293 sIdleInvalidator->setIdleTimeout(timeout);
294 ALOGI("Idle timeout set to %u", timeout);
295 } else {
296 ALOGW("Cannot set idle timeout, IdleInvalidator not enabled");
297 }
298}
299
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800300void MDPComp::setMDPCompLayerFlags(hwc_context_t *ctx,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800301 hwc_display_contents_1_t* list) {
302 LayerProp *layerProp = ctx->layerProp[mDpy];
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800303
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800304 for(int index = 0; index < ctx->listStats[mDpy].numAppLayers; index++) {
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800305 hwc_layer_1_t* layer = &(list->hwLayers[index]);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800306 if(!mCurrentFrame.isFBComposed[index]) {
307 layerProp[index].mFlags |= HWC_MDPCOMP;
308 layer->compositionType = HWC_OVERLAY;
309 layer->hints |= HWC_HINT_CLEAR_FB;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800310 } else {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700311 /* Drop the layer when its already present in FB OR when it lies
312 * outside frame's ROI */
313 if(!mCurrentFrame.needsRedraw || mCurrentFrame.drop[index]) {
Arun Kumar K.R00b84792015-03-27 11:28:36 -0700314 if(index == mCurrentFrame.hwCursorIndex) {
315 layer->compositionType = HWC_CURSOR_OVERLAY;
316 } else {
317 layer->compositionType = HWC_OVERLAY;
318 }
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700319 }
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800320 }
321 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700322}
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500323
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800324void MDPComp::setRedraw(hwc_context_t *ctx,
325 hwc_display_contents_1_t* list) {
326 mCurrentFrame.needsRedraw = false;
327 if(!mCachedFrame.isSameFrame(mCurrentFrame, list) ||
328 (list->flags & HWC_GEOMETRY_CHANGED) ||
329 isSkipPresent(ctx, mDpy)) {
330 mCurrentFrame.needsRedraw = true;
331 }
332}
333
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800334MDPComp::FrameInfo::FrameInfo() {
Saurabh Shahf7fad542014-08-14 10:11:36 -0700335 memset(&mdpToLayer, 0, sizeof(mdpToLayer));
Saurabh Shahaa236822013-04-24 18:07:26 -0700336 reset(0);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800337}
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800338
Saurabh Shahaa236822013-04-24 18:07:26 -0700339void MDPComp::FrameInfo::reset(const int& numLayers) {
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700340 for(int i = 0 ; i < MAX_NUM_BLEND_STAGES; i++ ) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800341 if(mdpToLayer[i].pipeInfo) {
342 delete mdpToLayer[i].pipeInfo;
343 mdpToLayer[i].pipeInfo = NULL;
344 //We dont own the rotator
345 mdpToLayer[i].rot = NULL;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800346 }
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800347 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800348
349 memset(&mdpToLayer, 0, sizeof(mdpToLayer));
350 memset(&layerToMDP, -1, sizeof(layerToMDP));
Saurabh Shahaa236822013-04-24 18:07:26 -0700351 memset(&isFBComposed, 1, sizeof(isFBComposed));
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800352
Saurabh Shahaa236822013-04-24 18:07:26 -0700353 layerCount = numLayers;
354 fbCount = numLayers;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800355 mdpCount = 0;
Saurabh Shah2f3895f2013-05-02 10:13:31 -0700356 needsRedraw = true;
Saurabh Shahd53bc5f2014-02-05 10:17:43 -0800357 fbZ = -1;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800358}
359
Saurabh Shahaa236822013-04-24 18:07:26 -0700360void MDPComp::FrameInfo::map() {
361 // populate layer and MDP maps
362 int mdpIdx = 0;
363 for(int idx = 0; idx < layerCount; idx++) {
364 if(!isFBComposed[idx]) {
365 mdpToLayer[mdpIdx].listIndex = idx;
366 layerToMDP[idx] = mdpIdx++;
367 }
368 }
369}
370
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800371MDPComp::LayerCache::LayerCache() {
372 reset();
373}
374
375void MDPComp::LayerCache::reset() {
Saurabh Shahaa236822013-04-24 18:07:26 -0700376 memset(&hnd, 0, sizeof(hnd));
Prabhanjan Kandula2243aa62013-10-24 12:58:55 +0530377 memset(&isFBComposed, true, sizeof(isFBComposed));
378 memset(&drop, false, sizeof(drop));
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800379 layerCount = 0;
Saurabh Shahaa236822013-04-24 18:07:26 -0700380}
381
382void MDPComp::LayerCache::cacheAll(hwc_display_contents_1_t* list) {
Praveena Pachipulusud9443c72014-02-17 10:42:28 +0530383 const int numAppLayers = (int)list->numHwLayers - 1;
Saurabh Shahaa236822013-04-24 18:07:26 -0700384 for(int i = 0; i < numAppLayers; i++) {
385 hnd[i] = list->hwLayers[i].handle;
386 }
387}
388
389void MDPComp::LayerCache::updateCounts(const FrameInfo& curFrame) {
Saurabh Shahaa236822013-04-24 18:07:26 -0700390 layerCount = curFrame.layerCount;
Prabhanjan Kandula2243aa62013-10-24 12:58:55 +0530391 memcpy(&isFBComposed, &curFrame.isFBComposed, sizeof(isFBComposed));
392 memcpy(&drop, &curFrame.drop, sizeof(drop));
393}
394
Jeykumar Sankaran988d3682013-11-15 11:57:16 -0800395bool MDPComp::LayerCache::isSameFrame(const FrameInfo& curFrame,
396 hwc_display_contents_1_t* list) {
Prabhanjan Kandula2243aa62013-10-24 12:58:55 +0530397 if(layerCount != curFrame.layerCount)
398 return false;
399 for(int i = 0; i < curFrame.layerCount; i++) {
400 if((curFrame.isFBComposed[i] != isFBComposed[i]) ||
401 (curFrame.drop[i] != drop[i])) {
402 return false;
403 }
Jeykumar Sankaran988d3682013-11-15 11:57:16 -0800404 if(curFrame.isFBComposed[i] &&
405 (hnd[i] != list->hwLayers[i].handle)){
406 return false;
407 }
Prabhanjan Kandula2243aa62013-10-24 12:58:55 +0530408 }
409 return true;
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800410}
411
Raj Kamalfdfdddf2015-03-16 21:59:25 +0530412bool MDPComp::LayerCache::isSameFrame(hwc_context_t *ctx, int dpy,
413 hwc_display_contents_1_t* list) {
414
415 if(layerCount != ctx->listStats[dpy].numAppLayers)
416 return false;
417
418 if((list->flags & HWC_GEOMETRY_CHANGED) ||
419 isSkipPresent(ctx, dpy)) {
420 return false;
421 }
422
423 for(int i = 0; i < layerCount; i++) {
424 if(hnd[i] != list->hwLayers[i].handle)
425 return false;
426 }
427
428 return true;
429}
430
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700431bool MDPComp::isSupportedForMDPComp(hwc_context_t *ctx, hwc_layer_1_t* layer) {
432 private_handle_t *hnd = (private_handle_t *)layer->handle;
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800433 if((has90Transform(layer) and (not isRotationDoable(ctx, hnd))) ||
Raj Kamal1179d9c2014-10-28 15:31:35 +0530434 (not isValidDimension(ctx,layer)) ||
435 isSkipLayer(layer)) {
436 //More conditions here, sRGB+Blend etc
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700437 return false;
438 }
radhakrishna35e33072015-04-08 17:20:43 +0530439
440 //In targets with fewer pipes, frequent composition switch between MDP/GPU
441 //can happen for a layer due to lack of pipes. When this switch happens
442 //continuously for RGB downscaled layer with downscale greater than
443 //threshold, it appears as flicker as output
444 //of MDP and GPU are different as they use different filters for downscale.
445 //To avoid this flicker, punt RGB downscaled layer with downscale greater
446 //than threshold value to GPU always.
447 if((sDownscaleThreshold > 1.0)) {
448 if(((not isYuvBuffer(hnd))
449 and (not isDownscaleWithinThreshold(layer,
450 sDownscaleThreshold)))) {
451 ALOGD_IF(isDebug(), "%s: required downscale is greater than \
452 threshold %f", __FUNCTION__, sDownscaleThreshold);
453 return false;
454 }
455 }
456
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700457 return true;
458}
459
Sravan Kumar D.V.Nad5d9292013-04-24 14:23:04 +0530460bool MDPComp::isValidDimension(hwc_context_t *ctx, hwc_layer_1_t *layer) {
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800461 private_handle_t *hnd = (private_handle_t *)layer->handle;
462
463 if(!hnd) {
Sushil Chauhan897a9c32013-07-18 11:09:55 -0700464 if (layer->flags & HWC_COLOR_FILL) {
465 // Color layer
466 return true;
467 }
Ramkumar Radhakrishnan0cabf212014-09-08 20:07:49 -0700468 ALOGD_IF(isDebug(), "%s: layer handle is NULL", __FUNCTION__);
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800469 return false;
470 }
471
Naseer Ahmede850a802013-09-06 13:12:52 -0400472 //XXX: Investigate doing this with pixel phase on MDSS
Arun Kumar K.R7b1f1522015-06-01 19:55:47 -0700473 if((!isSecureBuffer(hnd) || !isProtectedBuffer(hnd)) &&
474 isNonIntegralSourceCrop(layer->sourceCropf)) {
Naseer Ahmede850a802013-09-06 13:12:52 -0400475 return false;
Arun Kumar K.R7b1f1522015-06-01 19:55:47 -0700476 }
Naseer Ahmede850a802013-09-06 13:12:52 -0400477
Saurabh Shah62e1d732013-09-17 10:44:05 -0700478 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
Saurabh Shah4fdde762013-04-30 18:47:33 -0700479 hwc_rect_t dst = layer->displayFrame;
Saurabh Shahb6810df2014-06-17 16:00:22 -0700480 bool rotated90 = (bool)(layer->transform & HAL_TRANSFORM_ROT_90);
Saurabh Shahe28a4022014-06-13 11:41:13 -0700481 int crop_w = rotated90 ? crop.bottom - crop.top : crop.right - crop.left;
482 int crop_h = rotated90 ? crop.right - crop.left : crop.bottom - crop.top;
Saurabh Shah4fdde762013-04-30 18:47:33 -0700483 int dst_w = dst.right - dst.left;
484 int dst_h = dst.bottom - dst.top;
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800485 float w_scale = ((float)crop_w / (float)dst_w);
486 float h_scale = ((float)crop_h / (float)dst_h);
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530487 MDPVersion& mdpHw = MDPVersion::getInstance();
Saurabh Shah4fdde762013-04-30 18:47:33 -0700488
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800489 /* Workaround for MDP HW limitation in DSI command mode panels where
490 * FPS will not go beyond 30 if buffers on RGB pipes are of width or height
491 * less than 5 pixels
Sravan Kumar D.V.Nad5d9292013-04-24 14:23:04 +0530492 * There also is a HW limilation in MDP, minimum block size is 2x2
493 * Fallback to GPU if height is less than 2.
494 */
Saurabh Shah189f23d2014-09-26 17:21:00 -0700495 if(mdpHw.hasMinCropWidthLimitation() and (crop_w < 5 or crop_h < 5))
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800496 return false;
497
Ramkumar Radhakrishnan1a763e92015-03-19 16:46:46 -0700498 /* crop_w and crop_h should be even for yuv layer, so fallback to GPU for
499 * those cases
500 */
501 if(isYuvBuffer(hnd) && (crop_w < 2 || crop_h < 2)) {
502 return false;
503 }
504
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800505 if((w_scale > 1.0f) || (h_scale > 1.0f)) {
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530506 const uint32_t maxMDPDownscale = mdpHw.getMaxMDPDownscale();
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800507 const float w_dscale = w_scale;
508 const float h_dscale = h_scale;
509
Jeykumar Sankaran1706a772013-11-27 12:55:19 -0800510 if(ctx->mMDP.version >= qdutils::MDSS_V5) {
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700511
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530512 if(!mdpHw.supportsDecimation()) {
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700513 /* On targets that doesnt support Decimation (eg.,8x26)
514 * maximum downscale support is overlay pipe downscale.
515 */
Jeykumar Sankaran39305802014-12-12 17:55:57 -0800516 if(crop_w > (int) mdpHw.getMaxPipeWidth() ||
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530517 w_dscale > maxMDPDownscale ||
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700518 h_dscale > maxMDPDownscale)
Jeykumar Sankaran1706a772013-11-27 12:55:19 -0800519 return false;
520 } else {
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700521 // Decimation on macrotile format layers is not supported.
522 if(isTileRendered(hnd)) {
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530523 /* Bail out if
524 * 1. Src crop > Mixer limit on nonsplit MDPComp
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700525 * 2. exceeds maximum downscale limit
526 */
Jeykumar Sankaran39305802014-12-12 17:55:57 -0800527 if(((crop_w > (int) mdpHw.getMaxPipeWidth()) &&
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530528 !sSrcSplitEnabled) ||
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700529 w_dscale > maxMDPDownscale ||
530 h_dscale > maxMDPDownscale) {
531 return false;
532 }
533 } else if(w_dscale > 64 || h_dscale > 64)
Jeykumar Sankaran1706a772013-11-27 12:55:19 -0800534 return false;
535 }
536 } else { //A-family
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700537 if(w_dscale > maxMDPDownscale || h_dscale > maxMDPDownscale)
Saurabh Shah4fdde762013-04-30 18:47:33 -0700538 return false;
539 }
Saurabh Shah4fdde762013-04-30 18:47:33 -0700540 }
541
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800542 if((w_scale < 1.0f) || (h_scale < 1.0f)) {
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530543 const uint32_t upscale = mdpHw.getMaxMDPUpscale();
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800544 const float w_uscale = 1.0f / w_scale;
545 const float h_uscale = 1.0f / h_scale;
546
547 if(w_uscale > upscale || h_uscale > upscale)
548 return false;
549 }
550
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800551 return true;
552}
553
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800554bool MDPComp::isFrameDoable(hwc_context_t *ctx) {
Saurabh Shahaa236822013-04-24 18:07:26 -0700555 bool ret = true;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800556
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800557 if(!isEnabled()) {
558 ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
Saurabh Shahaa236822013-04-24 18:07:26 -0700559 ret = false;
Raj Kamal83605462015-05-27 11:30:16 +0530560 } else if (ctx->isDMAStateChanging) {
561 // Bail out if a padding round has been invoked in order to switch DMA
562 // state to block mode. We need this to cater for the case when a layer
563 // requires rotation in the current frame.
564 ALOGD_IF(isDebug(), "%s: padding round invoked to switch DMA state",
565 __FUNCTION__);
566 ret = false;
Saurabh Shah19740d02015-04-10 10:05:42 -0700567 } else if(ctx->mVideoTransFlag && isSecondaryConnected(ctx)) {
Saurabh Shahd4e65852013-06-17 11:33:53 -0700568 //1 Padding round to shift pipes across mixers
569 ALOGD_IF(isDebug(),"%s: MDP Comp. video transition padding round",
570 __FUNCTION__);
571 ret = false;
Raj Kamalc0d34242015-03-17 20:53:14 +0530572 } else if((qdutils::MDPVersion::getInstance().is8x26() ||
573 qdutils::MDPVersion::getInstance().is8x16() ||
Prabhanjan Kandulafc541b32015-03-30 20:56:16 +0530574 qdutils::MDPVersion::getInstance().is8x39() ||
575 qdutils::MDPVersion::getInstance().is8x52()) &&
Raj Kamalc0d34242015-03-17 20:53:14 +0530576 !mDpy && isSecondaryAnimating(ctx) &&
577 isYuvPresent(ctx,HWC_DISPLAY_VIRTUAL)) {
578 ALOGD_IF(isDebug(),"%s: Display animation in progress",
579 __FUNCTION__);
580 ret = false;
Ramkumar Radhakrishnanf26fe9e2014-09-09 13:47:54 -0700581 } else if(qdutils::MDPVersion::getInstance().getTotalPipes() < 8) {
582 /* TODO: freeing up all the resources only for the targets having total
583 number of pipes < 8. Need to analyze number of VIG pipes used
584 for primary in previous draw cycle and accordingly decide
585 whether to fall back to full GPU comp or video only comp
586 */
587 if(isSecondaryConfiguring(ctx)) {
588 ALOGD_IF( isDebug(),"%s: External Display connection is pending",
589 __FUNCTION__);
590 ret = false;
591 } else if(ctx->isPaddingRound) {
592 ALOGD_IF(isDebug(), "%s: padding round invoked for dpy %d",
593 __FUNCTION__,mDpy);
594 ret = false;
595 }
Saurabh Shah0ceeb6a2013-04-23 10:46:07 -0700596 }
Tatenda Chipeperekwadc8d7082014-11-04 16:41:50 -0800597
Saurabh Shahaa236822013-04-24 18:07:26 -0700598 return ret;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800599}
600
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800601void MDPCompNonSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect &crop,
602 hwc_rect &dst) {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800603 hwc_rect_t roi = ctx->listStats[mDpy].lRoi;
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800604 dst = getIntersection(dst, roi);
605 crop = dst;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800606}
607
608/* 1) Identify layers that are not visible or lying outside the updating ROI and
609 * drop them from composition.
610 * 2) If we have a scaling layer which needs cropping against generated
611 * ROI, reset ROI to full resolution. */
612bool MDPCompNonSplit::validateAndApplyROI(hwc_context_t *ctx,
613 hwc_display_contents_1_t* list) {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700614 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800615 hwc_rect_t visibleRect = ctx->listStats[mDpy].lRoi;
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800616
617 for(int i = numAppLayers - 1; i >= 0; i--){
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800618 if(!isValidRect(visibleRect)) {
619 mCurrentFrame.drop[i] = true;
620 mCurrentFrame.dropCount++;
Jeykumar Sankaran0b961452014-01-21 17:26:12 -0800621 continue;
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800622 }
623
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700624 const hwc_layer_1_t* layer = &list->hwLayers[i];
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700625 hwc_rect_t dstRect = layer->displayFrame;
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800626 hwc_rect_t res = getIntersection(visibleRect, dstRect);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700627
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700628 if(!isValidRect(res)) {
629 mCurrentFrame.drop[i] = true;
630 mCurrentFrame.dropCount++;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800631 } else {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700632 /* Reset frame ROI when any layer which needs scaling also needs ROI
633 * cropping */
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800634 if(!isSameRect(res, dstRect) && needsScaling (layer)) {
Arpita Banerjeed8965982013-11-08 17:27:33 -0800635 ALOGI("%s: Resetting ROI due to scaling", __FUNCTION__);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700636 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
637 mCurrentFrame.dropCount = 0;
638 return false;
639 }
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800640
Jeykumar Sankaran0b961452014-01-21 17:26:12 -0800641 /* deduct any opaque region from visibleRect */
radhakrishna4efbdd62014-11-03 13:19:27 +0530642 if (layer->blending == HWC_BLENDING_NONE &&
643 layer->planeAlpha == 0xFF)
Jeykumar Sankaran0b961452014-01-21 17:26:12 -0800644 visibleRect = deductRect(visibleRect, res);
645 }
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700646 }
647 return true;
648}
649
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800650/* Calculate ROI for the frame by accounting all the layer's dispalyFrame which
651 * are updating. If DirtyRegion is applicable, calculate it by accounting all
652 * the changing layer's dirtyRegion. */
653void MDPCompNonSplit::generateROI(hwc_context_t *ctx,
654 hwc_display_contents_1_t* list) {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700655 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800656 if(!canPartialUpdate(ctx, list))
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700657 return;
658
659 struct hwc_rect roi = (struct hwc_rect){0, 0, 0, 0};
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800660 hwc_rect fullFrame = (struct hwc_rect) {0, 0,(int)ctx->dpyAttr[mDpy].xres,
661 (int)ctx->dpyAttr[mDpy].yres};
662
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700663 for(int index = 0; index < numAppLayers; index++ ) {
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800664 hwc_layer_1_t* layer = &list->hwLayers[index];
665 if ((mCachedFrame.hnd[index] != layer->handle) ||
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800666 isYuvBuffer((private_handle_t *)layer->handle)) {
Jeykumar Sankaran455678c2014-05-30 10:22:38 -0700667 hwc_rect_t dst = layer->displayFrame;
668 hwc_rect_t updatingRect = dst;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800669
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800670#ifdef QCOM_BSP
Dileep Kumar Reddi7399d5c2014-12-31 18:01:19 +0530671 if(!needsScaling(layer) && !layer->transform &&
672 (!isYuvBuffer((private_handle_t *)layer->handle)))
Jeykumar Sankaran455678c2014-05-30 10:22:38 -0700673 {
674 hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
675 int x_off = dst.left - src.left;
676 int y_off = dst.top - src.top;
677 updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
678 }
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800679#endif
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800680
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800681 roi = getUnion(roi, updatingRect);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700682 }
683 }
684
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800685 /* No layer is updating. Still SF wants a refresh.*/
686 if(!isValidRect(roi))
687 return;
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800688
689 // Align ROI coordinates to panel restrictions
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800690 roi = getSanitizeROI(roi, fullFrame);
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800691
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800692 ctx->listStats[mDpy].lRoi = roi;
693 if(!validateAndApplyROI(ctx, list))
694 resetROI(ctx, mDpy);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700695
696 ALOGD_IF(isDebug(),"%s: generated ROI: [%d, %d, %d, %d]", __FUNCTION__,
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800697 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
698 ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom);
699}
700
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800701void MDPCompSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect &crop,
702 hwc_rect &dst) {
703 hwc_rect roi = getUnion(ctx->listStats[mDpy].lRoi,
704 ctx->listStats[mDpy].rRoi);
705 hwc_rect tmpDst = getIntersection(dst, roi);
706 if(!isSameRect(dst, tmpDst)) {
707 crop.left = crop.left + (tmpDst.left - dst.left);
708 crop.top = crop.top + (tmpDst.top - dst.top);
709 crop.right = crop.left + (tmpDst.right - tmpDst.left);
710 crop.bottom = crop.top + (tmpDst.bottom - tmpDst.top);
711 dst = tmpDst;
712 }
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800713}
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800714
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800715/* 1) Identify layers that are not visible or lying outside BOTH the updating
716 * ROI's and drop them from composition. If a layer is spanning across both
717 * the halves of the screen but needed by only ROI, the non-contributing
718 * half will not be programmed for MDP.
719 * 2) If we have a scaling layer which needs cropping against generated
720 * ROI, reset ROI to full resolution. */
721bool MDPCompSplit::validateAndApplyROI(hwc_context_t *ctx,
722 hwc_display_contents_1_t* list) {
723
724 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
725
726 hwc_rect_t visibleRectL = ctx->listStats[mDpy].lRoi;
727 hwc_rect_t visibleRectR = ctx->listStats[mDpy].rRoi;
728
729 for(int i = numAppLayers - 1; i >= 0; i--){
730 if(!isValidRect(visibleRectL) && !isValidRect(visibleRectR))
731 {
732 mCurrentFrame.drop[i] = true;
733 mCurrentFrame.dropCount++;
734 continue;
735 }
736
737 const hwc_layer_1_t* layer = &list->hwLayers[i];
738 hwc_rect_t dstRect = layer->displayFrame;
739
740 hwc_rect_t l_res = getIntersection(visibleRectL, dstRect);
741 hwc_rect_t r_res = getIntersection(visibleRectR, dstRect);
742 hwc_rect_t res = getUnion(l_res, r_res);
743
744 if(!isValidRect(l_res) && !isValidRect(r_res)) {
745 mCurrentFrame.drop[i] = true;
746 mCurrentFrame.dropCount++;
747 } else {
748 /* Reset frame ROI when any layer which needs scaling also needs ROI
749 * cropping */
750 if(!isSameRect(res, dstRect) && needsScaling (layer)) {
751 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
752 mCurrentFrame.dropCount = 0;
753 return false;
754 }
755
radhakrishna4efbdd62014-11-03 13:19:27 +0530756 if (layer->blending == HWC_BLENDING_NONE &&
757 layer->planeAlpha == 0xFF) {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800758 visibleRectL = deductRect(visibleRectL, l_res);
759 visibleRectR = deductRect(visibleRectR, r_res);
760 }
761 }
762 }
763 return true;
764}
765/* Calculate ROI for the frame by accounting all the layer's dispalyFrame which
766 * are updating. If DirtyRegion is applicable, calculate it by accounting all
767 * the changing layer's dirtyRegion. */
768void MDPCompSplit::generateROI(hwc_context_t *ctx,
769 hwc_display_contents_1_t* list) {
770 if(!canPartialUpdate(ctx, list))
771 return;
772
773 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
774 int lSplit = getLeftSplit(ctx, mDpy);
775
776 int hw_h = (int)ctx->dpyAttr[mDpy].yres;
777 int hw_w = (int)ctx->dpyAttr[mDpy].xres;
778
779 struct hwc_rect l_frame = (struct hwc_rect){0, 0, lSplit, hw_h};
780 struct hwc_rect r_frame = (struct hwc_rect){lSplit, 0, hw_w, hw_h};
781
782 struct hwc_rect l_roi = (struct hwc_rect){0, 0, 0, 0};
783 struct hwc_rect r_roi = (struct hwc_rect){0, 0, 0, 0};
784
785 for(int index = 0; index < numAppLayers; index++ ) {
786 hwc_layer_1_t* layer = &list->hwLayers[index];
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800787 private_handle_t *hnd = (private_handle_t *)layer->handle;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800788 if ((mCachedFrame.hnd[index] != layer->handle) ||
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800789 isYuvBuffer(hnd)) {
Jeykumar Sankaran71e597c2014-05-07 16:23:14 -0700790 hwc_rect_t dst = layer->displayFrame;
791 hwc_rect_t updatingRect = dst;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800792
793#ifdef QCOM_BSP
794 if(!needsScaling(layer) && !layer->transform)
Jeykumar Sankaran71e597c2014-05-07 16:23:14 -0700795 {
796 hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
797 int x_off = dst.left - src.left;
798 int y_off = dst.top - src.top;
799 updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
800 }
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800801#endif
802
803 hwc_rect_t l_dst = getIntersection(l_frame, updatingRect);
804 if(isValidRect(l_dst))
805 l_roi = getUnion(l_roi, l_dst);
806
807 hwc_rect_t r_dst = getIntersection(r_frame, updatingRect);
808 if(isValidRect(r_dst))
809 r_roi = getUnion(r_roi, r_dst);
810 }
811 }
812
Jeykumar Sankarana40a9342014-04-25 09:37:10 -0700813 /* For panels that cannot accept commands in both the interfaces, we cannot
814 * send two ROI's (for each half). We merge them into single ROI and split
815 * them across lSplit for MDP mixer use. The ROI's will be merged again
816 * finally before udpating the panel in the driver. */
817 if(qdutils::MDPVersion::getInstance().needsROIMerge()) {
818 hwc_rect_t temp_roi = getUnion(l_roi, r_roi);
819 l_roi = getIntersection(temp_roi, l_frame);
820 r_roi = getIntersection(temp_roi, r_frame);
821 }
822
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800823 /* No layer is updating. Still SF wants a refresh. */
824 if(!isValidRect(l_roi) && !isValidRect(r_roi))
825 return;
826
827 l_roi = getSanitizeROI(l_roi, l_frame);
828 r_roi = getSanitizeROI(r_roi, r_frame);
829
830 ctx->listStats[mDpy].lRoi = l_roi;
831 ctx->listStats[mDpy].rRoi = r_roi;
832
833 if(!validateAndApplyROI(ctx, list))
834 resetROI(ctx, mDpy);
835
836 ALOGD_IF(isDebug(),"%s: generated L_ROI: [%d, %d, %d, %d]"
837 "R_ROI: [%d, %d, %d, %d]", __FUNCTION__,
838 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
839 ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom,
840 ctx->listStats[mDpy].rRoi.left, ctx->listStats[mDpy].rRoi.top,
841 ctx->listStats[mDpy].rRoi.right, ctx->listStats[mDpy].rRoi.bottom);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700842}
843
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800844/* Checks for conditions where all the layers marked for MDP comp cannot be
845 * bypassed. On such conditions we try to bypass atleast YUV layers */
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800846bool MDPComp::tryFullFrame(hwc_context_t *ctx,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800847 hwc_display_contents_1_t* list){
848
Saurabh Shahaa236822013-04-24 18:07:26 -0700849 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800850
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -0700851 // Fall back to video only composition, if AIV video mode is enabled
852 if(ctx->listStats[mDpy].mAIVVideoMode) {
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -0700853 ALOGD_IF(isDebug(), "%s: AIV Video Mode enabled dpy %d",
854 __FUNCTION__, mDpy);
855 return false;
856 }
857
Praveena Pachipulusu47346c22014-12-04 11:06:41 +0530858 /* No Idle fall back if secure display or secure RGB layers are present
859 * or if there is only a single layer being composed */
860 if(sIdleFallBack && !ctx->listStats[mDpy].secureUI &&
861 !ctx->listStats[mDpy].secureRGBCount &&
862 (ctx->listStats[mDpy].numAppLayers > 1)) {
Saurabh Shah2d998a92013-05-14 17:55:58 -0700863 ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
864 return false;
865 }
866
Raj Kamalc0d34242015-03-17 20:53:14 +0530867 if(!mDpy && isSecondaryAnimating(ctx) &&
868 (isYuvPresent(ctx,HWC_DISPLAY_EXTERNAL) ||
869 isYuvPresent(ctx,HWC_DISPLAY_VIRTUAL)) ) {
870 ALOGD_IF(isDebug(),"%s: Display animation in progress",
871 __FUNCTION__);
872 return false;
873 }
874
Ramkumar Radhakrishnanf26fe9e2014-09-09 13:47:54 -0700875 // if secondary is configuring or Padding round, fall back to video only
876 // composition and release all assigned non VIG pipes from primary.
877 if(isSecondaryConfiguring(ctx)) {
878 ALOGD_IF( isDebug(),"%s: External Display connection is pending",
879 __FUNCTION__);
880 return false;
881 } else if(ctx->isPaddingRound) {
882 ALOGD_IF(isDebug(), "%s: padding round invoked for dpy %d",
883 __FUNCTION__,mDpy);
884 return false;
885 }
886
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -0500887 // No MDP composition for 3D
888 if(needs3DComposition(ctx, mDpy))
889 return false;
890
Tatenda Chipeperekwacb2a2432014-08-06 17:45:58 -0700891 // check for action safe flag and MDP scaling mode which requires scaling.
Ramkumar Radhakrishnan4af1ef02013-12-12 11:53:08 -0800892 if(ctx->dpyAttr[mDpy].mActionSafePresent
Tatenda Chipeperekwacb2a2432014-08-06 17:45:58 -0700893 || ctx->dpyAttr[mDpy].mMDPScalingMode) {
Ramkumar Radhakrishnan4af1ef02013-12-12 11:53:08 -0800894 ALOGD_IF(isDebug(), "%s: Scaling needed for this frame",__FUNCTION__);
895 return false;
896 }
897
Saurabh Shahd1d93a22015-04-02 15:25:16 -0700898 uint32_t totalDirtyArea = 0;
899 bool computeDirtyArea = not (list->flags & HWC_GEOMETRY_CHANGED) and
900 not isYuvPresent(ctx, mDpy) and
901 not qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() and
902 numAppLayers > 1;
903
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800904 for(int i = 0; i < numAppLayers; ++i) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800905 hwc_layer_1_t* layer = &list->hwLayers[i];
906 private_handle_t *hnd = (private_handle_t *)layer->handle;
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -0800907
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800908 if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700909 if(!canUseRotator(ctx, mDpy)) {
910 ALOGD_IF(isDebug(), "%s: Can't use rotator for dpy %d",
911 __FUNCTION__, mDpy);
Amara Venkata Mastan Manoj Kumar9d373c02013-08-20 14:30:09 -0700912 return false;
913 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800914 }
Prabhanjan Kandula9fb032a2013-06-18 17:37:22 +0530915
916 //For 8x26 with panel width>1k, if RGB layer needs HFLIP fail mdp comp
917 // may not need it if Gfx pre-rotation can handle all flips & rotations
Saurabh Shahcad57772014-12-01 14:19:51 -0800918 MDPVersion& mdpHw = MDPVersion::getInstance();
Sushil Chauhanfda00fc2014-03-20 11:08:41 -0700919 int transform = (layer->flags & HWC_COLOR_FILL) ? 0 : layer->transform;
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530920 if( mdpHw.is8x26() && (ctx->dpyAttr[mDpy].xres > 1024) &&
921 (transform & HWC_TRANSFORM_FLIP_H) && (!isYuvBuffer(hnd)))
922 return false;
Saurabh Shahd1d93a22015-04-02 15:25:16 -0700923
924#ifdef QCOM_BSP
925 if(computeDirtyArea and mCachedFrame.hnd[i] != hnd) {
926 if(needsScaling(layer)) {
927 totalDirtyArea = 0;
928 computeDirtyArea = false;
929 } else {
930 hwc_rect_t dirtyRect = layer->dirtyRect;
931 ALOGD_IF(isDebug(),
932 "Updating layer: %d Dirty rect: %d, %d, %d, %d",
933 i, dirtyRect.left, dirtyRect.top, dirtyRect.right,
934 dirtyRect.bottom);
935 totalDirtyArea += (dirtyRect.right - dirtyRect.left)
936 * (dirtyRect.bottom - dirtyRect.top);
937 }
938 }
939#endif
940 }
941
942 if(totalDirtyArea) {
943 const uint32_t fbArea = ctx->dpyAttr[mDpy].xres *
944 ctx->dpyAttr[mDpy].yres;
945 if(totalDirtyArea < (fbArea / 20)) {
946 ALOGD_IF(isDebug(), "%s: Small update, bailing out. Dirty area %u",
947 __FUNCTION__, totalDirtyArea);
948 return false;
949 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800950 }
Saurabh Shahaa236822013-04-24 18:07:26 -0700951
Saurabh Shaha9da08f2013-07-03 13:27:53 -0700952 if(ctx->mAD->isDoable()) {
953 return false;
954 }
955
Saurabh Shahaa236822013-04-24 18:07:26 -0700956 //If all above hard conditions are met we can do full or partial MDP comp.
957 bool ret = false;
958 if(fullMDPComp(ctx, list)) {
959 ret = true;
Sushil Chauhandefd3522014-05-13 18:17:12 -0700960 } else if(fullMDPCompWithPTOR(ctx, list)) {
961 ret = true;
Jeykumar Sankaran24c199d2013-05-24 09:40:36 -0700962 } else if(partialMDPComp(ctx, list)) {
Saurabh Shahaa236822013-04-24 18:07:26 -0700963 ret = true;
964 }
Prabhanjan Kandula21918db2013-11-26 15:51:58 +0530965
Saurabh Shahaa236822013-04-24 18:07:26 -0700966 return ret;
967}
968
969bool MDPComp::fullMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -0700970
971 if(sSimulationFlags & MDPCOMP_AVOID_FULL_MDP)
972 return false;
973
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700974 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
975 for(int i = 0; i < numAppLayers; i++) {
976 hwc_layer_1_t* layer = &list->hwLayers[i];
Jeykumar Sankaran880da832014-04-18 10:22:35 -0700977 if(not mCurrentFrame.drop[i] and
978 not isSupportedForMDPComp(ctx, layer)) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700979 ALOGD_IF(isDebug(), "%s: Unsupported layer in list",__FUNCTION__);
980 return false;
981 }
982 }
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800983
Raj Kamalb5f0b4a2015-04-08 15:10:37 +0530984 if(!mDpy && isSecondaryConnected(ctx) &&
985 (qdutils::MDPVersion::getInstance().is8x16() ||
986 qdutils::MDPVersion::getInstance().is8x26() ||
987 qdutils::MDPVersion::getInstance().is8x39()) &&
988 isYuvPresent(ctx, HWC_DISPLAY_VIRTUAL)) {
989 ALOGD_IF(isDebug(), "%s: YUV layer present on secondary", __FUNCTION__);
990 return false;
991 }
992
Saurabh Shahaa236822013-04-24 18:07:26 -0700993 mCurrentFrame.fbCount = 0;
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700994 memcpy(&mCurrentFrame.isFBComposed, &mCurrentFrame.drop,
995 sizeof(mCurrentFrame.isFBComposed));
996 mCurrentFrame.mdpCount = mCurrentFrame.layerCount - mCurrentFrame.fbCount -
997 mCurrentFrame.dropCount;
Saurabh Shahaa236822013-04-24 18:07:26 -0700998
Raj Kamal389d6e32014-08-04 14:43:24 +0530999 if(sEnableYUVsplit){
Saurabh Shah3d4b8042013-12-10 15:19:17 -08001000 adjustForSourceSplit(ctx, list);
radhakrishnac9a67412013-09-25 17:40:42 +05301001 }
1002
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001003 if(!postHeuristicsHandling(ctx, list)) {
1004 ALOGD_IF(isDebug(), "post heuristic handling failed");
1005 reset(ctx);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07001006 return false;
1007 }
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001008 ALOGD_IF(sSimulationFlags,"%s: FULL_MDP_COMP SUCCEEDED",
1009 __FUNCTION__);
Saurabh Shahaa236822013-04-24 18:07:26 -07001010 return true;
1011}
1012
Sushil Chauhandefd3522014-05-13 18:17:12 -07001013/* Full MDP Composition with Peripheral Tiny Overlap Removal.
1014 * MDP bandwidth limitations can be avoided, if the overlap region
1015 * covered by the smallest layer at a higher z-order, gets composed
1016 * by Copybit on a render buffer, which can be queued to MDP.
1017 */
1018bool MDPComp::fullMDPCompWithPTOR(hwc_context_t *ctx,
1019 hwc_display_contents_1_t* list) {
1020
1021 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001022 // PTOR does not qualify when there are layers dropped, but if
1023 // dropped layer is only a cursor, PTOR could qualify
1024 const int numNonCursorLayers = numAppLayers - mCurrentFrame.dropCount;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001025 const int stagesForMDP = min(sMaxPipesPerMixer,
1026 ctx->mOverlay->availablePipes(mDpy, Overlay::MIXER_DEFAULT));
1027
1028 // Hard checks where we cannot use this mode
Sushil Chauhanbfc2de02014-07-24 11:52:58 -07001029 if (mDpy || !ctx->mCopyBit[mDpy]) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001030 ALOGD_IF(isDebug(), "%s: Feature not supported!", __FUNCTION__);
1031 return false;
1032 }
1033
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001034 // Frame level checks - consider PTOR in case of dropCount only if the cursor
1035 // layer is dropped, otherwise bail out of PTOR
Sushil Chauhandefd3522014-05-13 18:17:12 -07001036 if ((numAppLayers > stagesForMDP) || isSkipPresent(ctx, mDpy) ||
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001037 isYuvPresent(ctx, mDpy) || isSecurePresent(ctx, mDpy) ||
1038 (mCurrentFrame.dropCount - (int)isCursorPresent(ctx, mDpy))) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001039 ALOGD_IF(isDebug(), "%s: Frame not supported!", __FUNCTION__);
1040 return false;
1041 }
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001042 // MDP comp checks
1043 for(int i = 0; i < numAppLayers; i++) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001044 hwc_layer_1_t* layer = &list->hwLayers[i];
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001045 if(not isSupportedForMDPComp(ctx, layer)) {
1046 ALOGD_IF(isDebug(), "%s: Unsupported layer in list",__FUNCTION__);
1047 return false;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001048 }
1049 }
1050
Raj Kamalb5f0b4a2015-04-08 15:10:37 +05301051 if(!mDpy && isSecondaryConnected(ctx) &&
1052 (qdutils::MDPVersion::getInstance().is8x16() ||
1053 qdutils::MDPVersion::getInstance().is8x26() ||
1054 qdutils::MDPVersion::getInstance().is8x39()) &&
1055 isYuvPresent(ctx, HWC_DISPLAY_VIRTUAL)) {
1056 ALOGD_IF(isDebug(), "%s: YUV layer present on secondary", __FUNCTION__);
1057 return false;
1058 }
1059
Sushil Chauhandefd3522014-05-13 18:17:12 -07001060 /* We cannot use this composition mode, if:
1061 1. A below layer needs scaling.
1062 2. Overlap is not peripheral to display.
1063 3. Overlap or a below layer has 90 degree transform.
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001064 4. Overlap area > (1/3 * FrameBuffer) area, based on Perf inputs.
Sushil Chauhandefd3522014-05-13 18:17:12 -07001065 */
1066
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001067 int minLayerIndex[MAX_PTOR_LAYERS] = { -1, -1};
1068 hwc_rect_t overlapRect[MAX_PTOR_LAYERS];
1069 memset(overlapRect, 0, sizeof(overlapRect));
1070 int layerPixelCount, minPixelCount = 0;
1071 int numPTORLayersFound = 0;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001072 for (int i = numNonCursorLayers - 1; (i >= 0 &&
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001073 numPTORLayersFound < MAX_PTOR_LAYERS); i--) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001074 hwc_layer_1_t* layer = &list->hwLayers[i];
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001075 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
Sushil Chauhandefd3522014-05-13 18:17:12 -07001076 hwc_rect_t dispFrame = layer->displayFrame;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001077 layerPixelCount = (crop.right - crop.left) * (crop.bottom - crop.top);
1078 // PTOR layer should be peripheral and cannot have transform
1079 if (!isPeripheral(dispFrame, ctx->mViewFrame[mDpy]) ||
1080 has90Transform(layer)) {
1081 continue;
1082 }
1083 if((3 * (layerPixelCount + minPixelCount)) >
1084 ((int)ctx->dpyAttr[mDpy].xres * (int)ctx->dpyAttr[mDpy].yres)) {
1085 // Overlap area > (1/3 * FrameBuffer) area, based on Perf inputs.
1086 continue;
1087 }
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001088 bool found = false;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001089 for (int j = i-1; j >= 0; j--) {
1090 // Check if the layers below this layer qualifies for PTOR comp
1091 hwc_layer_1_t* layer = &list->hwLayers[j];
1092 hwc_rect_t disFrame = layer->displayFrame;
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001093 // Layer below PTOR is intersecting and has 90 degree transform or
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001094 // needs scaling cannot be supported.
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001095 if (isValidRect(getIntersection(dispFrame, disFrame))) {
1096 if (has90Transform(layer) || needsScaling(layer)) {
1097 found = false;
1098 break;
1099 }
1100 found = true;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001101 }
1102 }
1103 // Store the minLayer Index
1104 if(found) {
1105 minLayerIndex[numPTORLayersFound] = i;
1106 overlapRect[numPTORLayersFound] = list->hwLayers[i].displayFrame;
1107 minPixelCount += layerPixelCount;
1108 numPTORLayersFound++;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001109 }
1110 }
1111
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001112 // No overlap layers
1113 if (!numPTORLayersFound)
1114 return false;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001115
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001116 // Store the displayFrame and the sourceCrops of the layers
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001117 hwc_rect_t displayFrame[numNonCursorLayers];
1118 hwc_rect_t sourceCrop[numNonCursorLayers];
1119 for(int i = 0; i < numNonCursorLayers; i++) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001120 hwc_layer_1_t* layer = &list->hwLayers[i];
1121 displayFrame[i] = layer->displayFrame;
1122 sourceCrop[i] = integerizeSourceCrop(layer->sourceCropf);
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001123 }
Sushil Chauhandefd3522014-05-13 18:17:12 -07001124
Prabhanjan Kandula9889a202014-09-04 21:50:35 +05301125 /**
1126 * It's possible that 2 PTOR layers might have overlapping.
1127 * In such case, remove the intersection(again if peripheral)
1128 * from the lower PTOR layer to avoid overlapping.
1129 * If intersection is not on peripheral then compromise
1130 * by reducing number of PTOR layers.
1131 **/
1132 hwc_rect_t commonRect = getIntersection(overlapRect[0], overlapRect[1]);
1133 if(isValidRect(commonRect)) {
1134 overlapRect[1] = deductRect(overlapRect[1], commonRect);
1135 list->hwLayers[minLayerIndex[1]].displayFrame = overlapRect[1];
1136 }
1137
1138 ctx->mPtorInfo.count = numPTORLayersFound;
1139 for(int i = 0; i < MAX_PTOR_LAYERS; i++) {
1140 ctx->mPtorInfo.layerIndex[i] = minLayerIndex[i];
1141 }
1142
1143 if (!ctx->mCopyBit[mDpy]->prepareOverlap(ctx, list)) {
1144 // reset PTOR
1145 ctx->mPtorInfo.count = 0;
1146 if(isValidRect(commonRect)) {
1147 // If PTORs are intersecting restore displayframe of PTOR[1]
1148 // before returning, as we have modified it above.
1149 list->hwLayers[minLayerIndex[1]].displayFrame =
1150 displayFrame[minLayerIndex[1]];
1151 }
1152 return false;
1153 }
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001154 private_handle_t *renderBuf = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
1155 Whf layerWhf[numPTORLayersFound]; // To store w,h,f of PTOR layers
1156
Xu Yangcda012c2014-07-30 21:57:21 +08001157 // Store the blending mode, planeAlpha, and transform of PTOR layers
1158 int32_t blending[numPTORLayersFound];
1159 uint8_t planeAlpha[numPTORLayersFound];
1160 uint32_t transform[numPTORLayersFound];
1161
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001162 for(int j = 0; j < numPTORLayersFound; j++) {
1163 int index = ctx->mPtorInfo.layerIndex[j];
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001164
1165 // Update src crop of PTOR layer
1166 hwc_layer_1_t* layer = &list->hwLayers[index];
1167 layer->sourceCropf.left = (float)ctx->mPtorInfo.displayFrame[j].left;
1168 layer->sourceCropf.top = (float)ctx->mPtorInfo.displayFrame[j].top;
1169 layer->sourceCropf.right = (float)ctx->mPtorInfo.displayFrame[j].right;
1170 layer->sourceCropf.bottom =(float)ctx->mPtorInfo.displayFrame[j].bottom;
1171
1172 // Store & update w, h, format of PTOR layer
1173 private_handle_t *hnd = (private_handle_t *)layer->handle;
1174 Whf whf(hnd->width, hnd->height, hnd->format, hnd->size);
1175 layerWhf[j] = whf;
1176 hnd->width = renderBuf->width;
1177 hnd->height = renderBuf->height;
1178 hnd->format = renderBuf->format;
1179
Xu Yangcda012c2014-07-30 21:57:21 +08001180 // Store & update blending mode, planeAlpha and transform of PTOR layer
1181 blending[j] = layer->blending;
1182 planeAlpha[j] = layer->planeAlpha;
1183 transform[j] = layer->transform;
1184 layer->blending = HWC_BLENDING_NONE;
1185 layer->planeAlpha = 0xFF;
1186 layer->transform = 0;
1187
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001188 // Remove overlap from crop & displayFrame of below layers
1189 for (int i = 0; i < index && index !=-1; i++) {
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001190 layer = &list->hwLayers[i];
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001191 if(!isValidRect(getIntersection(layer->displayFrame,
1192 overlapRect[j]))) {
1193 continue;
1194 }
1195 // Update layer attributes
1196 hwc_rect_t srcCrop = integerizeSourceCrop(layer->sourceCropf);
1197 hwc_rect_t destRect = deductRect(layer->displayFrame,
Dileep Kumar Reddi72058b82014-11-11 16:03:03 +05301198 getIntersection(layer->displayFrame, overlapRect[j]));
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001199 qhwc::calculate_crop_rects(srcCrop, layer->displayFrame, destRect,
1200 layer->transform);
1201 layer->sourceCropf.left = (float)srcCrop.left;
1202 layer->sourceCropf.top = (float)srcCrop.top;
1203 layer->sourceCropf.right = (float)srcCrop.right;
1204 layer->sourceCropf.bottom = (float)srcCrop.bottom;
1205 }
Sushil Chauhandefd3522014-05-13 18:17:12 -07001206 }
1207
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001208 mCurrentFrame.mdpCount = numNonCursorLayers;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001209 mCurrentFrame.fbCount = 0;
1210 mCurrentFrame.fbZ = -1;
1211
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001212 for (int j = 0; j < numNonCursorLayers; j++) {
Dileep Kumar Reddi72058b82014-11-11 16:03:03 +05301213 if(isValidRect(list->hwLayers[j].displayFrame)) {
1214 mCurrentFrame.isFBComposed[j] = false;
1215 } else {
1216 mCurrentFrame.mdpCount--;
1217 mCurrentFrame.drop[j] = true;
1218 }
1219 }
Sushil Chauhandefd3522014-05-13 18:17:12 -07001220
1221 bool result = postHeuristicsHandling(ctx, list);
1222
1223 // Restore layer attributes
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001224 for(int i = 0; i < numNonCursorLayers; i++) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001225 hwc_layer_1_t* layer = &list->hwLayers[i];
1226 layer->displayFrame = displayFrame[i];
1227 layer->sourceCropf.left = (float)sourceCrop[i].left;
1228 layer->sourceCropf.top = (float)sourceCrop[i].top;
1229 layer->sourceCropf.right = (float)sourceCrop[i].right;
1230 layer->sourceCropf.bottom = (float)sourceCrop[i].bottom;
1231 }
1232
Xu Yangcda012c2014-07-30 21:57:21 +08001233 // Restore w,h,f, blending attributes, and transform of PTOR layers
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001234 for (int i = 0; i < numPTORLayersFound; i++) {
1235 int idx = ctx->mPtorInfo.layerIndex[i];
Xu Yangcda012c2014-07-30 21:57:21 +08001236 hwc_layer_1_t* layer = &list->hwLayers[idx];
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001237 private_handle_t *hnd = (private_handle_t *)list->hwLayers[idx].handle;
1238 hnd->width = layerWhf[i].w;
1239 hnd->height = layerWhf[i].h;
1240 hnd->format = layerWhf[i].format;
Xu Yangcda012c2014-07-30 21:57:21 +08001241 layer->blending = blending[i];
1242 layer->planeAlpha = planeAlpha[i];
1243 layer->transform = transform[i];
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001244 }
1245
Sushil Chauhandefd3522014-05-13 18:17:12 -07001246 if (!result) {
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001247 // reset PTOR
1248 ctx->mPtorInfo.count = 0;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001249 reset(ctx);
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001250 } else {
1251 ALOGD_IF(isDebug(), "%s: PTOR Indexes: %d and %d", __FUNCTION__,
1252 ctx->mPtorInfo.layerIndex[0], ctx->mPtorInfo.layerIndex[1]);
Sushil Chauhandefd3522014-05-13 18:17:12 -07001253 }
1254
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001255 ALOGD_IF(isDebug(), "%s: Postheuristics %s!", __FUNCTION__,
1256 (result ? "successful" : "failed"));
Sushil Chauhandefd3522014-05-13 18:17:12 -07001257 return result;
1258}
1259
Saurabh Shahaa236822013-04-24 18:07:26 -07001260bool MDPComp::partialMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list)
1261{
radhakrishnac3198ff2015-03-10 17:10:02 +05301262 if(!sEnableMixedMode || !isAlphaPresentinFB(ctx, mDpy)) {
1263 //Mixed mode is disabled/can't be used. No need to even try caching.
Jeykumar Sankaran24c199d2013-05-24 09:40:36 -07001264 return false;
1265 }
1266
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001267 bool ret = false;
Raj Kamal1179d9c2014-10-28 15:31:35 +05301268 if(isSkipPresent(ctx, mDpy) or list->flags & HWC_GEOMETRY_CHANGED) {
1269 //Try load based first
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001270 ret = loadBasedComp(ctx, list) or
Saurabh Shahf2de00f2013-12-11 17:52:53 -08001271 cacheBasedComp(ctx, list);
1272 } else {
1273 ret = cacheBasedComp(ctx, list) or
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001274 loadBasedComp(ctx, list);
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001275 }
1276
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001277 return ret;
1278}
1279
1280bool MDPComp::cacheBasedComp(hwc_context_t *ctx,
1281 hwc_display_contents_1_t* list) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001282 if(sSimulationFlags & MDPCOMP_AVOID_CACHE_MDP)
1283 return false;
1284
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001285 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shahaa236822013-04-24 18:07:26 -07001286 mCurrentFrame.reset(numAppLayers);
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001287 updateLayerCache(ctx, list, mCurrentFrame);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001288
1289 //If an MDP marked layer is unsupported cannot do partial MDP Comp
1290 for(int i = 0; i < numAppLayers; i++) {
1291 if(!mCurrentFrame.isFBComposed[i]) {
1292 hwc_layer_1_t* layer = &list->hwLayers[i];
1293 if(not isSupportedForMDPComp(ctx, layer)) {
1294 ALOGD_IF(isDebug(), "%s: Unsupported layer in list",
1295 __FUNCTION__);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001296 reset(ctx);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001297 return false;
1298 }
1299 }
1300 }
1301
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001302 updateYUV(ctx, list, false /*secure only*/, mCurrentFrame);
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001303 /* mark secure RGB layers for MDP comp */
1304 updateSecureRGB(ctx, list);
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301305 bool ret = markLayersForCaching(ctx, list); //sets up fbZ also
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001306 if(!ret) {
1307 ALOGD_IF(isDebug(),"%s: batching failed, dpy %d",__FUNCTION__, mDpy);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001308 reset(ctx);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001309 return false;
1310 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001311
1312 int mdpCount = mCurrentFrame.mdpCount;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001313
Raj Kamal389d6e32014-08-04 14:43:24 +05301314 if(sEnableYUVsplit){
Saurabh Shah3d4b8042013-12-10 15:19:17 -08001315 adjustForSourceSplit(ctx, list);
radhakrishnac9a67412013-09-25 17:40:42 +05301316 }
1317
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001318 if(!postHeuristicsHandling(ctx, list)) {
1319 ALOGD_IF(isDebug(), "post heuristic handling failed");
1320 reset(ctx);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07001321 return false;
1322 }
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001323 ALOGD_IF(sSimulationFlags,"%s: CACHE_MDP_COMP SUCCEEDED",
1324 __FUNCTION__);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07001325
Saurabh Shahaa236822013-04-24 18:07:26 -07001326 return true;
1327}
1328
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001329bool MDPComp::loadBasedComp(hwc_context_t *ctx,
Saurabh Shahb772ae32013-11-18 15:40:02 -08001330 hwc_display_contents_1_t* list) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001331 if(sSimulationFlags & MDPCOMP_AVOID_LOAD_MDP)
1332 return false;
1333
Arun Kumar K.R2aa44c62014-01-21 23:08:28 -08001334 if(not isLoadBasedCompDoable(ctx)) {
Saurabh Shahf2de00f2013-12-11 17:52:53 -08001335 return false;
1336 }
1337
Saurabh Shahb772ae32013-11-18 15:40:02 -08001338 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001339 const int numNonDroppedLayers = numAppLayers - mCurrentFrame.dropCount;
1340 const int stagesForMDP = min(sMaxPipesPerMixer,
1341 ctx->mOverlay->availablePipes(mDpy, Overlay::MIXER_DEFAULT));
Saurabh Shahf2de00f2013-12-11 17:52:53 -08001342
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001343 int mdpBatchSize = stagesForMDP - 1; //1 stage for FB
1344 int fbBatchSize = numNonDroppedLayers - mdpBatchSize;
1345 int lastMDPSupportedIndex = numAppLayers;
1346 int dropCount = 0;
Saurabh Shahb772ae32013-11-18 15:40:02 -08001347
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001348 //Find the minimum MDP batch size
1349 for(int i = 0; i < numAppLayers;i++) {
1350 if(mCurrentFrame.drop[i]) {
1351 dropCount++;
Jeykumar Sankaran846e2792014-01-23 21:59:58 -08001352 continue;
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001353 }
1354 hwc_layer_1_t* layer = &list->hwLayers[i];
1355 if(not isSupportedForMDPComp(ctx, layer)) {
1356 lastMDPSupportedIndex = i;
1357 mdpBatchSize = min(i - dropCount, stagesForMDP - 1);
1358 fbBatchSize = numNonDroppedLayers - mdpBatchSize;
Jeykumar Sankaran846e2792014-01-23 21:59:58 -08001359 break;
Saurabh Shahb772ae32013-11-18 15:40:02 -08001360 }
Saurabh Shahb772ae32013-11-18 15:40:02 -08001361 }
1362
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001363 ALOGD_IF(isDebug(), "%s:Before optimizing fbBatch, mdpbatch %d, fbbatch %d "
1364 "dropped %d", __FUNCTION__, mdpBatchSize, fbBatchSize,
1365 mCurrentFrame.dropCount);
1366
1367 //Start at a point where the fb batch should at least have 2 layers, for
1368 //this mode to be justified.
1369 while(fbBatchSize < 2) {
1370 ++fbBatchSize;
1371 --mdpBatchSize;
Jeykumar Sankaran846e2792014-01-23 21:59:58 -08001372 }
Saurabh Shahb772ae32013-11-18 15:40:02 -08001373
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001374 //If there are no layers for MDP, this mode doesnt make sense.
1375 if(mdpBatchSize < 1) {
1376 ALOGD_IF(isDebug(), "%s: No MDP layers after optimizing for fbBatch",
1377 __FUNCTION__);
Saurabh Shahb772ae32013-11-18 15:40:02 -08001378 return false;
1379 }
1380
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001381 mCurrentFrame.reset(numAppLayers);
1382
1383 //Try with successively smaller mdp batch sizes until we succeed or reach 1
1384 while(mdpBatchSize > 0) {
1385 //Mark layers for MDP comp
1386 int mdpBatchLeft = mdpBatchSize;
1387 for(int i = 0; i < lastMDPSupportedIndex and mdpBatchLeft; i++) {
1388 if(mCurrentFrame.drop[i]) {
1389 continue;
1390 }
1391 mCurrentFrame.isFBComposed[i] = false;
1392 --mdpBatchLeft;
1393 }
1394
1395 mCurrentFrame.fbZ = mdpBatchSize;
1396 mCurrentFrame.fbCount = fbBatchSize;
1397 mCurrentFrame.mdpCount = mdpBatchSize;
1398
1399 ALOGD_IF(isDebug(), "%s:Trying with: mdpbatch %d fbbatch %d dropped %d",
1400 __FUNCTION__, mdpBatchSize, fbBatchSize,
1401 mCurrentFrame.dropCount);
1402
1403 if(postHeuristicsHandling(ctx, list)) {
1404 ALOGD_IF(isDebug(), "%s: Postheuristics handling succeeded",
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001405 __FUNCTION__);
1406 ALOGD_IF(sSimulationFlags,"%s: LOAD_MDP_COMP SUCCEEDED",
1407 __FUNCTION__);
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001408 return true;
1409 }
1410
1411 reset(ctx);
1412 --mdpBatchSize;
1413 ++fbBatchSize;
1414 }
1415
1416 return false;
Saurabh Shahb772ae32013-11-18 15:40:02 -08001417}
1418
Arun Kumar K.R2aa44c62014-01-21 23:08:28 -08001419bool MDPComp::isLoadBasedCompDoable(hwc_context_t *ctx) {
Prabhanjan Kandula3dbbd882013-12-11 14:43:46 +05301420 if(mDpy or isSecurePresent(ctx, mDpy) or
1421 isYuvPresent(ctx, mDpy)) {
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001422 return false;
1423 }
1424 return true;
1425}
1426
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001427bool MDPComp::canPartialUpdate(hwc_context_t *ctx,
1428 hwc_display_contents_1_t* list){
1429 if(!qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() ||
1430 isSkipPresent(ctx, mDpy) || (list->flags & HWC_GEOMETRY_CHANGED) ||
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001431 isCursorPresent(ctx, mDpy) || !sIsPartialUpdateActive || mDpy) {
1432 // On Async position update, the ROI becomes invalid, hence disable PU
1433 // when cursor is present
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001434 return false;
1435 }
Jeykumar Sankaran4dd10ab2014-07-02 12:23:09 -07001436 if(ctx->listStats[mDpy].secureUI)
1437 return false;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001438 return true;
1439}
1440
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001441bool MDPComp::tryVideoOnly(hwc_context_t *ctx,
1442 hwc_display_contents_1_t* list) {
1443 const bool secureOnly = true;
1444 return videoOnlyComp(ctx, list, not secureOnly) or
1445 videoOnlyComp(ctx, list, secureOnly);
1446}
1447
1448bool MDPComp::videoOnlyComp(hwc_context_t *ctx,
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001449 hwc_display_contents_1_t* list, bool secureOnly) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001450 if(sSimulationFlags & MDPCOMP_AVOID_VIDEO_ONLY)
1451 return false;
Praveena Pachipulusu47346c22014-12-04 11:06:41 +05301452
Saurabh Shahaa236822013-04-24 18:07:26 -07001453 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Praveena Pachipulusu47346c22014-12-04 11:06:41 +05301454 if(!isSecurePresent(ctx, mDpy)) {
1455 /* Bail out if we are processing only secured video layers
1456 * and we dont have any */
1457 if(secureOnly) {
1458 ALOGD_IF(isDebug(),"%s: No Secure Video Layers", __FUNCTION__);
1459 return false;
1460 }
1461 /* No Idle fall back for secure video layers and if there is only
1462 * single layer being composed. */
1463 if(sIdleFallBack && (ctx->listStats[mDpy].numAppLayers > 1)) {
1464 ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
1465 return false;
1466 }
1467 }
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001468
Saurabh Shahaa236822013-04-24 18:07:26 -07001469 mCurrentFrame.reset(numAppLayers);
Jeykumar Sankaraneb3a5e22014-04-08 16:07:55 -07001470 mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001471 updateYUV(ctx, list, secureOnly, mCurrentFrame);
Saurabh Shah4fdde762013-04-30 18:47:33 -07001472 int mdpCount = mCurrentFrame.mdpCount;
Saurabh Shahaa236822013-04-24 18:07:26 -07001473
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001474 if(!isYuvPresent(ctx, mDpy) or (mdpCount == 0)) {
1475 reset(ctx);
Saurabh Shahaa236822013-04-24 18:07:26 -07001476 return false;
1477 }
1478
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001479 if(mCurrentFrame.fbCount)
1480 mCurrentFrame.fbZ = mCurrentFrame.mdpCount;
Saurabh Shah4fdde762013-04-30 18:47:33 -07001481
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05001482 if(sEnableYUVsplit || needs3DComposition(ctx, mDpy)){
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001483 adjustForSourceSplit(ctx, list);
1484 }
1485
1486 if(!postHeuristicsHandling(ctx, list)) {
1487 ALOGD_IF(isDebug(), "post heuristic handling failed");
Justin Philip37ab9a82015-01-06 11:55:12 +05301488 if(errno == ENOBUFS) {
1489 ALOGD_IF(isDebug(), "SMP Allocation failed");
1490 //On SMP allocation failure in video only comp add padding round
1491 ctx->isPaddingRound = true;
1492 }
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001493 reset(ctx);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07001494 return false;
1495 }
1496
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001497 ALOGD_IF(sSimulationFlags,"%s: VIDEO_ONLY_COMP SUCCEEDED",
1498 __FUNCTION__);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001499 return true;
1500}
1501
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001502/* if tryFullFrame fails, try to push all video and secure RGB layers to MDP */
1503bool MDPComp::tryMDPOnlyLayers(hwc_context_t *ctx,
1504 hwc_display_contents_1_t* list) {
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001505 // Fall back to video only composition, if AIV video mode is enabled
1506 if(ctx->listStats[mDpy].mAIVVideoMode) {
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07001507 ALOGD_IF(isDebug(), "%s: AIV Video Mode enabled dpy %d",
1508 __FUNCTION__, mDpy);
1509 return false;
1510 }
1511
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05001512 // No MDP composition for 3D
1513 if(needs3DComposition(ctx,mDpy))
1514 return false;
1515
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001516 const bool secureOnly = true;
1517 return mdpOnlyLayersComp(ctx, list, not secureOnly) or
1518 mdpOnlyLayersComp(ctx, list, secureOnly);
1519
1520}
1521
1522bool MDPComp::mdpOnlyLayersComp(hwc_context_t *ctx,
1523 hwc_display_contents_1_t* list, bool secureOnly) {
1524
1525 if(sSimulationFlags & MDPCOMP_AVOID_MDP_ONLY_LAYERS)
1526 return false;
1527
Praveena Pachipulusu47346c22014-12-04 11:06:41 +05301528 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
1529 if(!isSecurePresent(ctx, mDpy) && !ctx->listStats[mDpy].secureUI) {
1530 /* Bail out if we are processing only secured video/ui layers
1531 * and we dont have any */
1532 if(secureOnly) {
1533 ALOGD_IF(isDebug(), "%s: No secure video/ui layers");
1534 return false;
1535 }
1536 /* No Idle fall back for secure video/ui layers and if there is only
1537 * single layer being composed. */
1538 if(sIdleFallBack && (ctx->listStats[mDpy].numAppLayers > 1)) {
1539 ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
1540 return false;
1541 }
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001542 }
1543
Tatenda Chipeperekwa95675a72014-12-15 17:06:43 -08001544 /* Bail out if we dont have any secure RGB layers */
1545 if (!ctx->listStats[mDpy].secureRGBCount) {
1546 reset(ctx);
1547 return false;
1548 }
1549
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001550 mCurrentFrame.reset(numAppLayers);
1551 mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
1552
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001553 updateYUV(ctx, list, secureOnly, mCurrentFrame);
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001554 /* mark secure RGB layers for MDP comp */
1555 updateSecureRGB(ctx, list);
1556
1557 if(mCurrentFrame.mdpCount == 0) {
1558 reset(ctx);
1559 return false;
1560 }
1561
1562 /* find the maximum batch of layers to be marked for framebuffer */
1563 bool ret = markLayersForCaching(ctx, list); //sets up fbZ also
1564 if(!ret) {
1565 ALOGD_IF(isDebug(),"%s: batching failed, dpy %d",__FUNCTION__, mDpy);
1566 reset(ctx);
1567 return false;
1568 }
1569
1570 if(sEnableYUVsplit){
1571 adjustForSourceSplit(ctx, list);
1572 }
1573
1574 if(!postHeuristicsHandling(ctx, list)) {
1575 ALOGD_IF(isDebug(), "post heuristic handling failed");
1576 reset(ctx);
1577 return false;
1578 }
1579
1580 ALOGD_IF(sSimulationFlags,"%s: MDP_ONLY_LAYERS_COMP SUCCEEDED",
1581 __FUNCTION__);
1582 return true;
1583}
1584
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001585/* Checks for conditions where YUV layers cannot be bypassed */
1586bool MDPComp::isYUVDoable(hwc_context_t* ctx, hwc_layer_1_t* layer) {
Ramkumar Radhakrishnana70981a2013-08-28 11:33:53 -07001587 if(isSkipLayer(layer)) {
Saurabh Shahe2474082013-05-15 16:32:13 -07001588 ALOGD_IF(isDebug(), "%s: Video marked SKIP dpy %d", __FUNCTION__, mDpy);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001589 return false;
1590 }
1591
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08001592 if(has90Transform(layer) && !canUseRotator(ctx, mDpy)) {
Amara Venkata Mastan Manoj Kumar9d373c02013-08-20 14:30:09 -07001593 ALOGD_IF(isDebug(), "%s: no free DMA pipe",__FUNCTION__);
1594 return false;
1595 }
1596
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001597 if(isSecuring(ctx, layer)) {
1598 ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
1599 return false;
1600 }
1601
Saurabh Shah4fdde762013-04-30 18:47:33 -07001602 if(!isValidDimension(ctx, layer)) {
1603 ALOGD_IF(isDebug(), "%s: Buffer is of invalid width",
1604 __FUNCTION__);
1605 return false;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001606 }
Saurabh Shah4fdde762013-04-30 18:47:33 -07001607
Naseer Ahmeddc61a972013-07-10 17:50:54 -04001608 if(layer->planeAlpha < 0xFF) {
1609 ALOGD_IF(isDebug(), "%s: Cannot handle YUV layer with plane alpha\
1610 in video only mode",
1611 __FUNCTION__);
1612 return false;
1613 }
1614
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001615 return true;
1616}
1617
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001618/* Checks for conditions where Secure RGB layers cannot be bypassed */
1619bool MDPComp::isSecureRGBDoable(hwc_context_t* ctx, hwc_layer_1_t* layer) {
1620 if(isSkipLayer(layer)) {
1621 ALOGD_IF(isDebug(), "%s: Secure RGB layer marked SKIP dpy %d",
1622 __FUNCTION__, mDpy);
1623 return false;
1624 }
1625
1626 if(isSecuring(ctx, layer)) {
1627 ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
1628 return false;
1629 }
1630
1631 if(not isSupportedForMDPComp(ctx, layer)) {
1632 ALOGD_IF(isDebug(), "%s: Unsupported secure RGB layer",
1633 __FUNCTION__);
1634 return false;
1635 }
1636 return true;
1637}
1638
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301639/* starts at fromIndex and check for each layer to find
1640 * if it it has overlapping with any Updating layer above it in zorder
1641 * till the end of the batch. returns true if it finds any intersection */
1642bool MDPComp::canPushBatchToTop(const hwc_display_contents_1_t* list,
1643 int fromIndex, int toIndex) {
1644 for(int i = fromIndex; i < toIndex; i++) {
1645 if(mCurrentFrame.isFBComposed[i] && !mCurrentFrame.drop[i]) {
1646 if(intersectingUpdatingLayers(list, i+1, toIndex, i)) {
1647 return false;
1648 }
1649 }
1650 }
1651 return true;
1652}
1653
1654/* Checks if given layer at targetLayerIndex has any
1655 * intersection with all the updating layers in beween
1656 * fromIndex and toIndex. Returns true if it finds intersectiion */
1657bool MDPComp::intersectingUpdatingLayers(const hwc_display_contents_1_t* list,
1658 int fromIndex, int toIndex, int targetLayerIndex) {
1659 for(int i = fromIndex; i <= toIndex; i++) {
1660 if(!mCurrentFrame.isFBComposed[i]) {
1661 if(areLayersIntersecting(&list->hwLayers[i],
1662 &list->hwLayers[targetLayerIndex])) {
1663 return true;
1664 }
1665 }
1666 }
1667 return false;
1668}
1669
1670int MDPComp::getBatch(hwc_display_contents_1_t* list,
1671 int& maxBatchStart, int& maxBatchEnd,
1672 int& maxBatchCount) {
1673 int i = 0;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301674 int fbZOrder =-1;
Jeykumar Sankaran9502f352014-01-20 12:25:32 -08001675 int droppedLayerCt = 0;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301676 while (i < mCurrentFrame.layerCount) {
1677 int batchCount = 0;
1678 int batchStart = i;
1679 int batchEnd = i;
Jeykumar Sankaran9502f352014-01-20 12:25:32 -08001680 /* Adjust batch Z order with the dropped layers so far */
1681 int fbZ = batchStart - droppedLayerCt;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301682 int firstZReverseIndex = -1;
Prabhanjan Kandula0ed2cc92013-12-06 12:39:04 +05301683 int updatingLayersAbove = 0;//Updating layer count in middle of batch
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301684 while(i < mCurrentFrame.layerCount) {
1685 if(!mCurrentFrame.isFBComposed[i]) {
1686 if(!batchCount) {
1687 i++;
1688 break;
1689 }
1690 updatingLayersAbove++;
1691 i++;
1692 continue;
1693 } else {
1694 if(mCurrentFrame.drop[i]) {
1695 i++;
Jeykumar Sankaran9502f352014-01-20 12:25:32 -08001696 droppedLayerCt++;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301697 continue;
1698 } else if(updatingLayersAbove <= 0) {
1699 batchCount++;
1700 batchEnd = i;
1701 i++;
1702 continue;
1703 } else { //Layer is FBComposed, not a drop & updatingLayer > 0
1704
1705 // We have a valid updating layer already. If layer-i not
1706 // have overlapping with all updating layers in between
1707 // batch-start and i, then we can add layer i to batch.
1708 if(!intersectingUpdatingLayers(list, batchStart, i-1, i)) {
1709 batchCount++;
1710 batchEnd = i;
1711 i++;
1712 continue;
1713 } else if(canPushBatchToTop(list, batchStart, i)) {
1714 //If All the non-updating layers with in this batch
1715 //does not have intersection with the updating layers
1716 //above in z-order, then we can safely move the batch to
1717 //higher z-order. Increment fbZ as it is moving up.
1718 if( firstZReverseIndex < 0) {
1719 firstZReverseIndex = i;
1720 }
1721 batchCount++;
1722 batchEnd = i;
1723 fbZ += updatingLayersAbove;
1724 i++;
1725 updatingLayersAbove = 0;
1726 continue;
1727 } else {
1728 //both failed.start the loop again from here.
1729 if(firstZReverseIndex >= 0) {
1730 i = firstZReverseIndex;
1731 }
1732 break;
1733 }
1734 }
1735 }
1736 }
1737 if(batchCount > maxBatchCount) {
1738 maxBatchCount = batchCount;
1739 maxBatchStart = batchStart;
1740 maxBatchEnd = batchEnd;
1741 fbZOrder = fbZ;
1742 }
1743 }
1744 return fbZOrder;
1745}
1746
1747bool MDPComp::markLayersForCaching(hwc_context_t* ctx,
1748 hwc_display_contents_1_t* list) {
1749 /* Idea is to keep as many non-updating(cached) layers in FB and
1750 * send rest of them through MDP. This is done in 2 steps.
1751 * 1. Find the maximum contiguous batch of non-updating layers.
1752 * 2. See if we can improve this batch size for caching by adding
1753 * opaque layers around the batch, if they don't have
1754 * any overlapping with the updating layers in between.
1755 * NEVER mark an updating layer for caching.
1756 * But cached ones can be marked for MDP */
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001757
1758 int maxBatchStart = -1;
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001759 int maxBatchEnd = -1;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001760 int maxBatchCount = 0;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301761 int fbZ = -1;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001762
Saurabh Shahd53bc5f2014-02-05 10:17:43 -08001763 /* Nothing is cached. No batching needed */
1764 if(mCurrentFrame.fbCount == 0) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001765 return true;
Saurabh Shahaa236822013-04-24 18:07:26 -07001766 }
Saurabh Shahd53bc5f2014-02-05 10:17:43 -08001767
1768 /* No MDP comp layers, try to use other comp modes */
1769 if(mCurrentFrame.mdpCount == 0) {
1770 return false;
Saurabh Shahaa236822013-04-24 18:07:26 -07001771 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001772
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301773 fbZ = getBatch(list, maxBatchStart, maxBatchEnd, maxBatchCount);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001774
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301775 /* reset rest of the layers lying inside ROI for MDP comp */
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001776 for(int i = 0; i < mCurrentFrame.layerCount; i++) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001777 hwc_layer_1_t* layer = &list->hwLayers[i];
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001778 if((i < maxBatchStart || i > maxBatchEnd) &&
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301779 mCurrentFrame.isFBComposed[i]){
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001780 if(!mCurrentFrame.drop[i]){
1781 //If an unsupported layer is being attempted to
1782 //be pulled out we should fail
1783 if(not isSupportedForMDPComp(ctx, layer)) {
1784 return false;
1785 }
1786 mCurrentFrame.isFBComposed[i] = false;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001787 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001788 }
1789 }
1790
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301791 // update the frame data
1792 mCurrentFrame.fbZ = fbZ;
1793 mCurrentFrame.fbCount = maxBatchCount;
Saurabh Shahaa236822013-04-24 18:07:26 -07001794 mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001795 mCurrentFrame.fbCount - mCurrentFrame.dropCount;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001796
1797 ALOGD_IF(isDebug(),"%s: cached count: %d",__FUNCTION__,
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301798 mCurrentFrame.fbCount);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001799
1800 return true;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001801}
Saurabh Shah85234ec2013-04-12 17:09:00 -07001802
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001803void MDPComp::updateLayerCache(hwc_context_t* ctx,
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001804 hwc_display_contents_1_t* list, FrameInfo& frame) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001805 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001806 int fbCount = 0;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001807
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001808 for(int i = 0; i < numAppLayers; i++) {
1809 if (mCachedFrame.hnd[i] == list->hwLayers[i].handle) {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001810 if(!frame.drop[i])
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001811 fbCount++;
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001812 frame.isFBComposed[i] = true;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001813 } else {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001814 frame.isFBComposed[i] = false;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001815 }
1816 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001817
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001818 frame.fbCount = fbCount;
1819 frame.mdpCount = frame.layerCount - frame.fbCount
1820 - frame.dropCount;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001821
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001822 ALOGD_IF(isDebug(),"%s: MDP count: %d FB count %d drop count: %d",
1823 __FUNCTION__, frame.mdpCount, frame.fbCount, frame.dropCount);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001824}
1825
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001826// drop other non-AIV layers from external display list.
1827void MDPComp::dropNonAIVLayers(hwc_context_t* ctx,
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07001828 hwc_display_contents_1_t* list) {
1829 for (size_t i = 0; i < (size_t)ctx->listStats[mDpy].numAppLayers; i++) {
1830 hwc_layer_1_t * layer = &list->hwLayers[i];
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001831 if(!(isAIVVideoLayer(layer) || isAIVCCLayer(layer))) {
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07001832 mCurrentFrame.dropCount++;
1833 mCurrentFrame.drop[i] = true;
1834 }
1835 }
1836 mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
1837 mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
1838 mCurrentFrame.fbCount - mCurrentFrame.dropCount;
1839 ALOGD_IF(isDebug(),"%s: fb count: %d mdp count %d drop count %d",
1840 __FUNCTION__, mCurrentFrame.fbCount, mCurrentFrame.mdpCount,
1841 mCurrentFrame.dropCount);
1842}
1843
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001844void MDPComp::updateYUV(hwc_context_t* ctx, hwc_display_contents_1_t* list,
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001845 bool secureOnly, FrameInfo& frame) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001846 int nYuvCount = ctx->listStats[mDpy].yuvCount;
radhakrishna03640472015-05-25 17:34:13 +05301847 int nVGpipes = qdutils::MDPVersion::getInstance().getVGPipes();
1848
1849 /* If number of YUV layers in the layer list is more than the number of
1850 VG pipes available in the target (non-split), try to program maximum
1851 possible number of YUV layers to MDP, instead of falling back to GPU
1852 completely.*/
1853 nYuvCount = (nYuvCount > nVGpipes) ? nVGpipes : nYuvCount;
1854
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001855 for(int index = 0;index < nYuvCount; index++){
1856 int nYuvIndex = ctx->listStats[mDpy].yuvIndices[index];
1857 hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
1858
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001859 if(mCurrentFrame.drop[nYuvIndex]) {
1860 continue;
1861 }
1862
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001863 if(!isYUVDoable(ctx, layer)) {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001864 if(!frame.isFBComposed[nYuvIndex]) {
1865 frame.isFBComposed[nYuvIndex] = true;
1866 frame.fbCount++;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001867 }
1868 } else {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001869 if(frame.isFBComposed[nYuvIndex]) {
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001870 private_handle_t *hnd = (private_handle_t *)layer->handle;
Arun Kumar K.R7b1f1522015-06-01 19:55:47 -07001871 if(!secureOnly || isSecureBuffer(hnd) ||
1872 isProtectedBuffer(hnd)) {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001873 frame.isFBComposed[nYuvIndex] = false;
1874 frame.fbCount--;
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001875 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001876 }
1877 }
1878 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001879
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001880 frame.mdpCount = frame.layerCount - frame.fbCount - frame.dropCount;
1881 ALOGD_IF(isDebug(),"%s: fb count: %d",__FUNCTION__, frame.fbCount);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001882}
1883
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001884void MDPComp::updateSecureRGB(hwc_context_t* ctx,
1885 hwc_display_contents_1_t* list) {
1886 int nSecureRGBCount = ctx->listStats[mDpy].secureRGBCount;
1887 for(int index = 0;index < nSecureRGBCount; index++){
1888 int nSecureRGBIndex = ctx->listStats[mDpy].secureRGBIndices[index];
1889 hwc_layer_1_t* layer = &list->hwLayers[nSecureRGBIndex];
1890
1891 if(!isSecureRGBDoable(ctx, layer)) {
1892 if(!mCurrentFrame.isFBComposed[nSecureRGBIndex]) {
1893 mCurrentFrame.isFBComposed[nSecureRGBIndex] = true;
1894 mCurrentFrame.fbCount++;
1895 }
1896 } else {
1897 if(mCurrentFrame.isFBComposed[nSecureRGBIndex]) {
1898 mCurrentFrame.isFBComposed[nSecureRGBIndex] = false;
1899 mCurrentFrame.fbCount--;
1900 }
1901 }
1902 }
1903
1904 mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
1905 mCurrentFrame.fbCount - mCurrentFrame.dropCount;
1906 ALOGD_IF(isDebug(),"%s: fb count: %d",__FUNCTION__,
1907 mCurrentFrame.fbCount);
1908}
1909
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001910hwc_rect_t MDPComp::getUpdatingFBRect(hwc_context_t *ctx,
1911 hwc_display_contents_1_t* list){
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001912 hwc_rect_t fbRect = (struct hwc_rect){0, 0, 0, 0};
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001913
1914 /* Update only the region of FB needed for composition */
1915 for(int i = 0; i < mCurrentFrame.layerCount; i++ ) {
1916 if(mCurrentFrame.isFBComposed[i] && !mCurrentFrame.drop[i]) {
1917 hwc_layer_1_t* layer = &list->hwLayers[i];
1918 hwc_rect_t dst = layer->displayFrame;
1919 fbRect = getUnion(fbRect, dst);
1920 }
1921 }
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08001922 trimAgainstROI(ctx, fbRect, fbRect);
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001923 return fbRect;
1924}
1925
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001926bool MDPComp::postHeuristicsHandling(hwc_context_t *ctx,
1927 hwc_display_contents_1_t* list) {
1928
1929 //Capability checks
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08001930 if(!resourceCheck(ctx, list)) {
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001931 ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
1932 return false;
1933 }
1934
1935 //Limitations checks
1936 if(!hwLimitationsCheck(ctx, list)) {
1937 ALOGD_IF(isDebug(), "%s: HW limitations",__FUNCTION__);
1938 return false;
1939 }
1940
Saurabh Shah3d4b8042013-12-10 15:19:17 -08001941 //Configure framebuffer first if applicable
1942 if(mCurrentFrame.fbZ >= 0) {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001943 hwc_rect_t fbRect = getUpdatingFBRect(ctx, list);
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001944 if(!ctx->mFBUpdate[mDpy]->prepare(ctx, list, fbRect, mCurrentFrame.fbZ))
1945 {
Saurabh Shah3d4b8042013-12-10 15:19:17 -08001946 ALOGD_IF(isDebug(), "%s configure framebuffer failed",
1947 __FUNCTION__);
1948 return false;
1949 }
1950 }
1951
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001952 mCurrentFrame.map();
1953
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001954 if(!allocLayerPipes(ctx, list)) {
1955 ALOGD_IF(isDebug(), "%s: Unable to allocate MDP pipes", __FUNCTION__);
Saurabh Shahaa236822013-04-24 18:07:26 -07001956 return false;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001957 }
1958
1959 for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
Saurabh Shahaa236822013-04-24 18:07:26 -07001960 index++) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001961 if(!mCurrentFrame.isFBComposed[index]) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001962 int mdpIndex = mCurrentFrame.layerToMDP[index];
1963 hwc_layer_1_t* layer = &list->hwLayers[index];
1964
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301965 //Leave fbZ for framebuffer. CACHE/GLES layers go here.
1966 if(mdpNextZOrder == mCurrentFrame.fbZ) {
1967 mdpNextZOrder++;
1968 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001969 MdpPipeInfo* cur_pipe = mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
1970 cur_pipe->zOrder = mdpNextZOrder++;
1971
radhakrishnac9a67412013-09-25 17:40:42 +05301972 private_handle_t *hnd = (private_handle_t *)layer->handle;
Raj Kamal389d6e32014-08-04 14:43:24 +05301973 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
radhakrishnac9a67412013-09-25 17:40:42 +05301974 if(configure4k2kYuv(ctx, layer,
1975 mCurrentFrame.mdpToLayer[mdpIndex])
1976 != 0 ){
1977 ALOGD_IF(isDebug(), "%s: Failed to configure split pipes \
1978 for layer %d",__FUNCTION__, index);
1979 return false;
1980 }
1981 else{
1982 mdpNextZOrder++;
1983 }
1984 continue;
1985 }
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05001986 if(needs3DComposition(ctx,mDpy) && get3DFormat(hnd) != HAL_NO_3D) {
1987 mdpNextZOrder++;
1988 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001989 if(configure(ctx, layer, mCurrentFrame.mdpToLayer[mdpIndex]) != 0 ){
1990 ALOGD_IF(isDebug(), "%s: Failed to configure overlay for \
radhakrishnac9a67412013-09-25 17:40:42 +05301991 layer %d",__FUNCTION__, index);
Saurabh Shahaa236822013-04-24 18:07:26 -07001992 return false;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001993 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001994 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001995 }
1996
Saurabh Shaha36be922013-12-16 18:18:39 -08001997 if(!ctx->mOverlay->validateAndSet(mDpy, ctx->dpyAttr[mDpy].fd)) {
1998 ALOGD_IF(isDebug(), "%s: Failed to validate and set overlay for dpy %d"
1999 ,__FUNCTION__, mDpy);
2000 return false;
2001 }
2002
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002003 setRedraw(ctx, list);
Saurabh Shahaa236822013-04-24 18:07:26 -07002004 return true;
2005}
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002006
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08002007bool MDPComp::resourceCheck(hwc_context_t* ctx,
2008 hwc_display_contents_1_t* list) {
Saurabh Shah173f4242013-11-20 09:50:12 -08002009 const bool fbUsed = mCurrentFrame.fbCount;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002010 int cursorInUse = 0;
2011 if(mDpy == HWC_DISPLAY_PRIMARY) {
2012 // check if cursor is in use for primary
2013 cursorInUse = HWCursor::getInstance()->isCursorSet();
2014 }
2015 int maxStages = qdutils::MDPVersion::getInstance().getBlendStages();
2016 // HW Cursor needs one blending stage, account for that in the check below
2017 // On high end targets(8994) has 8 blending stages, HAL is configured to use < 8.
2018 // Make use of the remaining stages for HW Cursor so that the composition
2019 // strategy would not fail due to this limitation.
2020 if (maxStages > sMaxPipesPerMixer) {
2021 cursorInUse = 0;
2022 }
2023 if(mCurrentFrame.mdpCount > (sMaxPipesPerMixer - fbUsed - cursorInUse)) {
Saurabh Shah173f4242013-11-20 09:50:12 -08002024 ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
2025 return false;
2026 }
Saurabh Shahacec8e42014-11-25 11:07:04 -08002027
2028 //Will benefit cases where a video has non-updating background.
2029 if((mDpy > HWC_DISPLAY_PRIMARY) and
2030 (mCurrentFrame.mdpCount > sMaxSecLayers)) {
2031 ALOGD_IF(isDebug(), "%s: Exceeds max secondary pipes",__FUNCTION__);
2032 return false;
2033 }
2034
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08002035 // Init rotCount to number of rotate sessions used by other displays
2036 int rotCount = ctx->mRotMgr->getNumActiveSessions();
2037 // Count the number of rotator sessions required for current display
2038 for (int index = 0; index < mCurrentFrame.layerCount; index++) {
2039 if(!mCurrentFrame.isFBComposed[index]) {
2040 hwc_layer_1_t* layer = &list->hwLayers[index];
2041 private_handle_t *hnd = (private_handle_t *)layer->handle;
2042 if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
2043 rotCount++;
2044 }
2045 }
2046 }
2047 // if number of layers to rotate exceeds max rotator sessions, bail out.
2048 if(rotCount > RotMgr::MAX_ROT_SESS) {
2049 ALOGD_IF(isDebug(), "%s: Exceeds max rotator sessions %d",
2050 __FUNCTION__, mDpy);
2051 return false;
2052 }
Saurabh Shah173f4242013-11-20 09:50:12 -08002053 return true;
2054}
2055
Prabhanjan Kandula21918db2013-11-26 15:51:58 +05302056bool MDPComp::hwLimitationsCheck(hwc_context_t* ctx,
2057 hwc_display_contents_1_t* list) {
2058
2059 //A-family hw limitation:
2060 //If a layer need alpha scaling, MDP can not support.
2061 if(ctx->mMDP.version < qdutils::MDSS_V5) {
2062 for(int i = 0; i < mCurrentFrame.layerCount; ++i) {
2063 if(!mCurrentFrame.isFBComposed[i] &&
2064 isAlphaScaled( &list->hwLayers[i])) {
2065 ALOGD_IF(isDebug(), "%s:frame needs alphaScaling",__FUNCTION__);
2066 return false;
2067 }
2068 }
2069 }
2070
2071 // On 8x26 & 8974 hw, we have a limitation of downscaling+blending.
2072 //If multiple layers requires downscaling and also they are overlapping
2073 //fall back to GPU since MDSS can not handle it.
2074 if(qdutils::MDPVersion::getInstance().is8x74v2() ||
2075 qdutils::MDPVersion::getInstance().is8x26()) {
2076 for(int i = 0; i < mCurrentFrame.layerCount-1; ++i) {
2077 hwc_layer_1_t* botLayer = &list->hwLayers[i];
2078 if(!mCurrentFrame.isFBComposed[i] &&
2079 isDownscaleRequired(botLayer)) {
2080 //if layer-i is marked for MDP and needs downscaling
2081 //check if any MDP layer on top of i & overlaps with layer-i
2082 for(int j = i+1; j < mCurrentFrame.layerCount; ++j) {
2083 hwc_layer_1_t* topLayer = &list->hwLayers[j];
2084 if(!mCurrentFrame.isFBComposed[j] &&
2085 isDownscaleRequired(topLayer)) {
2086 hwc_rect_t r = getIntersection(botLayer->displayFrame,
2087 topLayer->displayFrame);
2088 if(isValidRect(r))
2089 return false;
2090 }
2091 }
2092 }
2093 }
2094 }
2095 return true;
2096}
2097
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002098static bool validForCursor(hwc_context_t* ctx, int dpy, hwc_layer_1_t* layer) {
2099 private_handle_t *hnd = (private_handle_t *)layer->handle;
2100 hwc_rect dst = layer->displayFrame;
2101 hwc_rect src = integerizeSourceCrop(layer->sourceCropf);
2102 int srcW = src.right - src.left;
2103 int srcH = src.bottom - src.top;
2104 int dstW = dst.right - dst.left;
2105 int dstH = dst.bottom - dst.top;
2106 qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
2107 uint32_t maxCursorSize = mdpVersion.getMaxCursorSize();
2108 uint32_t numHwCursors = mdpVersion.getCursorPipes();
2109 bool primarySplit = isDisplaySplit(ctx, HWC_DISPLAY_PRIMARY);
2110 uint32_t cursorPipesNeeded = 1; // One cursor pipe needed(default)
2111 bool ret = false;
2112
2113 if(dpy > HWC_DISPLAY_PRIMARY) {
2114 // Cursor not supported on secondary displays, as it involves scaling
2115 // in most of the cases
2116 return false;
2117 } else if (isSkipLayer(layer)) {
2118 return false;
2119 // Checks for HW limitation
2120 } else if (numHwCursors == 0 || maxCursorSize <= 0) {
2121 return false;
2122 } else if (needsScaling(layer)) {
2123 return false;
2124 } else if (layer->transform != 0) {
2125 return false;
2126 } else if (hnd->format != HAL_PIXEL_FORMAT_RGBA_8888) {
2127 return false;
2128 } else if (srcW > (int)maxCursorSize || srcH > (int)maxCursorSize) {
2129 return false;
2130 }
2131
2132 if (isDisplaySplit(ctx, dpy) && !mdpVersion.isSrcSplit()) {
2133 // In case of split display with no srcSplit, the driver allocates two
2134 // pipes to support async position update across mixers, hence
2135 // need to account for that here.
2136 cursorPipesNeeded = 2;
2137 }
2138 if (cursorPipesNeeded <= numHwCursors) {
2139 ret = true;
2140 }
2141 return ret;
2142}
2143
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08002144// Checks only if videos or single layer(RGB) is updating
2145// which is used for setting dynamic fps or perf hint for single
2146// layer video playback
2147bool MDPComp::onlyVideosUpdating(hwc_context_t *ctx,
2148 hwc_display_contents_1_t* list) {
2149 bool support = false;
2150 FrameInfo frame;
2151 frame.reset(mCurrentFrame.layerCount);
2152 memset(&frame.drop, 0, sizeof(frame.drop));
2153 frame.dropCount = 0;
2154 ALOGD_IF(isDebug(), "%s: Update Cache and YUVInfo", __FUNCTION__);
2155 updateLayerCache(ctx, list, frame);
2156 updateYUV(ctx, list, false /*secure only*/, frame);
2157 // There are only updating YUV layers or there is single RGB
2158 // Layer(Youtube)
2159 if((ctx->listStats[mDpy].yuvCount == frame.mdpCount) ||
2160 (frame.layerCount == 1)) {
2161 support = true;
2162 }
2163 return support;
2164}
2165
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302166void MDPComp::setDynRefreshRate(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
2167 //For primary display, set the dynamic refreshrate
2168 if(!mDpy && qdutils::MDPVersion::getInstance().isDynFpsSupported() &&
2169 ctx->mUseMetaDataRefreshRate) {
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302170 uint32_t refreshRate = ctx->dpyAttr[mDpy].refreshRate;
2171 MDPVersion& mdpHw = MDPVersion::getInstance();
2172 if(sIdleFallBack) {
2173 //Set minimum panel refresh rate during idle timeout
2174 refreshRate = mdpHw.getMinFpsSupported();
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08002175 } else if(onlyVideosUpdating(ctx, list)) {
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302176 //Set the new fresh rate, if there is only one updating YUV layer
2177 //or there is one single RGB layer with this request
2178 refreshRate = ctx->listStats[mDpy].refreshRateRequest;
2179 }
2180 setRefreshRate(ctx, mDpy, refreshRate);
2181 }
2182}
2183
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002184int MDPComp::prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002185 int ret = 0;
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07002186 char property[PROPERTY_VALUE_MAX];
2187
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002188 if(!list) {
2189 ALOGE("%s: Invalid list", __FUNCTION__);
Raj Kamal4393eaa2014-06-06 13:45:20 +05302190 mCachedFrame.reset();
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002191 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Raj Kamal4393eaa2014-06-06 13:45:20 +05302192 return -1;
2193 }
2194
2195 const int numLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shah286cf122014-09-08 14:13:08 -07002196 if(mDpy == HWC_DISPLAY_PRIMARY) {
2197 sSimulationFlags = 0;
2198 if(property_get("debug.hwc.simulate", property, NULL) > 0) {
2199 int currentFlags = atoi(property);
2200 if(currentFlags != sSimulationFlags) {
2201 sSimulationFlags = currentFlags;
2202 ALOGI("%s: Simulation Flag read: 0x%x (%d)", __FUNCTION__,
2203 sSimulationFlags, sSimulationFlags);
2204 }
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07002205 }
2206 }
Ramkumar Radhakrishnanc5893f12013-06-06 19:43:53 -07002207
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302208 //reset old data
2209 mCurrentFrame.reset(numLayers);
2210 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
2211 mCurrentFrame.dropCount = 0;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002212 mCurrentFrame.hwCursorIndex = -1;
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302213
Raj Kamal9ed3d6b2014-02-07 16:15:17 +05302214 //Do not cache the information for next draw cycle.
2215 if(numLayers > MAX_NUM_APP_LAYERS or (!numLayers)) {
2216 ALOGI("%s: Unsupported layer count for mdp composition",
2217 __FUNCTION__);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002218 mCachedFrame.reset();
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302219#ifdef DYNAMIC_FPS
Praveena Pachipulusu1c5431e2015-05-29 19:38:30 +05302220 // Reset refresh rate
2221 setRefreshRate(ctx, mDpy, ctx->dpyAttr[mDpy].refreshRate);
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302222#endif
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002223 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002224 return -1;
2225 }
2226
Ramkumar Radhakrishnana70981a2013-08-28 11:33:53 -07002227 // Detect the start of animation and fall back to GPU only once to cache
2228 // all the layers in FB and display FB content untill animation completes.
2229 if(ctx->listStats[mDpy].isDisplayAnimating) {
2230 mCurrentFrame.needsRedraw = false;
2231 if(ctx->mAnimationState[mDpy] == ANIMATION_STOPPED) {
2232 mCurrentFrame.needsRedraw = true;
2233 ctx->mAnimationState[mDpy] = ANIMATION_STARTED;
2234 }
2235 setMDPCompLayerFlags(ctx, list);
2236 mCachedFrame.updateCounts(mCurrentFrame);
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302237#ifdef DYNAMIC_FPS
Praveena Pachipulusu1c5431e2015-05-29 19:38:30 +05302238 // Reset refresh rate
2239 setRefreshRate(ctx, mDpy, ctx->dpyAttr[mDpy].refreshRate);
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302240#endif
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002241 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Ramkumar Radhakrishnana70981a2013-08-28 11:33:53 -07002242 ret = -1;
2243 return ret;
2244 } else {
2245 ctx->mAnimationState[mDpy] = ANIMATION_STOPPED;
2246 }
2247
Raj Kamalfdfdddf2015-03-16 21:59:25 +05302248 if(!mDpy and !isSecondaryConnected(ctx) and !mPrevModeOn and
2249 mCachedFrame.isSameFrame(ctx,mDpy,list)) {
2250
2251 ALOGD_IF(isDebug(),"%s: Avoid new composition",__FUNCTION__);
2252 mCurrentFrame.needsRedraw = false;
2253 setMDPCompLayerFlags(ctx, list);
2254 mCachedFrame.updateCounts(mCurrentFrame);
2255#ifdef DYNAMIC_FPS
2256 setDynRefreshRate(ctx, list);
2257#endif
2258 return -1;
2259
2260 }
2261
Saurabh Shahb39f8152013-08-22 10:21:44 -07002262 //Hard conditions, if not met, cannot do MDP comp
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002263 if(isFrameDoable(ctx)) {
2264 generateROI(ctx, list);
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07002265 // if AIV Video mode is enabled, drop all non AIV layers from the
2266 // external display list.
2267 if(ctx->listStats[mDpy].mAIVVideoMode) {
2268 dropNonAIVLayers(ctx, list);
2269 }
Saurabh Shahb39f8152013-08-22 10:21:44 -07002270
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002271 // Configure the cursor if present
2272 int topIndex = ctx->listStats[mDpy].numAppLayers - 1;
2273 if(ctx->listStats[mDpy].cursorLayerPresent &&
2274 validForCursor(ctx, mDpy, &(list->hwLayers[topIndex]))) {
2275 if(configHwCursor(ctx->dpyAttr[mDpy].fd, mDpy,
2276 &(list->hwLayers[topIndex]))) {
2277 // As cursor is configured, mark that layer as dropped, so that
2278 // it wont be considered for composition by other strategies.
2279 mCurrentFrame.hwCursorIndex = topIndex;
2280 mCurrentFrame.drop[topIndex] = true;
2281 mCurrentFrame.dropCount++;
2282 }
2283 } else {
2284 // Release the hw cursor
2285 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
2286 }
2287
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07002288 // if tryFullFrame fails, try to push all video and secure RGB layers
2289 // to MDP for composition.
2290 mModeOn = tryFullFrame(ctx, list) || tryMDPOnlyLayers(ctx, list) ||
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07002291 tryVideoOnly(ctx, list);
Raj Kamal4393eaa2014-06-06 13:45:20 +05302292 if(mModeOn) {
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002293 setMDPCompLayerFlags(ctx, list);
2294 } else {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08002295 resetROI(ctx, mDpy);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002296 reset(ctx);
2297 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
2298 mCurrentFrame.dropCount = 0;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002299 // Check if cursor is in use for primary and mark accordingly
2300 if(!mDpy && HWCursor::getInstance()->isCursorSet()) {
2301 int topIndex = ctx->listStats[mDpy].numAppLayers - 1;
2302 hwc_layer_1_t *layer = &(list->hwLayers[topIndex]);
2303 layer->compositionType = HWC_CURSOR_OVERLAY;
2304 }
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002305 ret = -1;
Saurabh Shah286cf122014-09-08 14:13:08 -07002306 ALOGE_IF(sSimulationFlags && (mDpy == HWC_DISPLAY_PRIMARY),
2307 "MDP Composition Strategies Failed");
Saurabh Shahb39f8152013-08-22 10:21:44 -07002308 }
2309 } else {
Dileep Kumar Reddi4070e932014-09-30 09:00:57 +05302310 if ((ctx->mMDP.version == qdutils::MDP_V3_0_5) && ctx->mCopyBit[mDpy] &&
2311 enablePartialUpdateForMDP3) {
2312 generateROI(ctx, list);
2313 for(int i = 0; i < ctx->listStats[mDpy].numAppLayers; i++) {
2314 ctx->copybitDrop[i] = mCurrentFrame.drop[i];
2315 }
2316 }
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002317 ALOGD_IF( isDebug(),"%s: MDP Comp not possible for this frame",
2318 __FUNCTION__);
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002319 // Release the hw cursor
2320 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002321 ret = -1;
Saurabh Shahb39f8152013-08-22 10:21:44 -07002322 }
Saurabh Shahb39f8152013-08-22 10:21:44 -07002323
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002324 if(isDebug()) {
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002325 ALOGD("GEOMETRY change: %d",
2326 (list->flags & HWC_GEOMETRY_CHANGED));
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002327 android::String8 sDump("");
Jeykumar Sankaran6850ac62014-05-27 10:07:26 -07002328 dump(sDump, ctx);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002329 ALOGD("%s",sDump.string());
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002330 }
2331
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07002332#ifdef DYNAMIC_FPS
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302333 setDynRefreshRate(ctx, list);
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07002334#endif
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08002335 setPerfHint(ctx, list);
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07002336
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002337 mCachedFrame.cacheAll(list);
2338 mCachedFrame.updateCounts(mCurrentFrame);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002339 return ret;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002340}
2341
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002342bool MDPComp::allocSplitVGPipes(hwc_context_t *ctx, int index) {
radhakrishnac9a67412013-09-25 17:40:42 +05302343
2344 bool bRet = true;
radhakrishnac9a67412013-09-25 17:40:42 +05302345 int mdpIndex = mCurrentFrame.layerToMDP[index];
2346 PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
2347 info.pipeInfo = new MdpYUVPipeInfo;
2348 info.rot = NULL;
2349 MdpYUVPipeInfo& pipe_info = *(MdpYUVPipeInfo*)info.pipeInfo;
radhakrishnac9a67412013-09-25 17:40:42 +05302350
2351 pipe_info.lIndex = ovutils::OV_INVALID;
2352 pipe_info.rIndex = ovutils::OV_INVALID;
2353
Saurabh Shahc62f3982014-03-05 14:28:26 -08002354 Overlay::PipeSpecs pipeSpecs;
2355 pipeSpecs.formatClass = Overlay::FORMAT_YUV;
2356 pipeSpecs.needsScaling = true;
2357 pipeSpecs.dpy = mDpy;
2358 pipeSpecs.fb = false;
2359
2360 pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
radhakrishnac9a67412013-09-25 17:40:42 +05302361 if(pipe_info.lIndex == ovutils::OV_INVALID){
2362 bRet = false;
2363 ALOGD_IF(isDebug(),"%s: allocating first VG pipe failed",
2364 __FUNCTION__);
2365 }
Saurabh Shahc62f3982014-03-05 14:28:26 -08002366 pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
radhakrishnac9a67412013-09-25 17:40:42 +05302367 if(pipe_info.rIndex == ovutils::OV_INVALID){
2368 bRet = false;
2369 ALOGD_IF(isDebug(),"%s: allocating second VG pipe failed",
2370 __FUNCTION__);
2371 }
2372 return bRet;
2373}
Sushil Chauhandefd3522014-05-13 18:17:12 -07002374
2375int MDPComp::drawOverlap(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
2376 int fd = -1;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002377 if (ctx->mPtorInfo.isActive()) {
2378 fd = ctx->mCopyBit[mDpy]->drawOverlap(ctx, list);
Sushil Chauhandefd3522014-05-13 18:17:12 -07002379 if (fd < 0) {
2380 ALOGD_IF(isDebug(),"%s: failed", __FUNCTION__);
Sushil Chauhandefd3522014-05-13 18:17:12 -07002381 }
2382 }
2383 return fd;
2384}
Arun Kumar K.R2aa44c62014-01-21 23:08:28 -08002385//=============MDPCompNonSplit==================================================
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002386
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002387void MDPCompNonSplit::adjustForSourceSplit(hwc_context_t *ctx,
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302388 hwc_display_contents_1_t* list) {
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002389 //If 4k2k Yuv layer split is possible, and if
2390 //fbz is above 4k2k layer, increment fb zorder by 1
2391 //as we split 4k2k layer and increment zorder for right half
2392 //of the layer
Shalaj Jaina70b4352014-06-15 13:47:47 -07002393 if(!ctx)
2394 return;
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002395 if(mCurrentFrame.fbZ >= 0) {
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302396 for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
2397 index++) {
2398 if(!mCurrentFrame.isFBComposed[index]) {
2399 if(mdpNextZOrder == mCurrentFrame.fbZ) {
2400 mdpNextZOrder++;
2401 }
2402 mdpNextZOrder++;
2403 hwc_layer_1_t* layer = &list->hwLayers[index];
2404 private_handle_t *hnd = (private_handle_t *)layer->handle;
Raj Kamal389d6e32014-08-04 14:43:24 +05302405 if(isYUVSplitNeeded(hnd)) {
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302406 if(mdpNextZOrder <= mCurrentFrame.fbZ)
2407 mCurrentFrame.fbZ += 1;
2408 mdpNextZOrder++;
2409 //As we split 4kx2k yuv layer and program to 2 VG pipes
2410 //(if available) increase mdpcount by 1.
2411 mCurrentFrame.mdpCount++;
2412 }
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002413 }
2414 }
2415 }
radhakrishnac9a67412013-09-25 17:40:42 +05302416}
2417
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002418/*
2419 * Configures pipe(s) for MDP composition
2420 */
Saurabh Shah88e4d272013-09-03 13:31:29 -07002421int MDPCompNonSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002422 PipeLayerPair& PipeLayerPair) {
Saurabh Shah88e4d272013-09-03 13:31:29 -07002423 MdpPipeInfoNonSplit& mdp_info =
2424 *(static_cast<MdpPipeInfoNonSplit*>(PipeLayerPair.pipeInfo));
Justin Philipd6166602014-08-12 13:42:21 +05302425 eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shahacf10202013-02-26 10:15:15 -08002426 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Saurabh Shahacf10202013-02-26 10:15:15 -08002427 eDest dest = mdp_info.index;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002428
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002429 ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipe: %d",
2430 __FUNCTION__, layer, zOrder, dest);
2431
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002432 return configureNonSplit(ctx, layer, mDpy, mdpFlags, zOrder, dest,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002433 &PipeLayerPair.rot);
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002434}
2435
Saurabh Shah88e4d272013-09-03 13:31:29 -07002436bool MDPCompNonSplit::allocLayerPipes(hwc_context_t *ctx,
Saurabh Shahe51f8ca2013-05-06 17:26:16 -07002437 hwc_display_contents_1_t* list) {
Saurabh Shah8cc77712015-03-31 10:48:51 -07002438 for(uint32_t formatType = FORMAT_YUV; formatType < FORMAT_MAX;
2439 formatType++) {
2440 for(int index = 0; index < mCurrentFrame.layerCount; index++) {
2441 if(mCurrentFrame.isFBComposed[index]) continue;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002442
Saurabh Shah8cc77712015-03-31 10:48:51 -07002443 hwc_layer_1_t* layer = &list->hwLayers[index];
2444 private_handle_t *hnd = (private_handle_t *)layer->handle;
2445 if(formatType == FORMAT_YUV && !isYuvBuffer(hnd))
radhakrishnac9a67412013-09-25 17:40:42 +05302446 continue;
Saurabh Shah8cc77712015-03-31 10:48:51 -07002447 if(formatType == FORMAT_RGB && isYuvBuffer(hnd))
2448 continue;
2449
2450 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
2451 if(allocSplitVGPipes(ctx, index)){
2452 continue;
2453 }
radhakrishnac9a67412013-09-25 17:40:42 +05302454 }
radhakrishnac9a67412013-09-25 17:40:42 +05302455
Saurabh Shah8cc77712015-03-31 10:48:51 -07002456 int mdpIndex = mCurrentFrame.layerToMDP[index];
2457 PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
2458 info.pipeInfo = new MdpPipeInfoNonSplit;
2459 info.rot = NULL;
2460 MdpPipeInfoNonSplit& pipe_info =
2461 *(MdpPipeInfoNonSplit*)info.pipeInfo;
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -08002462
Saurabh Shah8cc77712015-03-31 10:48:51 -07002463 Overlay::PipeSpecs pipeSpecs;
2464 pipeSpecs.formatClass = isYuvBuffer(hnd) ?
2465 Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
2466 pipeSpecs.needsScaling = qhwc::needsScaling(layer) or
2467 (qdutils::MDPVersion::getInstance().is8x26() and
2468 ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres > 1024);
2469 pipeSpecs.dpy = mDpy;
2470 pipeSpecs.fb = false;
2471 pipeSpecs.numActiveDisplays = ctx->numActiveDisplays;
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -08002472
Saurabh Shah8cc77712015-03-31 10:48:51 -07002473 pipe_info.index = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahc62f3982014-03-05 14:28:26 -08002474
Saurabh Shah8cc77712015-03-31 10:48:51 -07002475 if(pipe_info.index == ovutils::OV_INVALID) {
2476 ALOGD_IF(isDebug(), "%s: Unable to get pipe for layer %d of "\
2477 "format type %d", __FUNCTION__, index, formatType);
2478 return false;
2479 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002480 }
2481 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002482 return true;
2483}
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002484
radhakrishnac9a67412013-09-25 17:40:42 +05302485int MDPCompNonSplit::configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
2486 PipeLayerPair& PipeLayerPair) {
2487 MdpYUVPipeInfo& mdp_info =
2488 *(static_cast<MdpYUVPipeInfo*>(PipeLayerPair.pipeInfo));
2489 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Justin Philipd6166602014-08-12 13:42:21 +05302490 eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
radhakrishnac9a67412013-09-25 17:40:42 +05302491 eDest lDest = mdp_info.lIndex;
2492 eDest rDest = mdp_info.rIndex;
2493
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002494 return configureSourceSplit(ctx, layer, mDpy, mdpFlagsL, zOrder,
radhakrishnac9a67412013-09-25 17:40:42 +05302495 lDest, rDest, &PipeLayerPair.rot);
2496}
2497
Saurabh Shah88e4d272013-09-03 13:31:29 -07002498bool MDPCompNonSplit::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002499
Raj Kamal4393eaa2014-06-06 13:45:20 +05302500 if(!isEnabled() or !mModeOn) {
2501 ALOGD_IF(isDebug(),"%s: MDP Comp not enabled/configured", __FUNCTION__);
Prabhanjan Kandula08222fc2013-07-10 17:20:59 +05302502 return true;
2503 }
2504
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002505 overlay::Overlay& ov = *ctx->mOverlay;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002506 LayerProp *layerProp = ctx->layerProp[mDpy];
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002507
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002508 int numHwLayers = ctx->listStats[mDpy].numAppLayers;
2509 for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ )
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002510 {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002511 if(mCurrentFrame.isFBComposed[i]) continue;
2512
Naseer Ahmed5b6708a2012-08-02 13:46:08 -07002513 hwc_layer_1_t *layer = &list->hwLayers[i];
Saurabh Shahacf10202013-02-26 10:15:15 -08002514 private_handle_t *hnd = (private_handle_t *)layer->handle;
2515 if(!hnd) {
Sushil Chauhan897a9c32013-07-18 11:09:55 -07002516 if (!(layer->flags & HWC_COLOR_FILL)) {
2517 ALOGE("%s handle null", __FUNCTION__);
2518 return false;
2519 }
2520 // No PLAY for Color layer
2521 layerProp[i].mFlags &= ~HWC_MDPCOMP;
2522 continue;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002523 }
2524
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002525 int mdpIndex = mCurrentFrame.layerToMDP[i];
2526
Raj Kamal389d6e32014-08-04 14:43:24 +05302527 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit)
radhakrishnac9a67412013-09-25 17:40:42 +05302528 {
2529 MdpYUVPipeInfo& pipe_info =
2530 *(MdpYUVPipeInfo*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
2531 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
2532 ovutils::eDest indexL = pipe_info.lIndex;
2533 ovutils::eDest indexR = pipe_info.rIndex;
2534 int fd = hnd->fd;
Praveena Pachipulusud9443c72014-02-17 10:42:28 +05302535 uint32_t offset = (uint32_t)hnd->offset;
radhakrishnac9a67412013-09-25 17:40:42 +05302536 if(rot) {
2537 rot->queueBuffer(fd, offset);
2538 fd = rot->getDstMemId();
2539 offset = rot->getDstOffset();
2540 }
2541 if(indexL != ovutils::OV_INVALID) {
2542 ovutils::eDest destL = (ovutils::eDest)indexL;
2543 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2544 using pipe: %d", __FUNCTION__, layer, hnd, indexL );
2545 if (!ov.queueBuffer(fd, offset, destL)) {
2546 ALOGE("%s: queueBuffer failed for display:%d",
2547 __FUNCTION__, mDpy);
2548 return false;
2549 }
2550 }
2551
2552 if(indexR != ovutils::OV_INVALID) {
2553 ovutils::eDest destR = (ovutils::eDest)indexR;
2554 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2555 using pipe: %d", __FUNCTION__, layer, hnd, indexR );
2556 if (!ov.queueBuffer(fd, offset, destR)) {
2557 ALOGE("%s: queueBuffer failed for display:%d",
2558 __FUNCTION__, mDpy);
2559 return false;
2560 }
2561 }
2562 }
2563 else{
2564 MdpPipeInfoNonSplit& pipe_info =
Saurabh Shah88e4d272013-09-03 13:31:29 -07002565 *(MdpPipeInfoNonSplit*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
radhakrishnac9a67412013-09-25 17:40:42 +05302566 ovutils::eDest dest = pipe_info.index;
2567 if(dest == ovutils::OV_INVALID) {
2568 ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, dest);
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002569 return false;
radhakrishnac9a67412013-09-25 17:40:42 +05302570 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002571
radhakrishnac9a67412013-09-25 17:40:42 +05302572 if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
2573 continue;
2574 }
2575
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002576 int fd = hnd->fd;
2577 uint32_t offset = (uint32_t)hnd->offset;
2578 int index = ctx->mPtorInfo.getPTORArrayIndex(i);
2579 if (!mDpy && (index != -1)) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07002580 hnd = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002581 fd = hnd->fd;
Sushil Chauhan875a92e2014-07-25 12:20:23 -07002582 offset = 0;
Sushil Chauhandefd3522014-05-13 18:17:12 -07002583 }
2584
radhakrishnac9a67412013-09-25 17:40:42 +05302585 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2586 using pipe: %d", __FUNCTION__, layer,
2587 hnd, dest );
2588
radhakrishnac9a67412013-09-25 17:40:42 +05302589 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
2590 if(rot) {
2591 if(!rot->queueBuffer(fd, offset))
2592 return false;
2593 fd = rot->getDstMemId();
2594 offset = rot->getDstOffset();
2595 }
2596
2597 if (!ov.queueBuffer(fd, offset, dest)) {
2598 ALOGE("%s: queueBuffer failed for display:%d ",
2599 __FUNCTION__, mDpy);
2600 return false;
2601 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002602 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002603
2604 layerProp[i].mFlags &= ~HWC_MDPCOMP;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002605 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002606 return true;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002607}
2608
Saurabh Shah88e4d272013-09-03 13:31:29 -07002609//=============MDPCompSplit===================================================
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002610
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002611void MDPCompSplit::adjustForSourceSplit(hwc_context_t *ctx,
radhakrishnac9a67412013-09-25 17:40:42 +05302612 hwc_display_contents_1_t* list){
2613 //if 4kx2k yuv layer is totally present in either in left half
2614 //or right half then try splitting the yuv layer to avoid decimation
radhakrishnac9a67412013-09-25 17:40:42 +05302615 const int lSplit = getLeftSplit(ctx, mDpy);
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302616 if(mCurrentFrame.fbZ >= 0) {
2617 for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
2618 index++) {
2619 if(!mCurrentFrame.isFBComposed[index]) {
2620 if(mdpNextZOrder == mCurrentFrame.fbZ) {
2621 mdpNextZOrder++;
2622 }
2623 mdpNextZOrder++;
2624 hwc_layer_1_t* layer = &list->hwLayers[index];
2625 private_handle_t *hnd = (private_handle_t *)layer->handle;
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002626 if(isYUVSplitNeeded(hnd) ||
2627 (needs3DComposition(ctx,mDpy) &&
2628 get3DFormat(hnd) != HAL_NO_3D)) {
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302629 hwc_rect_t dst = layer->displayFrame;
2630 if((dst.left > lSplit) || (dst.right < lSplit)) {
2631 mCurrentFrame.mdpCount += 1;
2632 }
2633 if(mdpNextZOrder <= mCurrentFrame.fbZ)
2634 mCurrentFrame.fbZ += 1;
2635 mdpNextZOrder++;
2636 }
2637 }
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002638 }
radhakrishnac9a67412013-09-25 17:40:42 +05302639 }
2640}
2641
Saurabh Shah88e4d272013-09-03 13:31:29 -07002642bool MDPCompSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
Saurabh Shahc62f3982014-03-05 14:28:26 -08002643 MdpPipeInfoSplit& pipe_info) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002644
Saurabh Shahc62f3982014-03-05 14:28:26 -08002645 const int lSplit = getLeftSplit(ctx, mDpy);
2646 private_handle_t *hnd = (private_handle_t *)layer->handle;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002647 hwc_rect_t dst = layer->displayFrame;
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002648 pipe_info.lIndex = ovutils::OV_INVALID;
2649 pipe_info.rIndex = ovutils::OV_INVALID;
2650
Saurabh Shahc62f3982014-03-05 14:28:26 -08002651 Overlay::PipeSpecs pipeSpecs;
2652 pipeSpecs.formatClass = isYuvBuffer(hnd) ?
2653 Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
2654 pipeSpecs.needsScaling = qhwc::needsScalingWithSplit(ctx, layer, mDpy);
2655 pipeSpecs.dpy = mDpy;
2656 pipeSpecs.mixer = Overlay::MIXER_LEFT;
2657 pipeSpecs.fb = false;
2658
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08002659 // Acquire pipe only for the updating half
2660 hwc_rect_t l_roi = ctx->listStats[mDpy].lRoi;
2661 hwc_rect_t r_roi = ctx->listStats[mDpy].rRoi;
2662
2663 if (dst.left < lSplit && isValidRect(getIntersection(dst, l_roi))) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002664 pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002665 if(pipe_info.lIndex == ovutils::OV_INVALID)
2666 return false;
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002667 }
2668
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08002669 if(dst.right > lSplit && isValidRect(getIntersection(dst, r_roi))) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002670 pipeSpecs.mixer = Overlay::MIXER_RIGHT;
2671 pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002672 if(pipe_info.rIndex == ovutils::OV_INVALID)
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002673 return false;
2674 }
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002675
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002676 return true;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002677}
2678
Saurabh Shah88e4d272013-09-03 13:31:29 -07002679bool MDPCompSplit::allocLayerPipes(hwc_context_t *ctx,
Saurabh Shahe51f8ca2013-05-06 17:26:16 -07002680 hwc_display_contents_1_t* list) {
Saurabh Shah8cc77712015-03-31 10:48:51 -07002681 for(uint32_t formatType = FORMAT_YUV; formatType < FORMAT_MAX;
2682 formatType++) {
2683 for(int index = 0 ; index < mCurrentFrame.layerCount; index++) {
2684 if(mCurrentFrame.isFBComposed[index]) continue;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002685
Saurabh Shah8cc77712015-03-31 10:48:51 -07002686 hwc_layer_1_t* layer = &list->hwLayers[index];
2687 private_handle_t *hnd = (private_handle_t *)layer->handle;
2688 if(formatType == FORMAT_YUV && !isYuvBuffer(hnd))
2689 continue;
2690 if(formatType == FORMAT_RGB && isYuvBuffer(hnd))
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002691 continue;
2692
Saurabh Shah8cc77712015-03-31 10:48:51 -07002693 hwc_rect_t dst = layer->displayFrame;
2694 const int lSplit = getLeftSplit(ctx, mDpy);
2695 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
2696 if((dst.left > lSplit)||(dst.right < lSplit)){
2697 if(allocSplitVGPipes(ctx, index)){
2698 continue;
2699 }
2700 }
2701 }
2702 //XXX: Check for forced 2D composition
2703 if(needs3DComposition(ctx, mDpy) && get3DFormat(hnd) != HAL_NO_3D)
2704 if(allocSplitVGPipes(ctx,index))
2705 continue;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002706
Saurabh Shah8cc77712015-03-31 10:48:51 -07002707 int mdpIndex = mCurrentFrame.layerToMDP[index];
2708 PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
2709 info.pipeInfo = new MdpPipeInfoSplit;
2710 info.rot = NULL;
2711 MdpPipeInfoSplit& pipe_info = *(MdpPipeInfoSplit*)info.pipeInfo;
2712
2713 if(!acquireMDPPipes(ctx, layer, pipe_info)) {
2714 ALOGD_IF(isDebug(), "%s: Unable to get pipe for layer %d of "\
2715 "format type %d", __FUNCTION__, index, formatType);
2716 return false;
2717 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002718 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002719 }
2720 return true;
2721}
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002722
radhakrishnac9a67412013-09-25 17:40:42 +05302723int MDPCompSplit::configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
2724 PipeLayerPair& PipeLayerPair) {
2725 const int lSplit = getLeftSplit(ctx, mDpy);
2726 hwc_rect_t dst = layer->displayFrame;
2727 if((dst.left > lSplit)||(dst.right < lSplit)){
2728 MdpYUVPipeInfo& mdp_info =
2729 *(static_cast<MdpYUVPipeInfo*>(PipeLayerPair.pipeInfo));
2730 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Justin Philipd6166602014-08-12 13:42:21 +05302731 eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
radhakrishnac9a67412013-09-25 17:40:42 +05302732 eDest lDest = mdp_info.lIndex;
2733 eDest rDest = mdp_info.rIndex;
2734
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002735 return configureSourceSplit(ctx, layer, mDpy, mdpFlagsL, zOrder,
radhakrishnac9a67412013-09-25 17:40:42 +05302736 lDest, rDest, &PipeLayerPair.rot);
2737 }
2738 else{
2739 return configure(ctx, layer, PipeLayerPair);
2740 }
2741}
2742
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002743/*
2744 * Configures pipe(s) for MDP composition
2745 */
Saurabh Shah88e4d272013-09-03 13:31:29 -07002746int MDPCompSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
Saurabh Shah67a38c32013-06-10 16:23:15 -07002747 PipeLayerPair& PipeLayerPair) {
Saurabh Shah88e4d272013-09-03 13:31:29 -07002748 MdpPipeInfoSplit& mdp_info =
2749 *(static_cast<MdpPipeInfoSplit*>(PipeLayerPair.pipeInfo));
Saurabh Shahacf10202013-02-26 10:15:15 -08002750 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Justin Philipd6166602014-08-12 13:42:21 +05302751 eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shahacf10202013-02-26 10:15:15 -08002752 eDest lDest = mdp_info.lIndex;
2753 eDest rDest = mdp_info.rIndex;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002754
2755 ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
Jeykumar Sankaran39305802014-12-12 17:55:57 -08002756 "dest_pipeR: %d",__FUNCTION__, layer, zOrder, lDest, rDest);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002757
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002758 return configureSplit(ctx, layer, mDpy, mdpFlagsL, zOrder, lDest,
Jeykumar Sankaran39305802014-12-12 17:55:57 -08002759 rDest, &PipeLayerPair.rot);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002760}
2761
Saurabh Shah88e4d272013-09-03 13:31:29 -07002762bool MDPCompSplit::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002763
Raj Kamal4393eaa2014-06-06 13:45:20 +05302764 if(!isEnabled() or !mModeOn) {
2765 ALOGD_IF(isDebug(),"%s: MDP Comp not enabled/configured", __FUNCTION__);
Prabhanjan Kandula08222fc2013-07-10 17:20:59 +05302766 return true;
2767 }
2768
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002769 overlay::Overlay& ov = *ctx->mOverlay;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002770 LayerProp *layerProp = ctx->layerProp[mDpy];
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002771
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002772 int numHwLayers = ctx->listStats[mDpy].numAppLayers;
2773 for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ )
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002774 {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002775 if(mCurrentFrame.isFBComposed[i]) continue;
2776
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002777 hwc_layer_1_t *layer = &list->hwLayers[i];
Saurabh Shahacf10202013-02-26 10:15:15 -08002778 private_handle_t *hnd = (private_handle_t *)layer->handle;
2779 if(!hnd) {
2780 ALOGE("%s handle null", __FUNCTION__);
2781 return false;
2782 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002783
2784 if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
2785 continue;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002786 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002787
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002788 int mdpIndex = mCurrentFrame.layerToMDP[i];
2789
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002790 if((isYUVSplitNeeded(hnd) && sEnableYUVsplit) ||
2791 (needs3DComposition(ctx, mDpy) && get3DFormat(hnd) != HAL_NO_3D))
radhakrishnac9a67412013-09-25 17:40:42 +05302792 {
2793 MdpYUVPipeInfo& pipe_info =
2794 *(MdpYUVPipeInfo*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
2795 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
2796 ovutils::eDest indexL = pipe_info.lIndex;
2797 ovutils::eDest indexR = pipe_info.rIndex;
2798 int fd = hnd->fd;
Praveena Pachipulusud9443c72014-02-17 10:42:28 +05302799 uint32_t offset = (uint32_t)hnd->offset;
radhakrishnac9a67412013-09-25 17:40:42 +05302800 if(rot) {
2801 rot->queueBuffer(fd, offset);
2802 fd = rot->getDstMemId();
2803 offset = rot->getDstOffset();
2804 }
2805 if(indexL != ovutils::OV_INVALID) {
2806 ovutils::eDest destL = (ovutils::eDest)indexL;
2807 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2808 using pipe: %d", __FUNCTION__, layer, hnd, indexL );
2809 if (!ov.queueBuffer(fd, offset, destL)) {
2810 ALOGE("%s: queueBuffer failed for display:%d",
2811 __FUNCTION__, mDpy);
2812 return false;
2813 }
2814 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002815
radhakrishnac9a67412013-09-25 17:40:42 +05302816 if(indexR != ovutils::OV_INVALID) {
2817 ovutils::eDest destR = (ovutils::eDest)indexR;
2818 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2819 using pipe: %d", __FUNCTION__, layer, hnd, indexR );
2820 if (!ov.queueBuffer(fd, offset, destR)) {
2821 ALOGE("%s: queueBuffer failed for display:%d",
2822 __FUNCTION__, mDpy);
2823 return false;
2824 }
Saurabh Shaha9da08f2013-07-03 13:27:53 -07002825 }
2826 }
radhakrishnac9a67412013-09-25 17:40:42 +05302827 else{
2828 MdpPipeInfoSplit& pipe_info =
2829 *(MdpPipeInfoSplit*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
2830 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
Saurabh Shaha9da08f2013-07-03 13:27:53 -07002831
radhakrishnac9a67412013-09-25 17:40:42 +05302832 ovutils::eDest indexL = pipe_info.lIndex;
2833 ovutils::eDest indexR = pipe_info.rIndex;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002834
radhakrishnac9a67412013-09-25 17:40:42 +05302835 int fd = hnd->fd;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002836 uint32_t offset = (uint32_t)hnd->offset;
2837 int index = ctx->mPtorInfo.getPTORArrayIndex(i);
2838 if (!mDpy && (index != -1)) {
2839 hnd = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
2840 fd = hnd->fd;
Sushil Chauhan875a92e2014-07-25 12:20:23 -07002841 offset = 0;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002842 }
radhakrishnac9a67412013-09-25 17:40:42 +05302843
Tatenda Chipeperekwa88fe6352014-04-14 10:36:06 -07002844 if(ctx->mAD->draw(ctx, fd, offset)) {
2845 fd = ctx->mAD->getDstFd();
2846 offset = ctx->mAD->getDstOffset();
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002847 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002848
radhakrishnac9a67412013-09-25 17:40:42 +05302849 if(rot) {
2850 rot->queueBuffer(fd, offset);
2851 fd = rot->getDstMemId();
2852 offset = rot->getDstOffset();
2853 }
2854
2855 //************* play left mixer **********
2856 if(indexL != ovutils::OV_INVALID) {
2857 ovutils::eDest destL = (ovutils::eDest)indexL;
2858 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2859 using pipe: %d", __FUNCTION__, layer, hnd, indexL );
2860 if (!ov.queueBuffer(fd, offset, destL)) {
2861 ALOGE("%s: queueBuffer failed for left mixer",
2862 __FUNCTION__);
2863 return false;
2864 }
2865 }
2866
2867 //************* play right mixer **********
2868 if(indexR != ovutils::OV_INVALID) {
2869 ovutils::eDest destR = (ovutils::eDest)indexR;
2870 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2871 using pipe: %d", __FUNCTION__, layer, hnd, indexR );
2872 if (!ov.queueBuffer(fd, offset, destR)) {
2873 ALOGE("%s: queueBuffer failed for right mixer",
2874 __FUNCTION__);
2875 return false;
2876 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002877 }
2878 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002879
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002880 layerProp[i].mFlags &= ~HWC_MDPCOMP;
2881 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002882
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002883 return true;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002884}
Saurabh Shahab47c692014-02-12 18:45:57 -08002885
2886//================MDPCompSrcSplit==============================================
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08002887
2888bool MDPCompSrcSplit::validateAndApplyROI(hwc_context_t *ctx,
2889 hwc_display_contents_1_t* list) {
2890 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
2891 hwc_rect_t visibleRect = ctx->listStats[mDpy].lRoi;
2892
2893 for(int i = numAppLayers - 1; i >= 0; i--) {
2894 if(!isValidRect(visibleRect)) {
2895 mCurrentFrame.drop[i] = true;
2896 mCurrentFrame.dropCount++;
2897 continue;
2898 }
2899
2900 const hwc_layer_1_t* layer = &list->hwLayers[i];
2901 hwc_rect_t dstRect = layer->displayFrame;
2902 hwc_rect_t res = getIntersection(visibleRect, dstRect);
2903
2904 if(!isValidRect(res)) {
2905 mCurrentFrame.drop[i] = true;
2906 mCurrentFrame.dropCount++;
2907 } else {
2908 /* Reset frame ROI when any layer which needs scaling also needs ROI
2909 * cropping */
2910 if(!isSameRect(res, dstRect) && needsScaling (layer)) {
2911 ALOGI("%s: Resetting ROI due to scaling", __FUNCTION__);
2912 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
2913 mCurrentFrame.dropCount = 0;
2914 return false;
2915 }
2916
2917 /* deduct any opaque region from visibleRect */
2918 if (layer->blending == HWC_BLENDING_NONE &&
2919 layer->planeAlpha == 0xFF)
2920 visibleRect = deductRect(visibleRect, res);
2921 }
2922 }
2923 return true;
2924}
2925
2926/*
2927 * HW Limitation: ping pong split can always split the ping pong output
2928 * equally across two DSI's. So the ROI programmed should be of equal width
2929 * for both the halves
2930 */
2931void MDPCompSrcSplit::generateROI(hwc_context_t *ctx,
2932 hwc_display_contents_1_t* list) {
2933 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
2934
2935
2936 if(!canPartialUpdate(ctx, list))
2937 return;
2938
2939 struct hwc_rect roi = (struct hwc_rect){0, 0, 0, 0};
2940 hwc_rect fullFrame = (struct hwc_rect) {0, 0,(int)ctx->dpyAttr[mDpy].xres,
2941 (int)ctx->dpyAttr[mDpy].yres};
2942
2943 for(int index = 0; index < numAppLayers; index++ ) {
2944 hwc_layer_1_t* layer = &list->hwLayers[index];
2945
2946 // If we have a RGB layer which needs rotation, no partial update
2947 if(!isYuvBuffer((private_handle_t *)layer->handle) && layer->transform)
2948 return;
2949
2950 if ((mCachedFrame.hnd[index] != layer->handle) ||
2951 isYuvBuffer((private_handle_t *)layer->handle)) {
2952 hwc_rect_t dst = layer->displayFrame;
2953 hwc_rect_t updatingRect = dst;
2954
2955#ifdef QCOM_BSP
2956 if(!needsScaling(layer) && !layer->transform)
2957 {
2958 hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
2959 int x_off = dst.left - src.left;
2960 int y_off = dst.top - src.top;
2961 updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
2962 }
2963#endif
2964
2965 roi = getUnion(roi, updatingRect);
2966 }
2967 }
2968
2969 /* No layer is updating. Still SF wants a refresh.*/
2970 if(!isValidRect(roi))
2971 return;
2972
2973 roi = expandROIFromMidPoint(roi, fullFrame);
2974
2975 hwc_rect lFrame = fullFrame;
2976 lFrame.right /= 2;
2977 hwc_rect lRoi = getIntersection(roi, lFrame);
2978
2979 // Align ROI coordinates to panel restrictions
2980 lRoi = getSanitizeROI(lRoi, lFrame);
2981
2982 hwc_rect rFrame = fullFrame;
2983 rFrame.left = lFrame.right;
2984 hwc_rect rRoi = getIntersection(roi, rFrame);
2985
2986 // Align ROI coordinates to panel restrictions
2987 rRoi = getSanitizeROI(rRoi, rFrame);
2988
2989 roi = getUnion(lRoi, rRoi);
2990
2991 ctx->listStats[mDpy].lRoi = roi;
2992 if(!validateAndApplyROI(ctx, list))
2993 resetROI(ctx, mDpy);
2994
2995 ALOGD_IF(isDebug(),"%s: generated ROI: [%d, %d, %d, %d] [%d, %d, %d, %d]",
2996 __FUNCTION__,
2997 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
2998 ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom,
2999 ctx->listStats[mDpy].rRoi.left, ctx->listStats[mDpy].rRoi.top,
3000 ctx->listStats[mDpy].rRoi.right, ctx->listStats[mDpy].rRoi.bottom);
3001}
3002
Saurabh Shahab47c692014-02-12 18:45:57 -08003003bool MDPCompSrcSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
Saurabh Shahc62f3982014-03-05 14:28:26 -08003004 MdpPipeInfoSplit& pipe_info) {
Saurabh Shahab47c692014-02-12 18:45:57 -08003005 private_handle_t *hnd = (private_handle_t *)layer->handle;
3006 hwc_rect_t dst = layer->displayFrame;
3007 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
3008 pipe_info.lIndex = ovutils::OV_INVALID;
3009 pipe_info.rIndex = ovutils::OV_INVALID;
3010
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08003011 if(qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() && !mDpy)
3012 trimAgainstROI(ctx,crop, dst);
3013
Saurabh Shahab47c692014-02-12 18:45:57 -08003014 //If 2 pipes are staged on a single stage of a mixer, then the left pipe
3015 //should have a higher priority than the right one. Pipe priorities are
3016 //starting with VG0, VG1 ... , RGB0 ..., DMA1
Saurabh Shahab47c692014-02-12 18:45:57 -08003017
Saurabh Shahc62f3982014-03-05 14:28:26 -08003018 Overlay::PipeSpecs pipeSpecs;
3019 pipeSpecs.formatClass = isYuvBuffer(hnd) ?
3020 Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
3021 pipeSpecs.needsScaling = qhwc::needsScaling(layer);
3022 pipeSpecs.dpy = mDpy;
3023 pipeSpecs.fb = false;
3024
Saurabh Shahab47c692014-02-12 18:45:57 -08003025 //1 pipe by default for a layer
Saurabh Shahc62f3982014-03-05 14:28:26 -08003026 pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahab47c692014-02-12 18:45:57 -08003027 if(pipe_info.lIndex == ovutils::OV_INVALID) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08003028 return false;
Saurabh Shahab47c692014-02-12 18:45:57 -08003029 }
3030
Saurabh Shahea7a01d2014-05-22 17:45:36 -07003031 /* Use 2 pipes IF
3032 a) Layer's crop width is > 2048 or
3033 b) Layer's dest width > 2048 or
3034 c) On primary, driver has indicated with caps to split always. This is
3035 based on an empirically derived value of panel height. Applied only
3036 if the layer's width is > mixer's width
3037 */
3038
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +05303039 MDPVersion& mdpHw = MDPVersion::getInstance();
Saurabh Shahea7a01d2014-05-22 17:45:36 -07003040 bool primarySplitAlways = (mDpy == HWC_DISPLAY_PRIMARY) and
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +05303041 mdpHw.isSrcSplitAlways();
Saurabh Shah514759d2014-11-11 18:02:24 -08003042 const uint32_t lSplit = getLeftSplit(ctx, mDpy);
3043 const uint32_t dstWidth = dst.right - dst.left;
3044 const uint32_t dstHeight = dst.bottom - dst.top;
Saurabh Shah05f4e222015-02-05 14:36:22 -08003045 uint32_t cropWidth = has90Transform(layer) ? crop.bottom - crop.top :
Saurabh Shah189f23d2014-09-26 17:21:00 -07003046 crop.right - crop.left;
Saurabh Shah05f4e222015-02-05 14:36:22 -08003047 uint32_t cropHeight = has90Transform(layer) ? crop.right - crop.left :
Saurabh Shah514759d2014-11-11 18:02:24 -08003048 crop.bottom - crop.top;
3049 //Approximation to actual clock, ignoring the common factors in pipe and
3050 //mixer cases like line_time
3051 const uint32_t layerClock = getLayerClock(dstWidth, dstHeight, cropHeight);
3052 const uint32_t mixerClock = lSplit;
Saurabh Shahea7a01d2014-05-22 17:45:36 -07003053
Saurabh Shah05f4e222015-02-05 14:36:22 -08003054 const uint32_t downscale = getRotDownscale(ctx, layer);
3055 if(downscale) {
3056 cropWidth /= downscale;
3057 cropHeight /= downscale;
3058 }
3059
Jeykumar Sankaran39305802014-12-12 17:55:57 -08003060 if(dstWidth > mdpHw.getMaxPipeWidth() or
3061 cropWidth > mdpHw.getMaxPipeWidth() or
Saurabh Shah514759d2014-11-11 18:02:24 -08003062 (primarySplitAlways and
3063 (cropWidth > lSplit or layerClock > mixerClock))) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08003064 pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahab47c692014-02-12 18:45:57 -08003065 if(pipe_info.rIndex == ovutils::OV_INVALID) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08003066 return false;
Saurabh Shahdd8237a2014-02-28 14:29:09 -08003067 }
3068
Jeykumar Sankaran89e23ab2015-01-28 15:57:46 -08003069 if(ctx->mOverlay->needsPrioritySwap(pipe_info.lIndex,
3070 pipe_info.rIndex)) {
Saurabh Shahdd8237a2014-02-28 14:29:09 -08003071 qhwc::swap(pipe_info.lIndex, pipe_info.rIndex);
Saurabh Shahab47c692014-02-12 18:45:57 -08003072 }
3073 }
3074
3075 return true;
3076}
3077
Saurabh Shahab47c692014-02-12 18:45:57 -08003078int MDPCompSrcSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
3079 PipeLayerPair& PipeLayerPair) {
3080 private_handle_t *hnd = (private_handle_t *)layer->handle;
3081 if(!hnd) {
3082 ALOGE("%s: layer handle is NULL", __FUNCTION__);
3083 return -1;
3084 }
3085 MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
3086 MdpPipeInfoSplit& mdp_info =
3087 *(static_cast<MdpPipeInfoSplit*>(PipeLayerPair.pipeInfo));
3088 Rotator **rot = &PipeLayerPair.rot;
3089 eZorder z = static_cast<eZorder>(mdp_info.zOrder);
Saurabh Shahab47c692014-02-12 18:45:57 -08003090 eDest lDest = mdp_info.lIndex;
3091 eDest rDest = mdp_info.rIndex;
3092 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
3093 hwc_rect_t dst = layer->displayFrame;
3094 int transform = layer->transform;
3095 eTransform orient = static_cast<eTransform>(transform);
Saurabh Shahab47c692014-02-12 18:45:57 -08003096 int rotFlags = ROT_FLAGS_NONE;
Sushil Chauhan65e26302015-01-14 10:48:57 -08003097 uint32_t format = ovutils::getMdpFormat(hnd->format, hnd->flags);
Saurabh Shahab47c692014-02-12 18:45:57 -08003098 Whf whf(getWidth(hnd), getHeight(hnd), format, hnd->size);
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05003099 eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shahab47c692014-02-12 18:45:57 -08003100
3101 ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
3102 "dest_pipeR: %d",__FUNCTION__, layer, z, lDest, rDest);
3103
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08003104 if(qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() && !mDpy) {
3105 /* MDP driver crops layer coordinates against ROI in Non-Split
3106 * and Split MDP comp. But HWC needs to crop them for source split.
3107 * Reason: 1) Source split is efficient only when the final effective
3108 * load is distributed evenly across mixers.
3109 * 2) We have to know the effective width of the layer that
3110 * the ROI needs to find the no. of pipes the layer needs.
3111 */
3112 trimAgainstROI(ctx, crop, dst);
3113 }
3114
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05003115 if(needs3DComposition(ctx, mDpy) &&
3116 get3DFormat(hnd) != HAL_NO_3D){
3117 return configure3DVideo(ctx, layer, mDpy, mdpFlags, z, lDest,
3118 rDest, &PipeLayerPair.rot);
3119 }
3120
Saurabh Shahab47c692014-02-12 18:45:57 -08003121 // Handle R/B swap
3122 if (layer->flags & HWC_FORMAT_RB_SWAP) {
3123 if (hnd->format == HAL_PIXEL_FORMAT_RGBA_8888)
3124 whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRA_8888);
3125 else if (hnd->format == HAL_PIXEL_FORMAT_RGBX_8888)
3126 whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
3127 }
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07003128 // update source crop and destination position of AIV video layer.
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07003129 if(ctx->listStats[mDpy].mAIVVideoMode && isYuvBuffer(hnd)) {
3130 updateCoordinates(ctx, crop, dst, mDpy);
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07003131 }
Ramkumar Radhakrishnana5c72872014-08-28 19:04:18 -07003132 /* Calculate the external display position based on MDP downscale,
3133 ActionSafe, and extorientation features. */
3134 calcExtDisplayPosition(ctx, hnd, mDpy, crop, dst, transform, orient);
Saurabh Shahab47c692014-02-12 18:45:57 -08003135
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003136 int downscale = getRotDownscale(ctx, layer);
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003137 setMdpFlags(ctx, layer, mdpFlags, downscale, transform);
Saurabh Shahab47c692014-02-12 18:45:57 -08003138
3139 if(lDest != OV_INVALID && rDest != OV_INVALID) {
3140 //Enable overfetch
Saurabh Shah97e2d802014-04-14 18:03:54 -07003141 setMdpFlags(mdpFlags, OV_MDSS_MDP_DUAL_PIPE);
Saurabh Shahab47c692014-02-12 18:45:57 -08003142 }
3143
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003144 if((has90Transform(layer) or downscale) and isRotationDoable(ctx, hnd)) {
Saurabh Shahab47c692014-02-12 18:45:57 -08003145 (*rot) = ctx->mRotMgr->getNext();
3146 if((*rot) == NULL) return -1;
Saurabh Shah39240c92014-03-31 10:31:42 -07003147 ctx->mLayerRotMap[mDpy]->add(layer, *rot);
Saurabh Shah1bd5b6f2014-05-19 12:23:13 -07003148 //If the video is using a single pipe, enable BWC
3149 if(rDest == OV_INVALID) {
Saurabh Shahcd018352014-11-11 13:54:19 -08003150 BwcPM::setBwc(ctx, mDpy, hnd, crop, dst, transform, downscale,
3151 mdpFlags);
Saurabh Shah1bd5b6f2014-05-19 12:23:13 -07003152 }
radhakrishnab8e2c952015-06-04 16:09:16 +05303153 uint32_t frame_rate = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].refreshRate;
3154 if(!mDpy && !isSecondaryConnected(ctx)) {
3155 if(metadata && (metadata->operation & UPDATE_REFRESH_RATE))
3156 frame_rate = metadata->refreshrate;
3157 }
Saurabh Shahab47c692014-02-12 18:45:57 -08003158 //Configure rotator for pre-rotation
radhakrishnab8e2c952015-06-04 16:09:16 +05303159 if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale,
3160 frame_rate) < 0) {
Saurabh Shahab47c692014-02-12 18:45:57 -08003161 ALOGE("%s: configRotator failed!", __FUNCTION__);
3162 return -1;
3163 }
Saurabh Shah8ec9b5e2014-06-30 14:37:17 -07003164 updateSource(orient, whf, crop, *rot);
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003165 rotFlags |= ovutils::ROT_PREROTATED;
Saurabh Shahab47c692014-02-12 18:45:57 -08003166 }
3167
3168 //If 2 pipes being used, divide layer into half, crop and dst
3169 hwc_rect_t cropL = crop;
3170 hwc_rect_t cropR = crop;
3171 hwc_rect_t dstL = dst;
3172 hwc_rect_t dstR = dst;
3173 if(lDest != OV_INVALID && rDest != OV_INVALID) {
3174 cropL.right = (crop.right + crop.left) / 2;
3175 cropR.left = cropL.right;
3176 sanitizeSourceCrop(cropL, cropR, hnd);
3177
Saurabh Shahb729b192014-08-15 18:04:24 -07003178 bool cropSwap = false;
Saurabh Shahab47c692014-02-12 18:45:57 -08003179 //Swap crops on H flip since 2 pipes are being used
3180 if((orient & OVERLAY_TRANSFORM_FLIP_H) && (*rot) == NULL) {
3181 hwc_rect_t tmp = cropL;
3182 cropL = cropR;
3183 cropR = tmp;
Saurabh Shahb729b192014-08-15 18:04:24 -07003184 cropSwap = true;
Saurabh Shahab47c692014-02-12 18:45:57 -08003185 }
3186
Saurabh Shahb729b192014-08-15 18:04:24 -07003187 //cropSwap trick: If the src and dst widths are both odd, let us say
3188 //2507, then splitting both into half would cause left width to be 1253
3189 //and right 1254. If crop is swapped because of H flip, this will cause
3190 //left crop width to be 1254, whereas left dst width remains 1253, thus
3191 //inducing a scaling that is unaccounted for. To overcome that we add 1
3192 //to the dst width if there is a cropSwap. So if the original width was
3193 //2507, the left dst width will be 1254. Even if the original width was
3194 //even for ex: 2508, the left dst width will still remain 1254.
3195 dstL.right = (dst.right + dst.left + cropSwap) / 2;
Saurabh Shahab47c692014-02-12 18:45:57 -08003196 dstR.left = dstL.right;
3197 }
3198
3199 //For the mdp, since either we are pre-rotating or MDP does flips
3200 orient = OVERLAY_TRANSFORM_0;
3201 transform = 0;
3202
3203 //configure left pipe
3204 if(lDest != OV_INVALID) {
Saurabh Shah2c8ad052014-08-15 13:27:46 -07003205 PipeArgs pargL(mdpFlags, whf, z,
Saurabh Shahab47c692014-02-12 18:45:57 -08003206 static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
3207 (ovutils::eBlending) getBlending(layer->blending));
3208
3209 if(configMdp(ctx->mOverlay, pargL, orient,
3210 cropL, dstL, metadata, lDest) < 0) {
3211 ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
3212 return -1;
3213 }
3214 }
3215
3216 //configure right pipe
3217 if(rDest != OV_INVALID) {
Saurabh Shah2c8ad052014-08-15 13:27:46 -07003218 PipeArgs pargR(mdpFlags, whf, z,
Saurabh Shahab47c692014-02-12 18:45:57 -08003219 static_cast<eRotFlags>(rotFlags),
3220 layer->planeAlpha,
3221 (ovutils::eBlending) getBlending(layer->blending));
3222 if(configMdp(ctx->mOverlay, pargR, orient,
3223 cropR, dstR, metadata, rDest) < 0) {
3224 ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
3225 return -1;
3226 }
3227 }
3228
3229 return 0;
3230}
3231
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -08003232bool MDPComp::getPartialUpdatePref(hwc_context_t *ctx) {
3233 Locker::Autolock _l(ctx->mDrawLock);
3234 const int fbNum = Overlay::getFbForDpy(Overlay::DPY_PRIMARY);
3235 char path[MAX_SYSFS_FILE_PATH];
3236 snprintf (path, sizeof(path), "sys/class/graphics/fb%d/dyn_pu", fbNum);
3237 int fd = open(path, O_RDONLY);
3238 if(fd < 0) {
3239 ALOGE("%s: Failed to open sysfd node: %s", __FUNCTION__, path);
3240 return -1;
3241 }
3242 char value[4];
3243 ssize_t size_read = read(fd, value, sizeof(value)-1);
3244 if(size_read <= 0) {
3245 ALOGE("%s: Failed to read sysfd node: %s", __FUNCTION__, path);
3246 close(fd);
3247 return -1;
3248 }
3249 close(fd);
3250 value[size_read] = '\0';
3251 return atoi(value);
3252}
3253
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003254int MDPComp::setPartialUpdatePref(hwc_context_t *ctx, bool enable) {
3255 Locker::Autolock _l(ctx->mDrawLock);
3256 const int fbNum = Overlay::getFbForDpy(Overlay::DPY_PRIMARY);
3257 char path[MAX_SYSFS_FILE_PATH];
3258 snprintf (path, sizeof(path), "sys/class/graphics/fb%d/dyn_pu", fbNum);
3259 int fd = open(path, O_WRONLY);
3260 if(fd < 0) {
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -08003261 ALOGE("%s: Failed to open sysfd node: %s", __FUNCTION__, path);
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003262 return -1;
3263 }
3264 char value[4];
3265 snprintf(value, sizeof(value), "%d", (int)enable);
3266 ssize_t ret = write(fd, value, strlen(value));
3267 if(ret <= 0) {
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -08003268 ALOGE("%s: Failed to write to sysfd nodes: %s", __FUNCTION__, path);
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003269 close(fd);
3270 return -1;
3271 }
3272 close(fd);
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003273 return 0;
3274}
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08003275
3276bool MDPComp::loadPerfLib() {
3277 char perfLibPath[PROPERTY_VALUE_MAX] = {0};
3278 bool success = false;
3279 if((property_get("ro.vendor.extension_library", perfLibPath, NULL) <= 0)) {
3280 ALOGE("vendor library not set in ro.vendor.extension_library");
3281 return false;
3282 }
3283
3284 sLibPerfHint = dlopen(perfLibPath, RTLD_NOW);
3285 if(sLibPerfHint) {
3286 *(void **)&sPerfLockAcquire = dlsym(sLibPerfHint, "perf_lock_acq");
3287 *(void **)&sPerfLockRelease = dlsym(sLibPerfHint, "perf_lock_rel");
3288 if (!sPerfLockAcquire || !sPerfLockRelease) {
3289 ALOGE("Failed to load symbols for perfLock");
3290 dlclose(sLibPerfHint);
3291 sLibPerfHint = NULL;
3292 return false;
3293 }
3294 success = true;
3295 ALOGI("Successfully Loaded perf hint API's");
3296 } else {
3297 ALOGE("Failed to open %s : %s", perfLibPath, dlerror());
3298 }
3299 return success;
3300}
3301
3302void MDPComp::setPerfHint(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
3303 if ((sPerfHintWindow < 0) || mDpy || !sLibPerfHint) {
3304 return;
3305 }
3306 static int count = sPerfHintWindow;
3307 static int perflockFlag = 0;
3308
3309 /* Send hint to mpctl when single layer is updated
3310 * for a successful number of windows. Hint release
3311 * happens immediately upon multiple layer update.
3312 */
3313 if (onlyVideosUpdating(ctx, list)) {
3314 if(count) {
3315 count--;
3316 }
3317 } else {
3318 if (perflockFlag) {
3319 perflockFlag = 0;
3320 sPerfLockRelease(sPerfLockHandle);
3321 }
3322 count = sPerfHintWindow;
3323 }
3324 if (count == 0 && !perflockFlag) {
3325 int perfHint = 0x4501; // 45-display layer hint, 01-Enable
3326 sPerfLockHandle = sPerfLockAcquire(0 /*handle*/, 0/*duration*/,
3327 &perfHint, sizeof(perfHint)/sizeof(int));
Arun Kumar K.R8b927022015-02-24 12:34:21 -08003328 if(sPerfLockHandle > 0) {
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08003329 perflockFlag = 1;
3330 }
3331 }
3332}
3333
Naseer Ahmed7c958d42012-07-31 18:57:03 -07003334}; //namespace
3335