blob: fdd7f0ff027c7df34f5585f2a513b4d1f4e435e7 [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;
58
Saurabh Shah8cc77712015-03-31 10:48:51 -070059enum AllocOrder { FORMAT_YUV, FORMAT_RGB, FORMAT_MAX };
60
Saurabh Shah88e4d272013-09-03 13:31:29 -070061MDPComp* MDPComp::getObject(hwc_context_t *ctx, const int& dpy) {
Saurabh Shah60e8bde2014-04-30 14:46:03 -070062 if(qdutils::MDPVersion::getInstance().isSrcSplit()) {
63 sSrcSplitEnabled = true;
64 return new MDPCompSrcSplit(dpy);
65 } else if(isDisplaySplit(ctx, dpy)) {
Saurabh Shah88e4d272013-09-03 13:31:29 -070066 return new MDPCompSplit(dpy);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -080067 }
Saurabh Shah88e4d272013-09-03 13:31:29 -070068 return new MDPCompNonSplit(dpy);
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -080069}
70
Jeykumar Sankaran85977e32013-02-25 17:06:08 -080071MDPComp::MDPComp(int dpy):mDpy(dpy){};
72
Jeykumar Sankaran6850ac62014-05-27 10:07:26 -070073void MDPComp::dump(android::String8& buf, hwc_context_t *ctx)
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -080074{
Jeykumar Sankaran3c6bb042013-08-15 14:01:04 -070075 if(mCurrentFrame.layerCount > MAX_NUM_APP_LAYERS)
76 return;
77
Jeykumar Sankaran85977e32013-02-25 17:06:08 -080078 dumpsys_log(buf,"HWC Map for Dpy: %s \n",
Jeykumar Sankaran27dee262013-08-01 17:09:54 -070079 (mDpy == 0) ? "\"PRIMARY\"" :
80 (mDpy == 1) ? "\"EXTERNAL\"" : "\"VIRTUAL\"");
Saurabh Shahe9bc60f2013-08-29 12:58:06 -070081 dumpsys_log(buf,"CURR_FRAME: layerCount:%2d mdpCount:%2d "
Arun Kumar K.R00b84792015-03-27 11:28:36 -070082 "fbCount:%2d dropCount:%2d\n", mCurrentFrame.layerCount,
83 mCurrentFrame.mdpCount, mCurrentFrame.fbCount, mCurrentFrame.dropCount);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -080084 dumpsys_log(buf,"needsFBRedraw:%3s pipesUsed:%2d MaxPipesPerMixer: %d \n",
85 (mCurrentFrame.needsRedraw? "YES" : "NO"),
86 mCurrentFrame.mdpCount, sMaxPipesPerMixer);
Jeykumar Sankaran6850ac62014-05-27 10:07:26 -070087 if(isDisplaySplit(ctx, mDpy)) {
88 dumpsys_log(buf, "Programmed ROI's: Left: [%d, %d, %d, %d] "
89 "Right: [%d, %d, %d, %d] \n",
90 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
91 ctx->listStats[mDpy].lRoi.right,
92 ctx->listStats[mDpy].lRoi.bottom,
93 ctx->listStats[mDpy].rRoi.left,ctx->listStats[mDpy].rRoi.top,
94 ctx->listStats[mDpy].rRoi.right,
95 ctx->listStats[mDpy].rRoi.bottom);
96 } else {
97 dumpsys_log(buf, "Programmed ROI: [%d, %d, %d, %d] \n",
98 ctx->listStats[mDpy].lRoi.left,ctx->listStats[mDpy].lRoi.top,
99 ctx->listStats[mDpy].lRoi.right,
100 ctx->listStats[mDpy].lRoi.bottom);
101 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800102 dumpsys_log(buf," --------------------------------------------- \n");
103 dumpsys_log(buf," listIdx | cached? | mdpIndex | comptype | Z \n");
104 dumpsys_log(buf," --------------------------------------------- \n");
105 for(int index = 0; index < mCurrentFrame.layerCount; index++ )
106 dumpsys_log(buf," %7d | %7s | %8d | %9s | %2d \n",
107 index,
108 (mCurrentFrame.isFBComposed[index] ? "YES" : "NO"),
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700109 mCurrentFrame.layerToMDP[index],
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800110 (mCurrentFrame.isFBComposed[index] ?
Arun Kumar K.R00b84792015-03-27 11:28:36 -0700111 (mCurrentFrame.drop[index] ?
112 ((mCurrentFrame.hwCursorIndex == index) ? "CURSOR": "DROP"):
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700113 (mCurrentFrame.needsRedraw ? "GLES" : "CACHE")) : "MDP"),
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800114 (mCurrentFrame.isFBComposed[index] ? mCurrentFrame.fbZ :
115 mCurrentFrame.mdpToLayer[mCurrentFrame.layerToMDP[index]].pipeInfo->zOrder));
116 dumpsys_log(buf,"\n");
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800117}
118
119bool MDPComp::init(hwc_context_t *ctx) {
120
121 if(!ctx) {
122 ALOGE("%s: Invalid hwc context!!",__FUNCTION__);
123 return false;
124 }
125
Saurabh Shah59562ff2014-09-30 16:13:12 -0700126 char property[PROPERTY_VALUE_MAX] = {0};
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800127
128 sEnabled = false;
Dileep Kumar Reddid8e601d2014-10-28 18:20:43 +0530129 if((ctx->mMDP.version >= qdutils::MDP_V4_0) &&
130 (property_get("persist.hwc.mdpcomp.enable", property, NULL) > 0) &&
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800131 (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
132 (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800133 sEnabled = true;
134 }
135
Jeykumar Sankaran24c199d2013-05-24 09:40:36 -0700136 sEnableMixedMode = true;
137 if((property_get("debug.mdpcomp.mixedmode.disable", property, NULL) > 0) &&
138 (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
139 (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
140 sEnableMixedMode = false;
141 }
142
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700143 qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
144
Saurabh Shah2fd8a252014-12-05 13:49:53 -0800145 sMaxPipesPerMixer = (int)mdpVersion.getBlendStages();
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700146 if(property_get("persist.hwc.mdpcomp.maxpermixer", property, "-1") > 0) {
Saurabh Shah85234ec2013-04-12 17:09:00 -0700147 int val = atoi(property);
148 if(val >= 0)
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700149 sMaxPipesPerMixer = min(val, sMaxPipesPerMixer);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800150 }
151
Saurabh Shahacec8e42014-11-25 11:07:04 -0800152 /* Maximum layers allowed to use MDP on secondary panels. If property
153 * doesn't exist, default to 1. Using the property it can be set to 0 or
154 * more.
155 */
156 if(property_get("persist.hwc.maxseclayers", property, "1") > 0) {
157 int val = atoi(property);
158 sMaxSecLayers = (val >= 0) ? val : 1;
159 sMaxSecLayers = min(sMaxSecLayers, sMaxPipesPerMixer);
160 }
161
Naseer Ahmedf40f2c82013-08-14 16:42:40 -0400162 if(ctx->mMDP.panel != MIPI_CMD_PANEL) {
Saurabh Shah59562ff2014-09-30 16:13:12 -0700163 sIdleInvalidator = IdleInvalidator::getInstance();
164 if(sIdleInvalidator->init(timeout_handler, ctx) < 0) {
165 delete sIdleInvalidator;
166 sIdleInvalidator = NULL;
Naseer Ahmedf40f2c82013-08-14 16:42:40 -0400167 }
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800168 }
radhakrishnac9a67412013-09-25 17:40:42 +0530169
Saurabh Shah7c727642014-06-02 15:47:14 -0700170 if(!qdutils::MDPVersion::getInstance().isSrcSplit() &&
Saurabh Shahc46cf9d2014-07-02 15:22:34 -0700171 !qdutils::MDPVersion::getInstance().isRotDownscaleEnabled() &&
Saurabh Shah7c727642014-06-02 15:47:14 -0700172 property_get("persist.mdpcomp.4k2kSplit", property, "0") > 0 &&
173 (!strncmp(property, "1", PROPERTY_VALUE_MAX) ||
174 !strncasecmp(property,"true", PROPERTY_VALUE_MAX))) {
Raj Kamal389d6e32014-08-04 14:43:24 +0530175 sEnableYUVsplit = true;
radhakrishnac9a67412013-09-25 17:40:42 +0530176 }
Sushil Chauhandefd3522014-05-13 18:17:12 -0700177
Dileep Kumar Reddic6ef3472014-09-24 19:07:08 +0530178 bool defaultPTOR = false;
179 //Enable PTOR when "persist.hwc.ptor.enable" is not defined for
180 //8x16 and 8x39 targets by default
181 if((property_get("persist.hwc.ptor.enable", property, NULL) <= 0) &&
182 (qdutils::MDPVersion::getInstance().is8x16() ||
183 qdutils::MDPVersion::getInstance().is8x39())) {
184 defaultPTOR = true;
185 }
186
187 if (defaultPTOR || (!strncasecmp(property, "true", PROPERTY_VALUE_MAX)) ||
188 (!strncmp(property, "1", PROPERTY_VALUE_MAX ))) {
Sushil Chauhandefd3522014-05-13 18:17:12 -0700189 ctx->mCopyBit[HWC_DISPLAY_PRIMARY] = new CopyBit(ctx,
190 HWC_DISPLAY_PRIMARY);
191 }
192
Dileep Kumar Reddi4070e932014-09-30 09:00:57 +0530193 if((property_get("persist.mdp3.partialUpdate", property, NULL) <= 0) &&
194 (ctx->mMDP.version == qdutils::MDP_V3_0_5)) {
195 enablePartialUpdateForMDP3 = true;
196 }
197
198 if(!enablePartialUpdateForMDP3 &&
199 (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
200 (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
201 enablePartialUpdateForMDP3 = true;
202 }
203
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -0800204 sIsPartialUpdateActive = getPartialUpdatePref(ctx);
205
Arun Kumar K.R299bcda2014-12-18 19:36:40 -0800206 if(property_get("persist.mdpcomp_perfhint", property, "-1") > 0) {
207 int val = atoi(property);
208 if(val > 0 && loadPerfLib()) {
209 sPerfHintWindow = val;
210 ALOGI("PerfHintWindow = %d", sPerfHintWindow);
211 }
212 }
213
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700214 return true;
215}
216
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800217void MDPComp::reset(hwc_context_t *ctx) {
218 const int numLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shah2a4eb1b2013-07-22 16:33:23 -0700219 mCurrentFrame.reset(numLayers);
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800220 ctx->mOverlay->clear(mDpy);
221 ctx->mLayerRotMap[mDpy]->clear();
Saurabh Shah2a4eb1b2013-07-22 16:33:23 -0700222}
223
Raj Kamal4393eaa2014-06-06 13:45:20 +0530224void MDPComp::reset() {
Raj Kamalfdfdddf2015-03-16 21:59:25 +0530225 mPrevModeOn = mModeOn;
Raj Kamal4393eaa2014-06-06 13:45:20 +0530226 mModeOn = false;
227}
228
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700229void MDPComp::timeout_handler(void *udata) {
230 struct hwc_context_t* ctx = (struct hwc_context_t*)(udata);
Raj Kamalfdfdddf2015-03-16 21:59:25 +0530231 bool handleTimeout = false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700232
233 if(!ctx) {
234 ALOGE("%s: received empty data in timer callback", __FUNCTION__);
235 return;
236 }
Raj Kamal58b31a02014-12-16 15:53:53 +0530237
238 ctx->mDrawLock.lock();
Raj Kamalfdfdddf2015-03-16 21:59:25 +0530239
240 /* Handle timeout event only if the previous composition
241 on any display is MDP or MIXED*/
242 for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
243 if(ctx->mMDPComp[i])
244 handleTimeout =
245 ctx->mMDPComp[i]->isMDPComp() || handleTimeout;
246 }
247
248 if(!handleTimeout) {
Ramkumar Radhakrishnan92abb4f2014-02-06 21:31:29 -0800249 ALOGD_IF(isDebug(), "%s:Do not handle this timeout", __FUNCTION__);
Raj Kamal58b31a02014-12-16 15:53:53 +0530250 ctx->mDrawLock.unlock();
Ramkumar Radhakrishnan92abb4f2014-02-06 21:31:29 -0800251 return;
252 }
Jesse Hall3be78d92012-08-21 15:12:23 -0700253 if(!ctx->proc) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700254 ALOGE("%s: HWC proc not registered", __FUNCTION__);
Raj Kamal58b31a02014-12-16 15:53:53 +0530255 ctx->mDrawLock.unlock();
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700256 return;
257 }
258 sIdleFallBack = true;
Raj Kamal58b31a02014-12-16 15:53:53 +0530259 ctx->mDrawLock.unlock();
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700260 /* Trigger SF to redraw the current frame */
Jesse Hall3be78d92012-08-21 15:12:23 -0700261 ctx->proc->invalidate(ctx->proc);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700262}
263
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700264void MDPComp::setMaxPipesPerMixer(const uint32_t value) {
265 qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
Saurabh Shah2fd8a252014-12-05 13:49:53 -0800266 uint32_t maxSupported = (int)mdpVersion.getBlendStages();
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700267 if(value > maxSupported) {
268 ALOGW("%s: Input exceeds max value supported. Setting to"
269 "max value: %d", __FUNCTION__, maxSupported);
270 }
271 sMaxPipesPerMixer = min(value, maxSupported);
272}
273
Saurabh Shah59562ff2014-09-30 16:13:12 -0700274void MDPComp::setIdleTimeout(const uint32_t& timeout) {
275 enum { ONE_REFRESH_PERIOD_MS = 17, ONE_BILLION_MS = 1000000000 };
276
277 if(sIdleInvalidator) {
278 if(timeout <= ONE_REFRESH_PERIOD_MS) {
279 //If the specified timeout is < 1 draw cycle worth, "virtually"
280 //disable idle timeout. The ideal way for clients to disable
281 //timeout is to set it to 0
282 sIdleInvalidator->setIdleTimeout(ONE_BILLION_MS);
283 ALOGI("Disabled idle timeout");
284 return;
285 }
286 sIdleInvalidator->setIdleTimeout(timeout);
287 ALOGI("Idle timeout set to %u", timeout);
288 } else {
289 ALOGW("Cannot set idle timeout, IdleInvalidator not enabled");
290 }
291}
292
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800293void MDPComp::setMDPCompLayerFlags(hwc_context_t *ctx,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800294 hwc_display_contents_1_t* list) {
295 LayerProp *layerProp = ctx->layerProp[mDpy];
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800296
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800297 for(int index = 0; index < ctx->listStats[mDpy].numAppLayers; index++) {
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800298 hwc_layer_1_t* layer = &(list->hwLayers[index]);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800299 if(!mCurrentFrame.isFBComposed[index]) {
300 layerProp[index].mFlags |= HWC_MDPCOMP;
301 layer->compositionType = HWC_OVERLAY;
302 layer->hints |= HWC_HINT_CLEAR_FB;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800303 } else {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700304 /* Drop the layer when its already present in FB OR when it lies
305 * outside frame's ROI */
306 if(!mCurrentFrame.needsRedraw || mCurrentFrame.drop[index]) {
Arun Kumar K.R00b84792015-03-27 11:28:36 -0700307 if(index == mCurrentFrame.hwCursorIndex) {
308 layer->compositionType = HWC_CURSOR_OVERLAY;
309 } else {
310 layer->compositionType = HWC_OVERLAY;
311 }
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700312 }
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800313 }
314 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700315}
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500316
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800317void MDPComp::setRedraw(hwc_context_t *ctx,
318 hwc_display_contents_1_t* list) {
319 mCurrentFrame.needsRedraw = false;
320 if(!mCachedFrame.isSameFrame(mCurrentFrame, list) ||
321 (list->flags & HWC_GEOMETRY_CHANGED) ||
322 isSkipPresent(ctx, mDpy)) {
323 mCurrentFrame.needsRedraw = true;
324 }
325}
326
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800327MDPComp::FrameInfo::FrameInfo() {
Saurabh Shahf7fad542014-08-14 10:11:36 -0700328 memset(&mdpToLayer, 0, sizeof(mdpToLayer));
Saurabh Shahaa236822013-04-24 18:07:26 -0700329 reset(0);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800330}
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800331
Saurabh Shahaa236822013-04-24 18:07:26 -0700332void MDPComp::FrameInfo::reset(const int& numLayers) {
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700333 for(int i = 0 ; i < MAX_NUM_BLEND_STAGES; i++ ) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800334 if(mdpToLayer[i].pipeInfo) {
335 delete mdpToLayer[i].pipeInfo;
336 mdpToLayer[i].pipeInfo = NULL;
337 //We dont own the rotator
338 mdpToLayer[i].rot = NULL;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800339 }
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800340 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800341
342 memset(&mdpToLayer, 0, sizeof(mdpToLayer));
343 memset(&layerToMDP, -1, sizeof(layerToMDP));
Saurabh Shahaa236822013-04-24 18:07:26 -0700344 memset(&isFBComposed, 1, sizeof(isFBComposed));
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800345
Saurabh Shahaa236822013-04-24 18:07:26 -0700346 layerCount = numLayers;
347 fbCount = numLayers;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800348 mdpCount = 0;
Saurabh Shah2f3895f2013-05-02 10:13:31 -0700349 needsRedraw = true;
Saurabh Shahd53bc5f2014-02-05 10:17:43 -0800350 fbZ = -1;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800351}
352
Saurabh Shahaa236822013-04-24 18:07:26 -0700353void MDPComp::FrameInfo::map() {
354 // populate layer and MDP maps
355 int mdpIdx = 0;
356 for(int idx = 0; idx < layerCount; idx++) {
357 if(!isFBComposed[idx]) {
358 mdpToLayer[mdpIdx].listIndex = idx;
359 layerToMDP[idx] = mdpIdx++;
360 }
361 }
362}
363
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800364MDPComp::LayerCache::LayerCache() {
365 reset();
366}
367
368void MDPComp::LayerCache::reset() {
Saurabh Shahaa236822013-04-24 18:07:26 -0700369 memset(&hnd, 0, sizeof(hnd));
Prabhanjan Kandula2243aa62013-10-24 12:58:55 +0530370 memset(&isFBComposed, true, sizeof(isFBComposed));
371 memset(&drop, false, sizeof(drop));
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800372 layerCount = 0;
Saurabh Shahaa236822013-04-24 18:07:26 -0700373}
374
375void MDPComp::LayerCache::cacheAll(hwc_display_contents_1_t* list) {
Praveena Pachipulusud9443c72014-02-17 10:42:28 +0530376 const int numAppLayers = (int)list->numHwLayers - 1;
Saurabh Shahaa236822013-04-24 18:07:26 -0700377 for(int i = 0; i < numAppLayers; i++) {
378 hnd[i] = list->hwLayers[i].handle;
379 }
380}
381
382void MDPComp::LayerCache::updateCounts(const FrameInfo& curFrame) {
Saurabh Shahaa236822013-04-24 18:07:26 -0700383 layerCount = curFrame.layerCount;
Prabhanjan Kandula2243aa62013-10-24 12:58:55 +0530384 memcpy(&isFBComposed, &curFrame.isFBComposed, sizeof(isFBComposed));
385 memcpy(&drop, &curFrame.drop, sizeof(drop));
386}
387
Jeykumar Sankaran988d3682013-11-15 11:57:16 -0800388bool MDPComp::LayerCache::isSameFrame(const FrameInfo& curFrame,
389 hwc_display_contents_1_t* list) {
Prabhanjan Kandula2243aa62013-10-24 12:58:55 +0530390 if(layerCount != curFrame.layerCount)
391 return false;
392 for(int i = 0; i < curFrame.layerCount; i++) {
393 if((curFrame.isFBComposed[i] != isFBComposed[i]) ||
394 (curFrame.drop[i] != drop[i])) {
395 return false;
396 }
Jeykumar Sankaran988d3682013-11-15 11:57:16 -0800397 if(curFrame.isFBComposed[i] &&
398 (hnd[i] != list->hwLayers[i].handle)){
399 return false;
400 }
Prabhanjan Kandula2243aa62013-10-24 12:58:55 +0530401 }
402 return true;
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800403}
404
Raj Kamalfdfdddf2015-03-16 21:59:25 +0530405bool MDPComp::LayerCache::isSameFrame(hwc_context_t *ctx, int dpy,
406 hwc_display_contents_1_t* list) {
407
408 if(layerCount != ctx->listStats[dpy].numAppLayers)
409 return false;
410
411 if((list->flags & HWC_GEOMETRY_CHANGED) ||
412 isSkipPresent(ctx, dpy)) {
413 return false;
414 }
415
416 for(int i = 0; i < layerCount; i++) {
417 if(hnd[i] != list->hwLayers[i].handle)
418 return false;
419 }
420
421 return true;
422}
423
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700424bool MDPComp::isSupportedForMDPComp(hwc_context_t *ctx, hwc_layer_1_t* layer) {
425 private_handle_t *hnd = (private_handle_t *)layer->handle;
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800426 if((has90Transform(layer) and (not isRotationDoable(ctx, hnd))) ||
Raj Kamal1179d9c2014-10-28 15:31:35 +0530427 (not isValidDimension(ctx,layer)) ||
428 isSkipLayer(layer)) {
429 //More conditions here, sRGB+Blend etc
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700430 return false;
431 }
432 return true;
433}
434
Sravan Kumar D.V.Nad5d9292013-04-24 14:23:04 +0530435bool MDPComp::isValidDimension(hwc_context_t *ctx, hwc_layer_1_t *layer) {
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800436 private_handle_t *hnd = (private_handle_t *)layer->handle;
437
438 if(!hnd) {
Sushil Chauhan897a9c32013-07-18 11:09:55 -0700439 if (layer->flags & HWC_COLOR_FILL) {
440 // Color layer
441 return true;
442 }
Ramkumar Radhakrishnan0cabf212014-09-08 20:07:49 -0700443 ALOGD_IF(isDebug(), "%s: layer handle is NULL", __FUNCTION__);
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800444 return false;
445 }
446
Naseer Ahmede850a802013-09-06 13:12:52 -0400447 //XXX: Investigate doing this with pixel phase on MDSS
Naseer Ahmede77f8082013-10-10 13:42:48 -0400448 if(!isSecureBuffer(hnd) && isNonIntegralSourceCrop(layer->sourceCropf))
Naseer Ahmede850a802013-09-06 13:12:52 -0400449 return false;
450
Saurabh Shah62e1d732013-09-17 10:44:05 -0700451 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
Saurabh Shah4fdde762013-04-30 18:47:33 -0700452 hwc_rect_t dst = layer->displayFrame;
Saurabh Shahb6810df2014-06-17 16:00:22 -0700453 bool rotated90 = (bool)(layer->transform & HAL_TRANSFORM_ROT_90);
Saurabh Shahe28a4022014-06-13 11:41:13 -0700454 int crop_w = rotated90 ? crop.bottom - crop.top : crop.right - crop.left;
455 int crop_h = rotated90 ? crop.right - crop.left : crop.bottom - crop.top;
Saurabh Shah4fdde762013-04-30 18:47:33 -0700456 int dst_w = dst.right - dst.left;
457 int dst_h = dst.bottom - dst.top;
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800458 float w_scale = ((float)crop_w / (float)dst_w);
459 float h_scale = ((float)crop_h / (float)dst_h);
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530460 MDPVersion& mdpHw = MDPVersion::getInstance();
Saurabh Shah4fdde762013-04-30 18:47:33 -0700461
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800462 /* Workaround for MDP HW limitation in DSI command mode panels where
463 * FPS will not go beyond 30 if buffers on RGB pipes are of width or height
464 * less than 5 pixels
Sravan Kumar D.V.Nad5d9292013-04-24 14:23:04 +0530465 * There also is a HW limilation in MDP, minimum block size is 2x2
466 * Fallback to GPU if height is less than 2.
467 */
Saurabh Shah189f23d2014-09-26 17:21:00 -0700468 if(mdpHw.hasMinCropWidthLimitation() and (crop_w < 5 or crop_h < 5))
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800469 return false;
470
Ramkumar Radhakrishnan1a763e92015-03-19 16:46:46 -0700471 /* crop_w and crop_h should be even for yuv layer, so fallback to GPU for
472 * those cases
473 */
474 if(isYuvBuffer(hnd) && (crop_w < 2 || crop_h < 2)) {
475 return false;
476 }
477
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800478 if((w_scale > 1.0f) || (h_scale > 1.0f)) {
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530479 const uint32_t maxMDPDownscale = mdpHw.getMaxMDPDownscale();
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800480 const float w_dscale = w_scale;
481 const float h_dscale = h_scale;
482
Jeykumar Sankaran1706a772013-11-27 12:55:19 -0800483 if(ctx->mMDP.version >= qdutils::MDSS_V5) {
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700484
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530485 if(!mdpHw.supportsDecimation()) {
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700486 /* On targets that doesnt support Decimation (eg.,8x26)
487 * maximum downscale support is overlay pipe downscale.
488 */
Jeykumar Sankaran39305802014-12-12 17:55:57 -0800489 if(crop_w > (int) mdpHw.getMaxPipeWidth() ||
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530490 w_dscale > maxMDPDownscale ||
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700491 h_dscale > maxMDPDownscale)
Jeykumar Sankaran1706a772013-11-27 12:55:19 -0800492 return false;
493 } else {
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700494 // Decimation on macrotile format layers is not supported.
495 if(isTileRendered(hnd)) {
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530496 /* Bail out if
497 * 1. Src crop > Mixer limit on nonsplit MDPComp
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700498 * 2. exceeds maximum downscale limit
499 */
Jeykumar Sankaran39305802014-12-12 17:55:57 -0800500 if(((crop_w > (int) mdpHw.getMaxPipeWidth()) &&
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530501 !sSrcSplitEnabled) ||
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700502 w_dscale > maxMDPDownscale ||
503 h_dscale > maxMDPDownscale) {
504 return false;
505 }
506 } else if(w_dscale > 64 || h_dscale > 64)
Jeykumar Sankaran1706a772013-11-27 12:55:19 -0800507 return false;
508 }
509 } else { //A-family
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700510 if(w_dscale > maxMDPDownscale || h_dscale > maxMDPDownscale)
Saurabh Shah4fdde762013-04-30 18:47:33 -0700511 return false;
512 }
Saurabh Shah4fdde762013-04-30 18:47:33 -0700513 }
514
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800515 if((w_scale < 1.0f) || (h_scale < 1.0f)) {
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530516 const uint32_t upscale = mdpHw.getMaxMDPUpscale();
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800517 const float w_uscale = 1.0f / w_scale;
518 const float h_uscale = 1.0f / h_scale;
519
520 if(w_uscale > upscale || h_uscale > upscale)
521 return false;
522 }
523
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800524 return true;
525}
526
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800527bool MDPComp::isFrameDoable(hwc_context_t *ctx) {
Saurabh Shahaa236822013-04-24 18:07:26 -0700528 bool ret = true;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800529
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800530 if(!isEnabled()) {
531 ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
Saurabh Shahaa236822013-04-24 18:07:26 -0700532 ret = false;
Raj Kamal068f4572014-04-14 16:14:06 +0530533 } else if((qdutils::MDPVersion::getInstance().is8x26() ||
Prabhanjan Kandula958ffa92014-05-12 14:56:56 +0530534 qdutils::MDPVersion::getInstance().is8x16() ||
535 qdutils::MDPVersion::getInstance().is8x39()) &&
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800536 ctx->mVideoTransFlag &&
537 isSecondaryConnected(ctx)) {
Saurabh Shahd4e65852013-06-17 11:33:53 -0700538 //1 Padding round to shift pipes across mixers
539 ALOGD_IF(isDebug(),"%s: MDP Comp. video transition padding round",
540 __FUNCTION__);
541 ret = false;
Raj Kamalc0d34242015-03-17 20:53:14 +0530542 } else if((qdutils::MDPVersion::getInstance().is8x26() ||
543 qdutils::MDPVersion::getInstance().is8x16() ||
544 qdutils::MDPVersion::getInstance().is8x39()) &&
545 !mDpy && isSecondaryAnimating(ctx) &&
546 isYuvPresent(ctx,HWC_DISPLAY_VIRTUAL)) {
547 ALOGD_IF(isDebug(),"%s: Display animation in progress",
548 __FUNCTION__);
549 ret = false;
Ramkumar Radhakrishnanf26fe9e2014-09-09 13:47:54 -0700550 } else if(qdutils::MDPVersion::getInstance().getTotalPipes() < 8) {
551 /* TODO: freeing up all the resources only for the targets having total
552 number of pipes < 8. Need to analyze number of VIG pipes used
553 for primary in previous draw cycle and accordingly decide
554 whether to fall back to full GPU comp or video only comp
555 */
556 if(isSecondaryConfiguring(ctx)) {
557 ALOGD_IF( isDebug(),"%s: External Display connection is pending",
558 __FUNCTION__);
559 ret = false;
560 } else if(ctx->isPaddingRound) {
561 ALOGD_IF(isDebug(), "%s: padding round invoked for dpy %d",
562 __FUNCTION__,mDpy);
563 ret = false;
564 }
Tatenda Chipeperekwadc8d7082014-11-04 16:41:50 -0800565 } else if (ctx->isDMAStateChanging) {
566 // Bail out if a padding round has been invoked in order to switch DMA
567 // state to block mode. We need this to cater for the case when a layer
568 // requires rotation in the current frame.
569 ALOGD_IF(isDebug(), "%s: padding round invoked to switch DMA state",
570 __FUNCTION__);
571 return false;
Saurabh Shah0ceeb6a2013-04-23 10:46:07 -0700572 }
Tatenda Chipeperekwadc8d7082014-11-04 16:41:50 -0800573
Saurabh Shahaa236822013-04-24 18:07:26 -0700574 return ret;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800575}
576
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800577void MDPCompNonSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect &crop,
578 hwc_rect &dst) {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800579 hwc_rect_t roi = ctx->listStats[mDpy].lRoi;
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800580 dst = getIntersection(dst, roi);
581 crop = dst;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800582}
583
584/* 1) Identify layers that are not visible or lying outside the updating ROI and
585 * drop them from composition.
586 * 2) If we have a scaling layer which needs cropping against generated
587 * ROI, reset ROI to full resolution. */
588bool MDPCompNonSplit::validateAndApplyROI(hwc_context_t *ctx,
589 hwc_display_contents_1_t* list) {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700590 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800591 hwc_rect_t visibleRect = ctx->listStats[mDpy].lRoi;
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800592
593 for(int i = numAppLayers - 1; i >= 0; i--){
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800594 if(!isValidRect(visibleRect)) {
595 mCurrentFrame.drop[i] = true;
596 mCurrentFrame.dropCount++;
Jeykumar Sankaran0b961452014-01-21 17:26:12 -0800597 continue;
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800598 }
599
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700600 const hwc_layer_1_t* layer = &list->hwLayers[i];
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700601 hwc_rect_t dstRect = layer->displayFrame;
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800602 hwc_rect_t res = getIntersection(visibleRect, dstRect);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700603
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700604 if(!isValidRect(res)) {
605 mCurrentFrame.drop[i] = true;
606 mCurrentFrame.dropCount++;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800607 } else {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700608 /* Reset frame ROI when any layer which needs scaling also needs ROI
609 * cropping */
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800610 if(!isSameRect(res, dstRect) && needsScaling (layer)) {
Arpita Banerjeed8965982013-11-08 17:27:33 -0800611 ALOGI("%s: Resetting ROI due to scaling", __FUNCTION__);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700612 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
613 mCurrentFrame.dropCount = 0;
614 return false;
615 }
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800616
Jeykumar Sankaran0b961452014-01-21 17:26:12 -0800617 /* deduct any opaque region from visibleRect */
radhakrishna4efbdd62014-11-03 13:19:27 +0530618 if (layer->blending == HWC_BLENDING_NONE &&
619 layer->planeAlpha == 0xFF)
Jeykumar Sankaran0b961452014-01-21 17:26:12 -0800620 visibleRect = deductRect(visibleRect, res);
621 }
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700622 }
623 return true;
624}
625
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800626/* Calculate ROI for the frame by accounting all the layer's dispalyFrame which
627 * are updating. If DirtyRegion is applicable, calculate it by accounting all
628 * the changing layer's dirtyRegion. */
629void MDPCompNonSplit::generateROI(hwc_context_t *ctx,
630 hwc_display_contents_1_t* list) {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700631 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800632 if(!canPartialUpdate(ctx, list))
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700633 return;
634
635 struct hwc_rect roi = (struct hwc_rect){0, 0, 0, 0};
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800636 hwc_rect fullFrame = (struct hwc_rect) {0, 0,(int)ctx->dpyAttr[mDpy].xres,
637 (int)ctx->dpyAttr[mDpy].yres};
638
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700639 for(int index = 0; index < numAppLayers; index++ ) {
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800640 hwc_layer_1_t* layer = &list->hwLayers[index];
641 if ((mCachedFrame.hnd[index] != layer->handle) ||
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800642 isYuvBuffer((private_handle_t *)layer->handle)) {
Jeykumar Sankaran455678c2014-05-30 10:22:38 -0700643 hwc_rect_t dst = layer->displayFrame;
644 hwc_rect_t updatingRect = dst;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800645
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800646#ifdef QCOM_BSP
Dileep Kumar Reddi7399d5c2014-12-31 18:01:19 +0530647 if(!needsScaling(layer) && !layer->transform &&
648 (!isYuvBuffer((private_handle_t *)layer->handle)))
Jeykumar Sankaran455678c2014-05-30 10:22:38 -0700649 {
650 hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
651 int x_off = dst.left - src.left;
652 int y_off = dst.top - src.top;
653 updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
654 }
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800655#endif
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800656
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800657 roi = getUnion(roi, updatingRect);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700658 }
659 }
660
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800661 /* No layer is updating. Still SF wants a refresh.*/
662 if(!isValidRect(roi))
663 return;
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800664
665 // Align ROI coordinates to panel restrictions
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800666 roi = getSanitizeROI(roi, fullFrame);
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800667
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800668 ctx->listStats[mDpy].lRoi = roi;
669 if(!validateAndApplyROI(ctx, list))
670 resetROI(ctx, mDpy);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700671
672 ALOGD_IF(isDebug(),"%s: generated ROI: [%d, %d, %d, %d]", __FUNCTION__,
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800673 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
674 ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom);
675}
676
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800677void MDPCompSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect &crop,
678 hwc_rect &dst) {
679 hwc_rect roi = getUnion(ctx->listStats[mDpy].lRoi,
680 ctx->listStats[mDpy].rRoi);
681 hwc_rect tmpDst = getIntersection(dst, roi);
682 if(!isSameRect(dst, tmpDst)) {
683 crop.left = crop.left + (tmpDst.left - dst.left);
684 crop.top = crop.top + (tmpDst.top - dst.top);
685 crop.right = crop.left + (tmpDst.right - tmpDst.left);
686 crop.bottom = crop.top + (tmpDst.bottom - tmpDst.top);
687 dst = tmpDst;
688 }
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800689}
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800690
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800691/* 1) Identify layers that are not visible or lying outside BOTH the updating
692 * ROI's and drop them from composition. If a layer is spanning across both
693 * the halves of the screen but needed by only ROI, the non-contributing
694 * half will not be programmed for MDP.
695 * 2) If we have a scaling layer which needs cropping against generated
696 * ROI, reset ROI to full resolution. */
697bool MDPCompSplit::validateAndApplyROI(hwc_context_t *ctx,
698 hwc_display_contents_1_t* list) {
699
700 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
701
702 hwc_rect_t visibleRectL = ctx->listStats[mDpy].lRoi;
703 hwc_rect_t visibleRectR = ctx->listStats[mDpy].rRoi;
704
705 for(int i = numAppLayers - 1; i >= 0; i--){
706 if(!isValidRect(visibleRectL) && !isValidRect(visibleRectR))
707 {
708 mCurrentFrame.drop[i] = true;
709 mCurrentFrame.dropCount++;
710 continue;
711 }
712
713 const hwc_layer_1_t* layer = &list->hwLayers[i];
714 hwc_rect_t dstRect = layer->displayFrame;
715
716 hwc_rect_t l_res = getIntersection(visibleRectL, dstRect);
717 hwc_rect_t r_res = getIntersection(visibleRectR, dstRect);
718 hwc_rect_t res = getUnion(l_res, r_res);
719
720 if(!isValidRect(l_res) && !isValidRect(r_res)) {
721 mCurrentFrame.drop[i] = true;
722 mCurrentFrame.dropCount++;
723 } else {
724 /* Reset frame ROI when any layer which needs scaling also needs ROI
725 * cropping */
726 if(!isSameRect(res, dstRect) && needsScaling (layer)) {
727 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
728 mCurrentFrame.dropCount = 0;
729 return false;
730 }
731
radhakrishna4efbdd62014-11-03 13:19:27 +0530732 if (layer->blending == HWC_BLENDING_NONE &&
733 layer->planeAlpha == 0xFF) {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800734 visibleRectL = deductRect(visibleRectL, l_res);
735 visibleRectR = deductRect(visibleRectR, r_res);
736 }
737 }
738 }
739 return true;
740}
741/* Calculate ROI for the frame by accounting all the layer's dispalyFrame which
742 * are updating. If DirtyRegion is applicable, calculate it by accounting all
743 * the changing layer's dirtyRegion. */
744void MDPCompSplit::generateROI(hwc_context_t *ctx,
745 hwc_display_contents_1_t* list) {
746 if(!canPartialUpdate(ctx, list))
747 return;
748
749 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
750 int lSplit = getLeftSplit(ctx, mDpy);
751
752 int hw_h = (int)ctx->dpyAttr[mDpy].yres;
753 int hw_w = (int)ctx->dpyAttr[mDpy].xres;
754
755 struct hwc_rect l_frame = (struct hwc_rect){0, 0, lSplit, hw_h};
756 struct hwc_rect r_frame = (struct hwc_rect){lSplit, 0, hw_w, hw_h};
757
758 struct hwc_rect l_roi = (struct hwc_rect){0, 0, 0, 0};
759 struct hwc_rect r_roi = (struct hwc_rect){0, 0, 0, 0};
760
761 for(int index = 0; index < numAppLayers; index++ ) {
762 hwc_layer_1_t* layer = &list->hwLayers[index];
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800763 private_handle_t *hnd = (private_handle_t *)layer->handle;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800764 if ((mCachedFrame.hnd[index] != layer->handle) ||
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800765 isYuvBuffer(hnd)) {
Jeykumar Sankaran71e597c2014-05-07 16:23:14 -0700766 hwc_rect_t dst = layer->displayFrame;
767 hwc_rect_t updatingRect = dst;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800768
769#ifdef QCOM_BSP
770 if(!needsScaling(layer) && !layer->transform)
Jeykumar Sankaran71e597c2014-05-07 16:23:14 -0700771 {
772 hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
773 int x_off = dst.left - src.left;
774 int y_off = dst.top - src.top;
775 updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
776 }
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800777#endif
778
779 hwc_rect_t l_dst = getIntersection(l_frame, updatingRect);
780 if(isValidRect(l_dst))
781 l_roi = getUnion(l_roi, l_dst);
782
783 hwc_rect_t r_dst = getIntersection(r_frame, updatingRect);
784 if(isValidRect(r_dst))
785 r_roi = getUnion(r_roi, r_dst);
786 }
787 }
788
Jeykumar Sankarana40a9342014-04-25 09:37:10 -0700789 /* For panels that cannot accept commands in both the interfaces, we cannot
790 * send two ROI's (for each half). We merge them into single ROI and split
791 * them across lSplit for MDP mixer use. The ROI's will be merged again
792 * finally before udpating the panel in the driver. */
793 if(qdutils::MDPVersion::getInstance().needsROIMerge()) {
794 hwc_rect_t temp_roi = getUnion(l_roi, r_roi);
795 l_roi = getIntersection(temp_roi, l_frame);
796 r_roi = getIntersection(temp_roi, r_frame);
797 }
798
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800799 /* No layer is updating. Still SF wants a refresh. */
800 if(!isValidRect(l_roi) && !isValidRect(r_roi))
801 return;
802
803 l_roi = getSanitizeROI(l_roi, l_frame);
804 r_roi = getSanitizeROI(r_roi, r_frame);
805
806 ctx->listStats[mDpy].lRoi = l_roi;
807 ctx->listStats[mDpy].rRoi = r_roi;
808
809 if(!validateAndApplyROI(ctx, list))
810 resetROI(ctx, mDpy);
811
812 ALOGD_IF(isDebug(),"%s: generated L_ROI: [%d, %d, %d, %d]"
813 "R_ROI: [%d, %d, %d, %d]", __FUNCTION__,
814 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
815 ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom,
816 ctx->listStats[mDpy].rRoi.left, ctx->listStats[mDpy].rRoi.top,
817 ctx->listStats[mDpy].rRoi.right, ctx->listStats[mDpy].rRoi.bottom);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700818}
819
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800820/* Checks for conditions where all the layers marked for MDP comp cannot be
821 * bypassed. On such conditions we try to bypass atleast YUV layers */
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800822bool MDPComp::tryFullFrame(hwc_context_t *ctx,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800823 hwc_display_contents_1_t* list){
824
Saurabh Shahaa236822013-04-24 18:07:26 -0700825 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800826
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -0700827 // Fall back to video only composition, if AIV video mode is enabled
828 if(ctx->listStats[mDpy].mAIVVideoMode) {
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -0700829 ALOGD_IF(isDebug(), "%s: AIV Video Mode enabled dpy %d",
830 __FUNCTION__, mDpy);
831 return false;
832 }
833
Praveena Pachipulusu47346c22014-12-04 11:06:41 +0530834 /* No Idle fall back if secure display or secure RGB layers are present
835 * or if there is only a single layer being composed */
836 if(sIdleFallBack && !ctx->listStats[mDpy].secureUI &&
837 !ctx->listStats[mDpy].secureRGBCount &&
838 (ctx->listStats[mDpy].numAppLayers > 1)) {
Saurabh Shah2d998a92013-05-14 17:55:58 -0700839 ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
840 return false;
841 }
842
Raj Kamalc0d34242015-03-17 20:53:14 +0530843 if(!mDpy && isSecondaryAnimating(ctx) &&
844 (isYuvPresent(ctx,HWC_DISPLAY_EXTERNAL) ||
845 isYuvPresent(ctx,HWC_DISPLAY_VIRTUAL)) ) {
846 ALOGD_IF(isDebug(),"%s: Display animation in progress",
847 __FUNCTION__);
848 return false;
849 }
850
Ramkumar Radhakrishnanf26fe9e2014-09-09 13:47:54 -0700851 // if secondary is configuring or Padding round, fall back to video only
852 // composition and release all assigned non VIG pipes from primary.
853 if(isSecondaryConfiguring(ctx)) {
854 ALOGD_IF( isDebug(),"%s: External Display connection is pending",
855 __FUNCTION__);
856 return false;
857 } else if(ctx->isPaddingRound) {
858 ALOGD_IF(isDebug(), "%s: padding round invoked for dpy %d",
859 __FUNCTION__,mDpy);
860 return false;
861 }
862
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -0500863 // No MDP composition for 3D
864 if(needs3DComposition(ctx, mDpy))
865 return false;
866
Tatenda Chipeperekwacb2a2432014-08-06 17:45:58 -0700867 // check for action safe flag and MDP scaling mode which requires scaling.
Ramkumar Radhakrishnan4af1ef02013-12-12 11:53:08 -0800868 if(ctx->dpyAttr[mDpy].mActionSafePresent
Tatenda Chipeperekwacb2a2432014-08-06 17:45:58 -0700869 || ctx->dpyAttr[mDpy].mMDPScalingMode) {
Ramkumar Radhakrishnan4af1ef02013-12-12 11:53:08 -0800870 ALOGD_IF(isDebug(), "%s: Scaling needed for this frame",__FUNCTION__);
871 return false;
872 }
873
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800874 for(int i = 0; i < numAppLayers; ++i) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800875 hwc_layer_1_t* layer = &list->hwLayers[i];
876 private_handle_t *hnd = (private_handle_t *)layer->handle;
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -0800877
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800878 if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700879 if(!canUseRotator(ctx, mDpy)) {
880 ALOGD_IF(isDebug(), "%s: Can't use rotator for dpy %d",
881 __FUNCTION__, mDpy);
Amara Venkata Mastan Manoj Kumar9d373c02013-08-20 14:30:09 -0700882 return false;
883 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800884 }
Prabhanjan Kandula9fb032a2013-06-18 17:37:22 +0530885
886 //For 8x26 with panel width>1k, if RGB layer needs HFLIP fail mdp comp
887 // may not need it if Gfx pre-rotation can handle all flips & rotations
Saurabh Shahcad57772014-12-01 14:19:51 -0800888 MDPVersion& mdpHw = MDPVersion::getInstance();
Sushil Chauhanfda00fc2014-03-20 11:08:41 -0700889 int transform = (layer->flags & HWC_COLOR_FILL) ? 0 : layer->transform;
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530890 if( mdpHw.is8x26() && (ctx->dpyAttr[mDpy].xres > 1024) &&
891 (transform & HWC_TRANSFORM_FLIP_H) && (!isYuvBuffer(hnd)))
892 return false;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800893 }
Saurabh Shahaa236822013-04-24 18:07:26 -0700894
Saurabh Shaha9da08f2013-07-03 13:27:53 -0700895 if(ctx->mAD->isDoable()) {
896 return false;
897 }
898
Saurabh Shahaa236822013-04-24 18:07:26 -0700899 //If all above hard conditions are met we can do full or partial MDP comp.
900 bool ret = false;
901 if(fullMDPComp(ctx, list)) {
902 ret = true;
Sushil Chauhandefd3522014-05-13 18:17:12 -0700903 } else if(fullMDPCompWithPTOR(ctx, list)) {
904 ret = true;
Jeykumar Sankaran24c199d2013-05-24 09:40:36 -0700905 } else if(partialMDPComp(ctx, list)) {
Saurabh Shahaa236822013-04-24 18:07:26 -0700906 ret = true;
907 }
Prabhanjan Kandula21918db2013-11-26 15:51:58 +0530908
Saurabh Shahaa236822013-04-24 18:07:26 -0700909 return ret;
910}
911
912bool MDPComp::fullMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -0700913
914 if(sSimulationFlags & MDPCOMP_AVOID_FULL_MDP)
915 return false;
916
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700917 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
918 for(int i = 0; i < numAppLayers; i++) {
919 hwc_layer_1_t* layer = &list->hwLayers[i];
Jeykumar Sankaran880da832014-04-18 10:22:35 -0700920 if(not mCurrentFrame.drop[i] and
921 not isSupportedForMDPComp(ctx, layer)) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700922 ALOGD_IF(isDebug(), "%s: Unsupported layer in list",__FUNCTION__);
923 return false;
924 }
925 }
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800926
Raj Kamalb5f0b4a2015-04-08 15:10:37 +0530927 if(!mDpy && isSecondaryConnected(ctx) &&
928 (qdutils::MDPVersion::getInstance().is8x16() ||
929 qdutils::MDPVersion::getInstance().is8x26() ||
930 qdutils::MDPVersion::getInstance().is8x39()) &&
931 isYuvPresent(ctx, HWC_DISPLAY_VIRTUAL)) {
932 ALOGD_IF(isDebug(), "%s: YUV layer present on secondary", __FUNCTION__);
933 return false;
934 }
935
Saurabh Shahaa236822013-04-24 18:07:26 -0700936 mCurrentFrame.fbCount = 0;
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700937 memcpy(&mCurrentFrame.isFBComposed, &mCurrentFrame.drop,
938 sizeof(mCurrentFrame.isFBComposed));
939 mCurrentFrame.mdpCount = mCurrentFrame.layerCount - mCurrentFrame.fbCount -
940 mCurrentFrame.dropCount;
Saurabh Shahaa236822013-04-24 18:07:26 -0700941
Raj Kamal389d6e32014-08-04 14:43:24 +0530942 if(sEnableYUVsplit){
Saurabh Shah3d4b8042013-12-10 15:19:17 -0800943 adjustForSourceSplit(ctx, list);
radhakrishnac9a67412013-09-25 17:40:42 +0530944 }
945
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800946 if(!postHeuristicsHandling(ctx, list)) {
947 ALOGD_IF(isDebug(), "post heuristic handling failed");
948 reset(ctx);
Saurabh Shah8c5c8522013-08-29 17:32:49 -0700949 return false;
950 }
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -0700951 ALOGD_IF(sSimulationFlags,"%s: FULL_MDP_COMP SUCCEEDED",
952 __FUNCTION__);
Saurabh Shahaa236822013-04-24 18:07:26 -0700953 return true;
954}
955
Sushil Chauhandefd3522014-05-13 18:17:12 -0700956/* Full MDP Composition with Peripheral Tiny Overlap Removal.
957 * MDP bandwidth limitations can be avoided, if the overlap region
958 * covered by the smallest layer at a higher z-order, gets composed
959 * by Copybit on a render buffer, which can be queued to MDP.
960 */
961bool MDPComp::fullMDPCompWithPTOR(hwc_context_t *ctx,
962 hwc_display_contents_1_t* list) {
963
964 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Arun Kumar K.R00b84792015-03-27 11:28:36 -0700965 // PTOR does not qualify when there are layers dropped, but if
966 // dropped layer is only a cursor, PTOR could qualify
967 const int numNonCursorLayers = numAppLayers - mCurrentFrame.dropCount;
Sushil Chauhandefd3522014-05-13 18:17:12 -0700968 const int stagesForMDP = min(sMaxPipesPerMixer,
969 ctx->mOverlay->availablePipes(mDpy, Overlay::MIXER_DEFAULT));
970
971 // Hard checks where we cannot use this mode
Sushil Chauhanbfc2de02014-07-24 11:52:58 -0700972 if (mDpy || !ctx->mCopyBit[mDpy]) {
Sushil Chauhandefd3522014-05-13 18:17:12 -0700973 ALOGD_IF(isDebug(), "%s: Feature not supported!", __FUNCTION__);
974 return false;
975 }
976
Arun Kumar K.R00b84792015-03-27 11:28:36 -0700977 // Frame level checks - consider PTOR in case of dropCount only if the cursor
978 // layer is dropped, otherwise bail out of PTOR
Sushil Chauhandefd3522014-05-13 18:17:12 -0700979 if ((numAppLayers > stagesForMDP) || isSkipPresent(ctx, mDpy) ||
Arun Kumar K.R00b84792015-03-27 11:28:36 -0700980 isYuvPresent(ctx, mDpy) || isSecurePresent(ctx, mDpy) ||
981 (mCurrentFrame.dropCount - (int)isCursorPresent(ctx, mDpy))) {
Sushil Chauhandefd3522014-05-13 18:17:12 -0700982 ALOGD_IF(isDebug(), "%s: Frame not supported!", __FUNCTION__);
983 return false;
984 }
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -0700985 // MDP comp checks
986 for(int i = 0; i < numAppLayers; i++) {
Sushil Chauhandefd3522014-05-13 18:17:12 -0700987 hwc_layer_1_t* layer = &list->hwLayers[i];
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -0700988 if(not isSupportedForMDPComp(ctx, layer)) {
989 ALOGD_IF(isDebug(), "%s: Unsupported layer in list",__FUNCTION__);
990 return false;
Sushil Chauhandefd3522014-05-13 18:17:12 -0700991 }
992 }
993
Raj Kamalb5f0b4a2015-04-08 15:10:37 +0530994 if(!mDpy && isSecondaryConnected(ctx) &&
995 (qdutils::MDPVersion::getInstance().is8x16() ||
996 qdutils::MDPVersion::getInstance().is8x26() ||
997 qdutils::MDPVersion::getInstance().is8x39()) &&
998 isYuvPresent(ctx, HWC_DISPLAY_VIRTUAL)) {
999 ALOGD_IF(isDebug(), "%s: YUV layer present on secondary", __FUNCTION__);
1000 return false;
1001 }
1002
Sushil Chauhandefd3522014-05-13 18:17:12 -07001003 /* We cannot use this composition mode, if:
1004 1. A below layer needs scaling.
1005 2. Overlap is not peripheral to display.
1006 3. Overlap or a below layer has 90 degree transform.
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001007 4. Overlap area > (1/3 * FrameBuffer) area, based on Perf inputs.
Sushil Chauhandefd3522014-05-13 18:17:12 -07001008 */
1009
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001010 int minLayerIndex[MAX_PTOR_LAYERS] = { -1, -1};
1011 hwc_rect_t overlapRect[MAX_PTOR_LAYERS];
1012 memset(overlapRect, 0, sizeof(overlapRect));
1013 int layerPixelCount, minPixelCount = 0;
1014 int numPTORLayersFound = 0;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001015 for (int i = numNonCursorLayers - 1; (i >= 0 &&
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001016 numPTORLayersFound < MAX_PTOR_LAYERS); i--) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001017 hwc_layer_1_t* layer = &list->hwLayers[i];
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001018 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
Sushil Chauhandefd3522014-05-13 18:17:12 -07001019 hwc_rect_t dispFrame = layer->displayFrame;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001020 layerPixelCount = (crop.right - crop.left) * (crop.bottom - crop.top);
1021 // PTOR layer should be peripheral and cannot have transform
1022 if (!isPeripheral(dispFrame, ctx->mViewFrame[mDpy]) ||
1023 has90Transform(layer)) {
1024 continue;
1025 }
1026 if((3 * (layerPixelCount + minPixelCount)) >
1027 ((int)ctx->dpyAttr[mDpy].xres * (int)ctx->dpyAttr[mDpy].yres)) {
1028 // Overlap area > (1/3 * FrameBuffer) area, based on Perf inputs.
1029 continue;
1030 }
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001031 bool found = false;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001032 for (int j = i-1; j >= 0; j--) {
1033 // Check if the layers below this layer qualifies for PTOR comp
1034 hwc_layer_1_t* layer = &list->hwLayers[j];
1035 hwc_rect_t disFrame = layer->displayFrame;
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001036 // Layer below PTOR is intersecting and has 90 degree transform or
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001037 // needs scaling cannot be supported.
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001038 if (isValidRect(getIntersection(dispFrame, disFrame))) {
1039 if (has90Transform(layer) || needsScaling(layer)) {
1040 found = false;
1041 break;
1042 }
1043 found = true;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001044 }
1045 }
1046 // Store the minLayer Index
1047 if(found) {
1048 minLayerIndex[numPTORLayersFound] = i;
1049 overlapRect[numPTORLayersFound] = list->hwLayers[i].displayFrame;
1050 minPixelCount += layerPixelCount;
1051 numPTORLayersFound++;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001052 }
1053 }
1054
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001055 // No overlap layers
1056 if (!numPTORLayersFound)
1057 return false;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001058
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001059 // Store the displayFrame and the sourceCrops of the layers
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001060 hwc_rect_t displayFrame[numNonCursorLayers];
1061 hwc_rect_t sourceCrop[numNonCursorLayers];
1062 for(int i = 0; i < numNonCursorLayers; i++) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001063 hwc_layer_1_t* layer = &list->hwLayers[i];
1064 displayFrame[i] = layer->displayFrame;
1065 sourceCrop[i] = integerizeSourceCrop(layer->sourceCropf);
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001066 }
Sushil Chauhandefd3522014-05-13 18:17:12 -07001067
Prabhanjan Kandula9889a202014-09-04 21:50:35 +05301068 /**
1069 * It's possible that 2 PTOR layers might have overlapping.
1070 * In such case, remove the intersection(again if peripheral)
1071 * from the lower PTOR layer to avoid overlapping.
1072 * If intersection is not on peripheral then compromise
1073 * by reducing number of PTOR layers.
1074 **/
1075 hwc_rect_t commonRect = getIntersection(overlapRect[0], overlapRect[1]);
1076 if(isValidRect(commonRect)) {
1077 overlapRect[1] = deductRect(overlapRect[1], commonRect);
1078 list->hwLayers[minLayerIndex[1]].displayFrame = overlapRect[1];
1079 }
1080
1081 ctx->mPtorInfo.count = numPTORLayersFound;
1082 for(int i = 0; i < MAX_PTOR_LAYERS; i++) {
1083 ctx->mPtorInfo.layerIndex[i] = minLayerIndex[i];
1084 }
1085
1086 if (!ctx->mCopyBit[mDpy]->prepareOverlap(ctx, list)) {
1087 // reset PTOR
1088 ctx->mPtorInfo.count = 0;
1089 if(isValidRect(commonRect)) {
1090 // If PTORs are intersecting restore displayframe of PTOR[1]
1091 // before returning, as we have modified it above.
1092 list->hwLayers[minLayerIndex[1]].displayFrame =
1093 displayFrame[minLayerIndex[1]];
1094 }
1095 return false;
1096 }
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001097 private_handle_t *renderBuf = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
1098 Whf layerWhf[numPTORLayersFound]; // To store w,h,f of PTOR layers
1099
Xu Yangcda012c2014-07-30 21:57:21 +08001100 // Store the blending mode, planeAlpha, and transform of PTOR layers
1101 int32_t blending[numPTORLayersFound];
1102 uint8_t planeAlpha[numPTORLayersFound];
1103 uint32_t transform[numPTORLayersFound];
1104
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001105 for(int j = 0; j < numPTORLayersFound; j++) {
1106 int index = ctx->mPtorInfo.layerIndex[j];
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001107
1108 // Update src crop of PTOR layer
1109 hwc_layer_1_t* layer = &list->hwLayers[index];
1110 layer->sourceCropf.left = (float)ctx->mPtorInfo.displayFrame[j].left;
1111 layer->sourceCropf.top = (float)ctx->mPtorInfo.displayFrame[j].top;
1112 layer->sourceCropf.right = (float)ctx->mPtorInfo.displayFrame[j].right;
1113 layer->sourceCropf.bottom =(float)ctx->mPtorInfo.displayFrame[j].bottom;
1114
1115 // Store & update w, h, format of PTOR layer
1116 private_handle_t *hnd = (private_handle_t *)layer->handle;
1117 Whf whf(hnd->width, hnd->height, hnd->format, hnd->size);
1118 layerWhf[j] = whf;
1119 hnd->width = renderBuf->width;
1120 hnd->height = renderBuf->height;
1121 hnd->format = renderBuf->format;
1122
Xu Yangcda012c2014-07-30 21:57:21 +08001123 // Store & update blending mode, planeAlpha and transform of PTOR layer
1124 blending[j] = layer->blending;
1125 planeAlpha[j] = layer->planeAlpha;
1126 transform[j] = layer->transform;
1127 layer->blending = HWC_BLENDING_NONE;
1128 layer->planeAlpha = 0xFF;
1129 layer->transform = 0;
1130
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001131 // Remove overlap from crop & displayFrame of below layers
1132 for (int i = 0; i < index && index !=-1; i++) {
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001133 layer = &list->hwLayers[i];
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001134 if(!isValidRect(getIntersection(layer->displayFrame,
1135 overlapRect[j]))) {
1136 continue;
1137 }
1138 // Update layer attributes
1139 hwc_rect_t srcCrop = integerizeSourceCrop(layer->sourceCropf);
1140 hwc_rect_t destRect = deductRect(layer->displayFrame,
Dileep Kumar Reddi72058b82014-11-11 16:03:03 +05301141 getIntersection(layer->displayFrame, overlapRect[j]));
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001142 qhwc::calculate_crop_rects(srcCrop, layer->displayFrame, destRect,
1143 layer->transform);
1144 layer->sourceCropf.left = (float)srcCrop.left;
1145 layer->sourceCropf.top = (float)srcCrop.top;
1146 layer->sourceCropf.right = (float)srcCrop.right;
1147 layer->sourceCropf.bottom = (float)srcCrop.bottom;
1148 }
Sushil Chauhandefd3522014-05-13 18:17:12 -07001149 }
1150
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001151 mCurrentFrame.mdpCount = numNonCursorLayers;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001152 mCurrentFrame.fbCount = 0;
1153 mCurrentFrame.fbZ = -1;
1154
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001155 for (int j = 0; j < numNonCursorLayers; j++) {
Dileep Kumar Reddi72058b82014-11-11 16:03:03 +05301156 if(isValidRect(list->hwLayers[j].displayFrame)) {
1157 mCurrentFrame.isFBComposed[j] = false;
1158 } else {
1159 mCurrentFrame.mdpCount--;
1160 mCurrentFrame.drop[j] = true;
1161 }
1162 }
Sushil Chauhandefd3522014-05-13 18:17:12 -07001163
1164 bool result = postHeuristicsHandling(ctx, list);
1165
1166 // Restore layer attributes
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001167 for(int i = 0; i < numNonCursorLayers; i++) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001168 hwc_layer_1_t* layer = &list->hwLayers[i];
1169 layer->displayFrame = displayFrame[i];
1170 layer->sourceCropf.left = (float)sourceCrop[i].left;
1171 layer->sourceCropf.top = (float)sourceCrop[i].top;
1172 layer->sourceCropf.right = (float)sourceCrop[i].right;
1173 layer->sourceCropf.bottom = (float)sourceCrop[i].bottom;
1174 }
1175
Xu Yangcda012c2014-07-30 21:57:21 +08001176 // Restore w,h,f, blending attributes, and transform of PTOR layers
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001177 for (int i = 0; i < numPTORLayersFound; i++) {
1178 int idx = ctx->mPtorInfo.layerIndex[i];
Xu Yangcda012c2014-07-30 21:57:21 +08001179 hwc_layer_1_t* layer = &list->hwLayers[idx];
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001180 private_handle_t *hnd = (private_handle_t *)list->hwLayers[idx].handle;
1181 hnd->width = layerWhf[i].w;
1182 hnd->height = layerWhf[i].h;
1183 hnd->format = layerWhf[i].format;
Xu Yangcda012c2014-07-30 21:57:21 +08001184 layer->blending = blending[i];
1185 layer->planeAlpha = planeAlpha[i];
1186 layer->transform = transform[i];
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001187 }
1188
Sushil Chauhandefd3522014-05-13 18:17:12 -07001189 if (!result) {
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001190 // reset PTOR
1191 ctx->mPtorInfo.count = 0;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001192 reset(ctx);
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001193 } else {
1194 ALOGD_IF(isDebug(), "%s: PTOR Indexes: %d and %d", __FUNCTION__,
1195 ctx->mPtorInfo.layerIndex[0], ctx->mPtorInfo.layerIndex[1]);
Sushil Chauhandefd3522014-05-13 18:17:12 -07001196 }
1197
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001198 ALOGD_IF(isDebug(), "%s: Postheuristics %s!", __FUNCTION__,
1199 (result ? "successful" : "failed"));
Sushil Chauhandefd3522014-05-13 18:17:12 -07001200 return result;
1201}
1202
Saurabh Shahaa236822013-04-24 18:07:26 -07001203bool MDPComp::partialMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list)
1204{
radhakrishnac3198ff2015-03-10 17:10:02 +05301205 if(!sEnableMixedMode || !isAlphaPresentinFB(ctx, mDpy)) {
1206 //Mixed mode is disabled/can't be used. No need to even try caching.
Jeykumar Sankaran24c199d2013-05-24 09:40:36 -07001207 return false;
1208 }
1209
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001210 bool ret = false;
Raj Kamal1179d9c2014-10-28 15:31:35 +05301211 if(isSkipPresent(ctx, mDpy) or list->flags & HWC_GEOMETRY_CHANGED) {
1212 //Try load based first
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001213 ret = loadBasedComp(ctx, list) or
Saurabh Shahf2de00f2013-12-11 17:52:53 -08001214 cacheBasedComp(ctx, list);
1215 } else {
1216 ret = cacheBasedComp(ctx, list) or
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001217 loadBasedComp(ctx, list);
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001218 }
1219
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001220 return ret;
1221}
1222
1223bool MDPComp::cacheBasedComp(hwc_context_t *ctx,
1224 hwc_display_contents_1_t* list) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001225 if(sSimulationFlags & MDPCOMP_AVOID_CACHE_MDP)
1226 return false;
1227
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001228 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shahaa236822013-04-24 18:07:26 -07001229 mCurrentFrame.reset(numAppLayers);
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001230 updateLayerCache(ctx, list, mCurrentFrame);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001231
1232 //If an MDP marked layer is unsupported cannot do partial MDP Comp
1233 for(int i = 0; i < numAppLayers; i++) {
1234 if(!mCurrentFrame.isFBComposed[i]) {
1235 hwc_layer_1_t* layer = &list->hwLayers[i];
1236 if(not isSupportedForMDPComp(ctx, layer)) {
1237 ALOGD_IF(isDebug(), "%s: Unsupported layer in list",
1238 __FUNCTION__);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001239 reset(ctx);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001240 return false;
1241 }
1242 }
1243 }
1244
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001245 updateYUV(ctx, list, false /*secure only*/, mCurrentFrame);
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001246 /* mark secure RGB layers for MDP comp */
1247 updateSecureRGB(ctx, list);
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301248 bool ret = markLayersForCaching(ctx, list); //sets up fbZ also
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001249 if(!ret) {
1250 ALOGD_IF(isDebug(),"%s: batching failed, dpy %d",__FUNCTION__, mDpy);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001251 reset(ctx);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001252 return false;
1253 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001254
1255 int mdpCount = mCurrentFrame.mdpCount;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001256
Raj Kamal389d6e32014-08-04 14:43:24 +05301257 if(sEnableYUVsplit){
Saurabh Shah3d4b8042013-12-10 15:19:17 -08001258 adjustForSourceSplit(ctx, list);
radhakrishnac9a67412013-09-25 17:40:42 +05301259 }
1260
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001261 if(!postHeuristicsHandling(ctx, list)) {
1262 ALOGD_IF(isDebug(), "post heuristic handling failed");
1263 reset(ctx);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07001264 return false;
1265 }
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001266 ALOGD_IF(sSimulationFlags,"%s: CACHE_MDP_COMP SUCCEEDED",
1267 __FUNCTION__);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07001268
Saurabh Shahaa236822013-04-24 18:07:26 -07001269 return true;
1270}
1271
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001272bool MDPComp::loadBasedComp(hwc_context_t *ctx,
Saurabh Shahb772ae32013-11-18 15:40:02 -08001273 hwc_display_contents_1_t* list) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001274 if(sSimulationFlags & MDPCOMP_AVOID_LOAD_MDP)
1275 return false;
1276
Arun Kumar K.R2aa44c62014-01-21 23:08:28 -08001277 if(not isLoadBasedCompDoable(ctx)) {
Saurabh Shahf2de00f2013-12-11 17:52:53 -08001278 return false;
1279 }
1280
Saurabh Shahb772ae32013-11-18 15:40:02 -08001281 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001282 const int numNonDroppedLayers = numAppLayers - mCurrentFrame.dropCount;
1283 const int stagesForMDP = min(sMaxPipesPerMixer,
1284 ctx->mOverlay->availablePipes(mDpy, Overlay::MIXER_DEFAULT));
Saurabh Shahf2de00f2013-12-11 17:52:53 -08001285
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001286 int mdpBatchSize = stagesForMDP - 1; //1 stage for FB
1287 int fbBatchSize = numNonDroppedLayers - mdpBatchSize;
1288 int lastMDPSupportedIndex = numAppLayers;
1289 int dropCount = 0;
Saurabh Shahb772ae32013-11-18 15:40:02 -08001290
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001291 //Find the minimum MDP batch size
1292 for(int i = 0; i < numAppLayers;i++) {
1293 if(mCurrentFrame.drop[i]) {
1294 dropCount++;
Jeykumar Sankaran846e2792014-01-23 21:59:58 -08001295 continue;
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001296 }
1297 hwc_layer_1_t* layer = &list->hwLayers[i];
1298 if(not isSupportedForMDPComp(ctx, layer)) {
1299 lastMDPSupportedIndex = i;
1300 mdpBatchSize = min(i - dropCount, stagesForMDP - 1);
1301 fbBatchSize = numNonDroppedLayers - mdpBatchSize;
Jeykumar Sankaran846e2792014-01-23 21:59:58 -08001302 break;
Saurabh Shahb772ae32013-11-18 15:40:02 -08001303 }
Saurabh Shahb772ae32013-11-18 15:40:02 -08001304 }
1305
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001306 ALOGD_IF(isDebug(), "%s:Before optimizing fbBatch, mdpbatch %d, fbbatch %d "
1307 "dropped %d", __FUNCTION__, mdpBatchSize, fbBatchSize,
1308 mCurrentFrame.dropCount);
1309
1310 //Start at a point where the fb batch should at least have 2 layers, for
1311 //this mode to be justified.
1312 while(fbBatchSize < 2) {
1313 ++fbBatchSize;
1314 --mdpBatchSize;
Jeykumar Sankaran846e2792014-01-23 21:59:58 -08001315 }
Saurabh Shahb772ae32013-11-18 15:40:02 -08001316
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001317 //If there are no layers for MDP, this mode doesnt make sense.
1318 if(mdpBatchSize < 1) {
1319 ALOGD_IF(isDebug(), "%s: No MDP layers after optimizing for fbBatch",
1320 __FUNCTION__);
Saurabh Shahb772ae32013-11-18 15:40:02 -08001321 return false;
1322 }
1323
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001324 mCurrentFrame.reset(numAppLayers);
1325
1326 //Try with successively smaller mdp batch sizes until we succeed or reach 1
1327 while(mdpBatchSize > 0) {
1328 //Mark layers for MDP comp
1329 int mdpBatchLeft = mdpBatchSize;
1330 for(int i = 0; i < lastMDPSupportedIndex and mdpBatchLeft; i++) {
1331 if(mCurrentFrame.drop[i]) {
1332 continue;
1333 }
1334 mCurrentFrame.isFBComposed[i] = false;
1335 --mdpBatchLeft;
1336 }
1337
1338 mCurrentFrame.fbZ = mdpBatchSize;
1339 mCurrentFrame.fbCount = fbBatchSize;
1340 mCurrentFrame.mdpCount = mdpBatchSize;
1341
1342 ALOGD_IF(isDebug(), "%s:Trying with: mdpbatch %d fbbatch %d dropped %d",
1343 __FUNCTION__, mdpBatchSize, fbBatchSize,
1344 mCurrentFrame.dropCount);
1345
1346 if(postHeuristicsHandling(ctx, list)) {
1347 ALOGD_IF(isDebug(), "%s: Postheuristics handling succeeded",
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001348 __FUNCTION__);
1349 ALOGD_IF(sSimulationFlags,"%s: LOAD_MDP_COMP SUCCEEDED",
1350 __FUNCTION__);
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001351 return true;
1352 }
1353
1354 reset(ctx);
1355 --mdpBatchSize;
1356 ++fbBatchSize;
1357 }
1358
1359 return false;
Saurabh Shahb772ae32013-11-18 15:40:02 -08001360}
1361
Arun Kumar K.R2aa44c62014-01-21 23:08:28 -08001362bool MDPComp::isLoadBasedCompDoable(hwc_context_t *ctx) {
Prabhanjan Kandula3dbbd882013-12-11 14:43:46 +05301363 if(mDpy or isSecurePresent(ctx, mDpy) or
1364 isYuvPresent(ctx, mDpy)) {
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001365 return false;
1366 }
1367 return true;
1368}
1369
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001370bool MDPComp::canPartialUpdate(hwc_context_t *ctx,
1371 hwc_display_contents_1_t* list){
1372 if(!qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() ||
1373 isSkipPresent(ctx, mDpy) || (list->flags & HWC_GEOMETRY_CHANGED) ||
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001374 isCursorPresent(ctx, mDpy) || !sIsPartialUpdateActive || mDpy) {
1375 // On Async position update, the ROI becomes invalid, hence disable PU
1376 // when cursor is present
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001377 return false;
1378 }
Jeykumar Sankaran4dd10ab2014-07-02 12:23:09 -07001379 if(ctx->listStats[mDpy].secureUI)
1380 return false;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001381 return true;
1382}
1383
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001384bool MDPComp::tryVideoOnly(hwc_context_t *ctx,
1385 hwc_display_contents_1_t* list) {
1386 const bool secureOnly = true;
1387 return videoOnlyComp(ctx, list, not secureOnly) or
1388 videoOnlyComp(ctx, list, secureOnly);
1389}
1390
1391bool MDPComp::videoOnlyComp(hwc_context_t *ctx,
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001392 hwc_display_contents_1_t* list, bool secureOnly) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001393 if(sSimulationFlags & MDPCOMP_AVOID_VIDEO_ONLY)
1394 return false;
Praveena Pachipulusu47346c22014-12-04 11:06:41 +05301395
Saurabh Shahaa236822013-04-24 18:07:26 -07001396 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Praveena Pachipulusu47346c22014-12-04 11:06:41 +05301397 if(!isSecurePresent(ctx, mDpy)) {
1398 /* Bail out if we are processing only secured video layers
1399 * and we dont have any */
1400 if(secureOnly) {
1401 ALOGD_IF(isDebug(),"%s: No Secure Video Layers", __FUNCTION__);
1402 return false;
1403 }
1404 /* No Idle fall back for secure video layers and if there is only
1405 * single layer being composed. */
1406 if(sIdleFallBack && (ctx->listStats[mDpy].numAppLayers > 1)) {
1407 ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
1408 return false;
1409 }
1410 }
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001411
Saurabh Shahaa236822013-04-24 18:07:26 -07001412 mCurrentFrame.reset(numAppLayers);
Jeykumar Sankaraneb3a5e22014-04-08 16:07:55 -07001413 mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001414 updateYUV(ctx, list, secureOnly, mCurrentFrame);
Saurabh Shah4fdde762013-04-30 18:47:33 -07001415 int mdpCount = mCurrentFrame.mdpCount;
Saurabh Shahaa236822013-04-24 18:07:26 -07001416
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001417 if(!isYuvPresent(ctx, mDpy) or (mdpCount == 0)) {
1418 reset(ctx);
Saurabh Shahaa236822013-04-24 18:07:26 -07001419 return false;
1420 }
1421
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001422 if(mCurrentFrame.fbCount)
1423 mCurrentFrame.fbZ = mCurrentFrame.mdpCount;
Saurabh Shah4fdde762013-04-30 18:47:33 -07001424
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05001425 if(sEnableYUVsplit || needs3DComposition(ctx, mDpy)){
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001426 adjustForSourceSplit(ctx, list);
1427 }
1428
1429 if(!postHeuristicsHandling(ctx, list)) {
1430 ALOGD_IF(isDebug(), "post heuristic handling failed");
Justin Philip37ab9a82015-01-06 11:55:12 +05301431 if(errno == ENOBUFS) {
1432 ALOGD_IF(isDebug(), "SMP Allocation failed");
1433 //On SMP allocation failure in video only comp add padding round
1434 ctx->isPaddingRound = true;
1435 }
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001436 reset(ctx);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07001437 return false;
1438 }
1439
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001440 ALOGD_IF(sSimulationFlags,"%s: VIDEO_ONLY_COMP SUCCEEDED",
1441 __FUNCTION__);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001442 return true;
1443}
1444
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001445/* if tryFullFrame fails, try to push all video and secure RGB layers to MDP */
1446bool MDPComp::tryMDPOnlyLayers(hwc_context_t *ctx,
1447 hwc_display_contents_1_t* list) {
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001448 // Fall back to video only composition, if AIV video mode is enabled
1449 if(ctx->listStats[mDpy].mAIVVideoMode) {
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07001450 ALOGD_IF(isDebug(), "%s: AIV Video Mode enabled dpy %d",
1451 __FUNCTION__, mDpy);
1452 return false;
1453 }
1454
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05001455 // No MDP composition for 3D
1456 if(needs3DComposition(ctx,mDpy))
1457 return false;
1458
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001459 const bool secureOnly = true;
1460 return mdpOnlyLayersComp(ctx, list, not secureOnly) or
1461 mdpOnlyLayersComp(ctx, list, secureOnly);
1462
1463}
1464
1465bool MDPComp::mdpOnlyLayersComp(hwc_context_t *ctx,
1466 hwc_display_contents_1_t* list, bool secureOnly) {
1467
1468 if(sSimulationFlags & MDPCOMP_AVOID_MDP_ONLY_LAYERS)
1469 return false;
1470
Praveena Pachipulusu47346c22014-12-04 11:06:41 +05301471 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
1472 if(!isSecurePresent(ctx, mDpy) && !ctx->listStats[mDpy].secureUI) {
1473 /* Bail out if we are processing only secured video/ui layers
1474 * and we dont have any */
1475 if(secureOnly) {
1476 ALOGD_IF(isDebug(), "%s: No secure video/ui layers");
1477 return false;
1478 }
1479 /* No Idle fall back for secure video/ui layers and if there is only
1480 * single layer being composed. */
1481 if(sIdleFallBack && (ctx->listStats[mDpy].numAppLayers > 1)) {
1482 ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
1483 return false;
1484 }
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001485 }
1486
Tatenda Chipeperekwa95675a72014-12-15 17:06:43 -08001487 /* Bail out if we dont have any secure RGB layers */
1488 if (!ctx->listStats[mDpy].secureRGBCount) {
1489 reset(ctx);
1490 return false;
1491 }
1492
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001493 mCurrentFrame.reset(numAppLayers);
1494 mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
1495
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001496 updateYUV(ctx, list, secureOnly, mCurrentFrame);
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001497 /* mark secure RGB layers for MDP comp */
1498 updateSecureRGB(ctx, list);
1499
1500 if(mCurrentFrame.mdpCount == 0) {
1501 reset(ctx);
1502 return false;
1503 }
1504
1505 /* find the maximum batch of layers to be marked for framebuffer */
1506 bool ret = markLayersForCaching(ctx, list); //sets up fbZ also
1507 if(!ret) {
1508 ALOGD_IF(isDebug(),"%s: batching failed, dpy %d",__FUNCTION__, mDpy);
1509 reset(ctx);
1510 return false;
1511 }
1512
1513 if(sEnableYUVsplit){
1514 adjustForSourceSplit(ctx, list);
1515 }
1516
1517 if(!postHeuristicsHandling(ctx, list)) {
1518 ALOGD_IF(isDebug(), "post heuristic handling failed");
1519 reset(ctx);
1520 return false;
1521 }
1522
1523 ALOGD_IF(sSimulationFlags,"%s: MDP_ONLY_LAYERS_COMP SUCCEEDED",
1524 __FUNCTION__);
1525 return true;
1526}
1527
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001528/* Checks for conditions where YUV layers cannot be bypassed */
1529bool MDPComp::isYUVDoable(hwc_context_t* ctx, hwc_layer_1_t* layer) {
Ramkumar Radhakrishnana70981a2013-08-28 11:33:53 -07001530 if(isSkipLayer(layer)) {
Saurabh Shahe2474082013-05-15 16:32:13 -07001531 ALOGD_IF(isDebug(), "%s: Video marked SKIP dpy %d", __FUNCTION__, mDpy);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001532 return false;
1533 }
1534
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08001535 if(has90Transform(layer) && !canUseRotator(ctx, mDpy)) {
Amara Venkata Mastan Manoj Kumar9d373c02013-08-20 14:30:09 -07001536 ALOGD_IF(isDebug(), "%s: no free DMA pipe",__FUNCTION__);
1537 return false;
1538 }
1539
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001540 if(isSecuring(ctx, layer)) {
1541 ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
1542 return false;
1543 }
1544
Saurabh Shah4fdde762013-04-30 18:47:33 -07001545 if(!isValidDimension(ctx, layer)) {
1546 ALOGD_IF(isDebug(), "%s: Buffer is of invalid width",
1547 __FUNCTION__);
1548 return false;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001549 }
Saurabh Shah4fdde762013-04-30 18:47:33 -07001550
Naseer Ahmeddc61a972013-07-10 17:50:54 -04001551 if(layer->planeAlpha < 0xFF) {
1552 ALOGD_IF(isDebug(), "%s: Cannot handle YUV layer with plane alpha\
1553 in video only mode",
1554 __FUNCTION__);
1555 return false;
1556 }
1557
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001558 return true;
1559}
1560
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001561/* Checks for conditions where Secure RGB layers cannot be bypassed */
1562bool MDPComp::isSecureRGBDoable(hwc_context_t* ctx, hwc_layer_1_t* layer) {
1563 if(isSkipLayer(layer)) {
1564 ALOGD_IF(isDebug(), "%s: Secure RGB layer marked SKIP dpy %d",
1565 __FUNCTION__, mDpy);
1566 return false;
1567 }
1568
1569 if(isSecuring(ctx, layer)) {
1570 ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
1571 return false;
1572 }
1573
1574 if(not isSupportedForMDPComp(ctx, layer)) {
1575 ALOGD_IF(isDebug(), "%s: Unsupported secure RGB layer",
1576 __FUNCTION__);
1577 return false;
1578 }
1579 return true;
1580}
1581
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301582/* starts at fromIndex and check for each layer to find
1583 * if it it has overlapping with any Updating layer above it in zorder
1584 * till the end of the batch. returns true if it finds any intersection */
1585bool MDPComp::canPushBatchToTop(const hwc_display_contents_1_t* list,
1586 int fromIndex, int toIndex) {
1587 for(int i = fromIndex; i < toIndex; i++) {
1588 if(mCurrentFrame.isFBComposed[i] && !mCurrentFrame.drop[i]) {
1589 if(intersectingUpdatingLayers(list, i+1, toIndex, i)) {
1590 return false;
1591 }
1592 }
1593 }
1594 return true;
1595}
1596
1597/* Checks if given layer at targetLayerIndex has any
1598 * intersection with all the updating layers in beween
1599 * fromIndex and toIndex. Returns true if it finds intersectiion */
1600bool MDPComp::intersectingUpdatingLayers(const hwc_display_contents_1_t* list,
1601 int fromIndex, int toIndex, int targetLayerIndex) {
1602 for(int i = fromIndex; i <= toIndex; i++) {
1603 if(!mCurrentFrame.isFBComposed[i]) {
1604 if(areLayersIntersecting(&list->hwLayers[i],
1605 &list->hwLayers[targetLayerIndex])) {
1606 return true;
1607 }
1608 }
1609 }
1610 return false;
1611}
1612
1613int MDPComp::getBatch(hwc_display_contents_1_t* list,
1614 int& maxBatchStart, int& maxBatchEnd,
1615 int& maxBatchCount) {
1616 int i = 0;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301617 int fbZOrder =-1;
Jeykumar Sankaran9502f352014-01-20 12:25:32 -08001618 int droppedLayerCt = 0;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301619 while (i < mCurrentFrame.layerCount) {
1620 int batchCount = 0;
1621 int batchStart = i;
1622 int batchEnd = i;
Jeykumar Sankaran9502f352014-01-20 12:25:32 -08001623 /* Adjust batch Z order with the dropped layers so far */
1624 int fbZ = batchStart - droppedLayerCt;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301625 int firstZReverseIndex = -1;
Prabhanjan Kandula0ed2cc92013-12-06 12:39:04 +05301626 int updatingLayersAbove = 0;//Updating layer count in middle of batch
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301627 while(i < mCurrentFrame.layerCount) {
1628 if(!mCurrentFrame.isFBComposed[i]) {
1629 if(!batchCount) {
1630 i++;
1631 break;
1632 }
1633 updatingLayersAbove++;
1634 i++;
1635 continue;
1636 } else {
1637 if(mCurrentFrame.drop[i]) {
1638 i++;
Jeykumar Sankaran9502f352014-01-20 12:25:32 -08001639 droppedLayerCt++;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301640 continue;
1641 } else if(updatingLayersAbove <= 0) {
1642 batchCount++;
1643 batchEnd = i;
1644 i++;
1645 continue;
1646 } else { //Layer is FBComposed, not a drop & updatingLayer > 0
1647
1648 // We have a valid updating layer already. If layer-i not
1649 // have overlapping with all updating layers in between
1650 // batch-start and i, then we can add layer i to batch.
1651 if(!intersectingUpdatingLayers(list, batchStart, i-1, i)) {
1652 batchCount++;
1653 batchEnd = i;
1654 i++;
1655 continue;
1656 } else if(canPushBatchToTop(list, batchStart, i)) {
1657 //If All the non-updating layers with in this batch
1658 //does not have intersection with the updating layers
1659 //above in z-order, then we can safely move the batch to
1660 //higher z-order. Increment fbZ as it is moving up.
1661 if( firstZReverseIndex < 0) {
1662 firstZReverseIndex = i;
1663 }
1664 batchCount++;
1665 batchEnd = i;
1666 fbZ += updatingLayersAbove;
1667 i++;
1668 updatingLayersAbove = 0;
1669 continue;
1670 } else {
1671 //both failed.start the loop again from here.
1672 if(firstZReverseIndex >= 0) {
1673 i = firstZReverseIndex;
1674 }
1675 break;
1676 }
1677 }
1678 }
1679 }
1680 if(batchCount > maxBatchCount) {
1681 maxBatchCount = batchCount;
1682 maxBatchStart = batchStart;
1683 maxBatchEnd = batchEnd;
1684 fbZOrder = fbZ;
1685 }
1686 }
1687 return fbZOrder;
1688}
1689
1690bool MDPComp::markLayersForCaching(hwc_context_t* ctx,
1691 hwc_display_contents_1_t* list) {
1692 /* Idea is to keep as many non-updating(cached) layers in FB and
1693 * send rest of them through MDP. This is done in 2 steps.
1694 * 1. Find the maximum contiguous batch of non-updating layers.
1695 * 2. See if we can improve this batch size for caching by adding
1696 * opaque layers around the batch, if they don't have
1697 * any overlapping with the updating layers in between.
1698 * NEVER mark an updating layer for caching.
1699 * But cached ones can be marked for MDP */
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001700
1701 int maxBatchStart = -1;
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001702 int maxBatchEnd = -1;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001703 int maxBatchCount = 0;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301704 int fbZ = -1;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001705
Saurabh Shahd53bc5f2014-02-05 10:17:43 -08001706 /* Nothing is cached. No batching needed */
1707 if(mCurrentFrame.fbCount == 0) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001708 return true;
Saurabh Shahaa236822013-04-24 18:07:26 -07001709 }
Saurabh Shahd53bc5f2014-02-05 10:17:43 -08001710
1711 /* No MDP comp layers, try to use other comp modes */
1712 if(mCurrentFrame.mdpCount == 0) {
1713 return false;
Saurabh Shahaa236822013-04-24 18:07:26 -07001714 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001715
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301716 fbZ = getBatch(list, maxBatchStart, maxBatchEnd, maxBatchCount);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001717
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301718 /* reset rest of the layers lying inside ROI for MDP comp */
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001719 for(int i = 0; i < mCurrentFrame.layerCount; i++) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001720 hwc_layer_1_t* layer = &list->hwLayers[i];
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001721 if((i < maxBatchStart || i > maxBatchEnd) &&
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301722 mCurrentFrame.isFBComposed[i]){
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001723 if(!mCurrentFrame.drop[i]){
1724 //If an unsupported layer is being attempted to
1725 //be pulled out we should fail
1726 if(not isSupportedForMDPComp(ctx, layer)) {
1727 return false;
1728 }
1729 mCurrentFrame.isFBComposed[i] = false;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001730 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001731 }
1732 }
1733
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301734 // update the frame data
1735 mCurrentFrame.fbZ = fbZ;
1736 mCurrentFrame.fbCount = maxBatchCount;
Saurabh Shahaa236822013-04-24 18:07:26 -07001737 mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001738 mCurrentFrame.fbCount - mCurrentFrame.dropCount;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001739
1740 ALOGD_IF(isDebug(),"%s: cached count: %d",__FUNCTION__,
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301741 mCurrentFrame.fbCount);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001742
1743 return true;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001744}
Saurabh Shah85234ec2013-04-12 17:09:00 -07001745
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001746void MDPComp::updateLayerCache(hwc_context_t* ctx,
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001747 hwc_display_contents_1_t* list, FrameInfo& frame) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001748 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001749 int fbCount = 0;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001750
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001751 for(int i = 0; i < numAppLayers; i++) {
1752 if (mCachedFrame.hnd[i] == list->hwLayers[i].handle) {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001753 if(!frame.drop[i])
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001754 fbCount++;
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001755 frame.isFBComposed[i] = true;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001756 } else {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001757 frame.isFBComposed[i] = false;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001758 }
1759 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001760
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001761 frame.fbCount = fbCount;
1762 frame.mdpCount = frame.layerCount - frame.fbCount
1763 - frame.dropCount;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001764
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001765 ALOGD_IF(isDebug(),"%s: MDP count: %d FB count %d drop count: %d",
1766 __FUNCTION__, frame.mdpCount, frame.fbCount, frame.dropCount);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001767}
1768
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001769// drop other non-AIV layers from external display list.
1770void MDPComp::dropNonAIVLayers(hwc_context_t* ctx,
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07001771 hwc_display_contents_1_t* list) {
1772 for (size_t i = 0; i < (size_t)ctx->listStats[mDpy].numAppLayers; i++) {
1773 hwc_layer_1_t * layer = &list->hwLayers[i];
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001774 if(!(isAIVVideoLayer(layer) || isAIVCCLayer(layer))) {
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07001775 mCurrentFrame.dropCount++;
1776 mCurrentFrame.drop[i] = true;
1777 }
1778 }
1779 mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
1780 mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
1781 mCurrentFrame.fbCount - mCurrentFrame.dropCount;
1782 ALOGD_IF(isDebug(),"%s: fb count: %d mdp count %d drop count %d",
1783 __FUNCTION__, mCurrentFrame.fbCount, mCurrentFrame.mdpCount,
1784 mCurrentFrame.dropCount);
1785}
1786
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001787void MDPComp::updateYUV(hwc_context_t* ctx, hwc_display_contents_1_t* list,
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001788 bool secureOnly, FrameInfo& frame) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001789 int nYuvCount = ctx->listStats[mDpy].yuvCount;
1790 for(int index = 0;index < nYuvCount; index++){
1791 int nYuvIndex = ctx->listStats[mDpy].yuvIndices[index];
1792 hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
1793
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001794 if(mCurrentFrame.drop[nYuvIndex]) {
1795 continue;
1796 }
1797
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001798 if(!isYUVDoable(ctx, layer)) {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001799 if(!frame.isFBComposed[nYuvIndex]) {
1800 frame.isFBComposed[nYuvIndex] = true;
1801 frame.fbCount++;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001802 }
1803 } else {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001804 if(frame.isFBComposed[nYuvIndex]) {
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001805 private_handle_t *hnd = (private_handle_t *)layer->handle;
1806 if(!secureOnly || isSecureBuffer(hnd)) {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001807 frame.isFBComposed[nYuvIndex] = false;
1808 frame.fbCount--;
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001809 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001810 }
1811 }
1812 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001813
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001814 frame.mdpCount = frame.layerCount - frame.fbCount - frame.dropCount;
1815 ALOGD_IF(isDebug(),"%s: fb count: %d",__FUNCTION__, frame.fbCount);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001816}
1817
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001818void MDPComp::updateSecureRGB(hwc_context_t* ctx,
1819 hwc_display_contents_1_t* list) {
1820 int nSecureRGBCount = ctx->listStats[mDpy].secureRGBCount;
1821 for(int index = 0;index < nSecureRGBCount; index++){
1822 int nSecureRGBIndex = ctx->listStats[mDpy].secureRGBIndices[index];
1823 hwc_layer_1_t* layer = &list->hwLayers[nSecureRGBIndex];
1824
1825 if(!isSecureRGBDoable(ctx, layer)) {
1826 if(!mCurrentFrame.isFBComposed[nSecureRGBIndex]) {
1827 mCurrentFrame.isFBComposed[nSecureRGBIndex] = true;
1828 mCurrentFrame.fbCount++;
1829 }
1830 } else {
1831 if(mCurrentFrame.isFBComposed[nSecureRGBIndex]) {
1832 mCurrentFrame.isFBComposed[nSecureRGBIndex] = false;
1833 mCurrentFrame.fbCount--;
1834 }
1835 }
1836 }
1837
1838 mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
1839 mCurrentFrame.fbCount - mCurrentFrame.dropCount;
1840 ALOGD_IF(isDebug(),"%s: fb count: %d",__FUNCTION__,
1841 mCurrentFrame.fbCount);
1842}
1843
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001844hwc_rect_t MDPComp::getUpdatingFBRect(hwc_context_t *ctx,
1845 hwc_display_contents_1_t* list){
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001846 hwc_rect_t fbRect = (struct hwc_rect){0, 0, 0, 0};
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001847
1848 /* Update only the region of FB needed for composition */
1849 for(int i = 0; i < mCurrentFrame.layerCount; i++ ) {
1850 if(mCurrentFrame.isFBComposed[i] && !mCurrentFrame.drop[i]) {
1851 hwc_layer_1_t* layer = &list->hwLayers[i];
1852 hwc_rect_t dst = layer->displayFrame;
1853 fbRect = getUnion(fbRect, dst);
1854 }
1855 }
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08001856 trimAgainstROI(ctx, fbRect, fbRect);
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001857 return fbRect;
1858}
1859
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001860bool MDPComp::postHeuristicsHandling(hwc_context_t *ctx,
1861 hwc_display_contents_1_t* list) {
1862
1863 //Capability checks
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08001864 if(!resourceCheck(ctx, list)) {
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001865 ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
1866 return false;
1867 }
1868
1869 //Limitations checks
1870 if(!hwLimitationsCheck(ctx, list)) {
1871 ALOGD_IF(isDebug(), "%s: HW limitations",__FUNCTION__);
1872 return false;
1873 }
1874
Saurabh Shah3d4b8042013-12-10 15:19:17 -08001875 //Configure framebuffer first if applicable
1876 if(mCurrentFrame.fbZ >= 0) {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001877 hwc_rect_t fbRect = getUpdatingFBRect(ctx, list);
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001878 if(!ctx->mFBUpdate[mDpy]->prepare(ctx, list, fbRect, mCurrentFrame.fbZ))
1879 {
Saurabh Shah3d4b8042013-12-10 15:19:17 -08001880 ALOGD_IF(isDebug(), "%s configure framebuffer failed",
1881 __FUNCTION__);
1882 return false;
1883 }
1884 }
1885
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001886 mCurrentFrame.map();
1887
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001888 if(!allocLayerPipes(ctx, list)) {
1889 ALOGD_IF(isDebug(), "%s: Unable to allocate MDP pipes", __FUNCTION__);
Saurabh Shahaa236822013-04-24 18:07:26 -07001890 return false;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001891 }
1892
1893 for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
Saurabh Shahaa236822013-04-24 18:07:26 -07001894 index++) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001895 if(!mCurrentFrame.isFBComposed[index]) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001896 int mdpIndex = mCurrentFrame.layerToMDP[index];
1897 hwc_layer_1_t* layer = &list->hwLayers[index];
1898
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301899 //Leave fbZ for framebuffer. CACHE/GLES layers go here.
1900 if(mdpNextZOrder == mCurrentFrame.fbZ) {
1901 mdpNextZOrder++;
1902 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001903 MdpPipeInfo* cur_pipe = mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
1904 cur_pipe->zOrder = mdpNextZOrder++;
1905
radhakrishnac9a67412013-09-25 17:40:42 +05301906 private_handle_t *hnd = (private_handle_t *)layer->handle;
Raj Kamal389d6e32014-08-04 14:43:24 +05301907 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
radhakrishnac9a67412013-09-25 17:40:42 +05301908 if(configure4k2kYuv(ctx, layer,
1909 mCurrentFrame.mdpToLayer[mdpIndex])
1910 != 0 ){
1911 ALOGD_IF(isDebug(), "%s: Failed to configure split pipes \
1912 for layer %d",__FUNCTION__, index);
1913 return false;
1914 }
1915 else{
1916 mdpNextZOrder++;
1917 }
1918 continue;
1919 }
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05001920 if(needs3DComposition(ctx,mDpy) && get3DFormat(hnd) != HAL_NO_3D) {
1921 mdpNextZOrder++;
1922 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001923 if(configure(ctx, layer, mCurrentFrame.mdpToLayer[mdpIndex]) != 0 ){
1924 ALOGD_IF(isDebug(), "%s: Failed to configure overlay for \
radhakrishnac9a67412013-09-25 17:40:42 +05301925 layer %d",__FUNCTION__, index);
Saurabh Shahaa236822013-04-24 18:07:26 -07001926 return false;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001927 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001928 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001929 }
1930
Saurabh Shaha36be922013-12-16 18:18:39 -08001931 if(!ctx->mOverlay->validateAndSet(mDpy, ctx->dpyAttr[mDpy].fd)) {
1932 ALOGD_IF(isDebug(), "%s: Failed to validate and set overlay for dpy %d"
1933 ,__FUNCTION__, mDpy);
1934 return false;
1935 }
1936
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001937 setRedraw(ctx, list);
Saurabh Shahaa236822013-04-24 18:07:26 -07001938 return true;
1939}
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001940
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08001941bool MDPComp::resourceCheck(hwc_context_t* ctx,
1942 hwc_display_contents_1_t* list) {
Saurabh Shah173f4242013-11-20 09:50:12 -08001943 const bool fbUsed = mCurrentFrame.fbCount;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001944 int cursorInUse = 0;
1945 if(mDpy == HWC_DISPLAY_PRIMARY) {
1946 // check if cursor is in use for primary
1947 cursorInUse = HWCursor::getInstance()->isCursorSet();
1948 }
1949 int maxStages = qdutils::MDPVersion::getInstance().getBlendStages();
1950 // HW Cursor needs one blending stage, account for that in the check below
1951 // On high end targets(8994) has 8 blending stages, HAL is configured to use < 8.
1952 // Make use of the remaining stages for HW Cursor so that the composition
1953 // strategy would not fail due to this limitation.
1954 if (maxStages > sMaxPipesPerMixer) {
1955 cursorInUse = 0;
1956 }
1957 if(mCurrentFrame.mdpCount > (sMaxPipesPerMixer - fbUsed - cursorInUse)) {
Saurabh Shah173f4242013-11-20 09:50:12 -08001958 ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
1959 return false;
1960 }
Saurabh Shahacec8e42014-11-25 11:07:04 -08001961
1962 //Will benefit cases where a video has non-updating background.
1963 if((mDpy > HWC_DISPLAY_PRIMARY) and
1964 (mCurrentFrame.mdpCount > sMaxSecLayers)) {
1965 ALOGD_IF(isDebug(), "%s: Exceeds max secondary pipes",__FUNCTION__);
1966 return false;
1967 }
1968
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08001969 // Init rotCount to number of rotate sessions used by other displays
1970 int rotCount = ctx->mRotMgr->getNumActiveSessions();
1971 // Count the number of rotator sessions required for current display
1972 for (int index = 0; index < mCurrentFrame.layerCount; index++) {
1973 if(!mCurrentFrame.isFBComposed[index]) {
1974 hwc_layer_1_t* layer = &list->hwLayers[index];
1975 private_handle_t *hnd = (private_handle_t *)layer->handle;
1976 if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
1977 rotCount++;
1978 }
1979 }
1980 }
1981 // if number of layers to rotate exceeds max rotator sessions, bail out.
1982 if(rotCount > RotMgr::MAX_ROT_SESS) {
1983 ALOGD_IF(isDebug(), "%s: Exceeds max rotator sessions %d",
1984 __FUNCTION__, mDpy);
1985 return false;
1986 }
Saurabh Shah173f4242013-11-20 09:50:12 -08001987 return true;
1988}
1989
Prabhanjan Kandula21918db2013-11-26 15:51:58 +05301990bool MDPComp::hwLimitationsCheck(hwc_context_t* ctx,
1991 hwc_display_contents_1_t* list) {
1992
1993 //A-family hw limitation:
1994 //If a layer need alpha scaling, MDP can not support.
1995 if(ctx->mMDP.version < qdutils::MDSS_V5) {
1996 for(int i = 0; i < mCurrentFrame.layerCount; ++i) {
1997 if(!mCurrentFrame.isFBComposed[i] &&
1998 isAlphaScaled( &list->hwLayers[i])) {
1999 ALOGD_IF(isDebug(), "%s:frame needs alphaScaling",__FUNCTION__);
2000 return false;
2001 }
2002 }
2003 }
2004
2005 // On 8x26 & 8974 hw, we have a limitation of downscaling+blending.
2006 //If multiple layers requires downscaling and also they are overlapping
2007 //fall back to GPU since MDSS can not handle it.
2008 if(qdutils::MDPVersion::getInstance().is8x74v2() ||
2009 qdutils::MDPVersion::getInstance().is8x26()) {
2010 for(int i = 0; i < mCurrentFrame.layerCount-1; ++i) {
2011 hwc_layer_1_t* botLayer = &list->hwLayers[i];
2012 if(!mCurrentFrame.isFBComposed[i] &&
2013 isDownscaleRequired(botLayer)) {
2014 //if layer-i is marked for MDP and needs downscaling
2015 //check if any MDP layer on top of i & overlaps with layer-i
2016 for(int j = i+1; j < mCurrentFrame.layerCount; ++j) {
2017 hwc_layer_1_t* topLayer = &list->hwLayers[j];
2018 if(!mCurrentFrame.isFBComposed[j] &&
2019 isDownscaleRequired(topLayer)) {
2020 hwc_rect_t r = getIntersection(botLayer->displayFrame,
2021 topLayer->displayFrame);
2022 if(isValidRect(r))
2023 return false;
2024 }
2025 }
2026 }
2027 }
2028 }
2029 return true;
2030}
2031
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002032static bool validForCursor(hwc_context_t* ctx, int dpy, hwc_layer_1_t* layer) {
2033 private_handle_t *hnd = (private_handle_t *)layer->handle;
2034 hwc_rect dst = layer->displayFrame;
2035 hwc_rect src = integerizeSourceCrop(layer->sourceCropf);
2036 int srcW = src.right - src.left;
2037 int srcH = src.bottom - src.top;
2038 int dstW = dst.right - dst.left;
2039 int dstH = dst.bottom - dst.top;
2040 qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
2041 uint32_t maxCursorSize = mdpVersion.getMaxCursorSize();
2042 uint32_t numHwCursors = mdpVersion.getCursorPipes();
2043 bool primarySplit = isDisplaySplit(ctx, HWC_DISPLAY_PRIMARY);
2044 uint32_t cursorPipesNeeded = 1; // One cursor pipe needed(default)
2045 bool ret = false;
2046
2047 if(dpy > HWC_DISPLAY_PRIMARY) {
2048 // Cursor not supported on secondary displays, as it involves scaling
2049 // in most of the cases
2050 return false;
2051 } else if (isSkipLayer(layer)) {
2052 return false;
2053 // Checks for HW limitation
2054 } else if (numHwCursors == 0 || maxCursorSize <= 0) {
2055 return false;
2056 } else if (needsScaling(layer)) {
2057 return false;
2058 } else if (layer->transform != 0) {
2059 return false;
2060 } else if (hnd->format != HAL_PIXEL_FORMAT_RGBA_8888) {
2061 return false;
2062 } else if (srcW > (int)maxCursorSize || srcH > (int)maxCursorSize) {
2063 return false;
2064 }
2065
2066 if (isDisplaySplit(ctx, dpy) && !mdpVersion.isSrcSplit()) {
2067 // In case of split display with no srcSplit, the driver allocates two
2068 // pipes to support async position update across mixers, hence
2069 // need to account for that here.
2070 cursorPipesNeeded = 2;
2071 }
2072 if (cursorPipesNeeded <= numHwCursors) {
2073 ret = true;
2074 }
2075 return ret;
2076}
2077
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08002078// Checks only if videos or single layer(RGB) is updating
2079// which is used for setting dynamic fps or perf hint for single
2080// layer video playback
2081bool MDPComp::onlyVideosUpdating(hwc_context_t *ctx,
2082 hwc_display_contents_1_t* list) {
2083 bool support = false;
2084 FrameInfo frame;
2085 frame.reset(mCurrentFrame.layerCount);
2086 memset(&frame.drop, 0, sizeof(frame.drop));
2087 frame.dropCount = 0;
2088 ALOGD_IF(isDebug(), "%s: Update Cache and YUVInfo", __FUNCTION__);
2089 updateLayerCache(ctx, list, frame);
2090 updateYUV(ctx, list, false /*secure only*/, frame);
2091 // There are only updating YUV layers or there is single RGB
2092 // Layer(Youtube)
2093 if((ctx->listStats[mDpy].yuvCount == frame.mdpCount) ||
2094 (frame.layerCount == 1)) {
2095 support = true;
2096 }
2097 return support;
2098}
2099
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302100void MDPComp::setDynRefreshRate(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
2101 //For primary display, set the dynamic refreshrate
2102 if(!mDpy && qdutils::MDPVersion::getInstance().isDynFpsSupported() &&
2103 ctx->mUseMetaDataRefreshRate) {
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302104 uint32_t refreshRate = ctx->dpyAttr[mDpy].refreshRate;
2105 MDPVersion& mdpHw = MDPVersion::getInstance();
2106 if(sIdleFallBack) {
2107 //Set minimum panel refresh rate during idle timeout
2108 refreshRate = mdpHw.getMinFpsSupported();
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08002109 } else if(onlyVideosUpdating(ctx, list)) {
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302110 //Set the new fresh rate, if there is only one updating YUV layer
2111 //or there is one single RGB layer with this request
2112 refreshRate = ctx->listStats[mDpy].refreshRateRequest;
2113 }
2114 setRefreshRate(ctx, mDpy, refreshRate);
2115 }
2116}
2117
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002118int MDPComp::prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002119 int ret = 0;
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07002120 char property[PROPERTY_VALUE_MAX];
2121
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002122 if(!list) {
2123 ALOGE("%s: Invalid list", __FUNCTION__);
Raj Kamal4393eaa2014-06-06 13:45:20 +05302124 mCachedFrame.reset();
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002125 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Raj Kamal4393eaa2014-06-06 13:45:20 +05302126 return -1;
2127 }
2128
2129 const int numLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shah286cf122014-09-08 14:13:08 -07002130 if(mDpy == HWC_DISPLAY_PRIMARY) {
2131 sSimulationFlags = 0;
2132 if(property_get("debug.hwc.simulate", property, NULL) > 0) {
2133 int currentFlags = atoi(property);
2134 if(currentFlags != sSimulationFlags) {
2135 sSimulationFlags = currentFlags;
2136 ALOGI("%s: Simulation Flag read: 0x%x (%d)", __FUNCTION__,
2137 sSimulationFlags, sSimulationFlags);
2138 }
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07002139 }
2140 }
Ramkumar Radhakrishnanc5893f12013-06-06 19:43:53 -07002141
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302142 //reset old data
2143 mCurrentFrame.reset(numLayers);
2144 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
2145 mCurrentFrame.dropCount = 0;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002146 mCurrentFrame.hwCursorIndex = -1;
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302147
Raj Kamal9ed3d6b2014-02-07 16:15:17 +05302148 //Do not cache the information for next draw cycle.
2149 if(numLayers > MAX_NUM_APP_LAYERS or (!numLayers)) {
2150 ALOGI("%s: Unsupported layer count for mdp composition",
2151 __FUNCTION__);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002152 mCachedFrame.reset();
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302153#ifdef DYNAMIC_FPS
2154 setDynRefreshRate(ctx, list);
2155#endif
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002156 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002157 return -1;
2158 }
2159
Ramkumar Radhakrishnana70981a2013-08-28 11:33:53 -07002160 // Detect the start of animation and fall back to GPU only once to cache
2161 // all the layers in FB and display FB content untill animation completes.
2162 if(ctx->listStats[mDpy].isDisplayAnimating) {
2163 mCurrentFrame.needsRedraw = false;
2164 if(ctx->mAnimationState[mDpy] == ANIMATION_STOPPED) {
2165 mCurrentFrame.needsRedraw = true;
2166 ctx->mAnimationState[mDpy] = ANIMATION_STARTED;
2167 }
2168 setMDPCompLayerFlags(ctx, list);
2169 mCachedFrame.updateCounts(mCurrentFrame);
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302170#ifdef DYNAMIC_FPS
2171 setDynRefreshRate(ctx, list);
2172#endif
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002173 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Ramkumar Radhakrishnana70981a2013-08-28 11:33:53 -07002174 ret = -1;
2175 return ret;
2176 } else {
2177 ctx->mAnimationState[mDpy] = ANIMATION_STOPPED;
2178 }
2179
Raj Kamalfdfdddf2015-03-16 21:59:25 +05302180 if(!mDpy and !isSecondaryConnected(ctx) and !mPrevModeOn and
2181 mCachedFrame.isSameFrame(ctx,mDpy,list)) {
2182
2183 ALOGD_IF(isDebug(),"%s: Avoid new composition",__FUNCTION__);
2184 mCurrentFrame.needsRedraw = false;
2185 setMDPCompLayerFlags(ctx, list);
2186 mCachedFrame.updateCounts(mCurrentFrame);
2187#ifdef DYNAMIC_FPS
2188 setDynRefreshRate(ctx, list);
2189#endif
2190 return -1;
2191
2192 }
2193
Saurabh Shahb39f8152013-08-22 10:21:44 -07002194 //Hard conditions, if not met, cannot do MDP comp
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002195 if(isFrameDoable(ctx)) {
2196 generateROI(ctx, list);
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07002197 // if AIV Video mode is enabled, drop all non AIV layers from the
2198 // external display list.
2199 if(ctx->listStats[mDpy].mAIVVideoMode) {
2200 dropNonAIVLayers(ctx, list);
2201 }
Saurabh Shahb39f8152013-08-22 10:21:44 -07002202
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002203 // Configure the cursor if present
2204 int topIndex = ctx->listStats[mDpy].numAppLayers - 1;
2205 if(ctx->listStats[mDpy].cursorLayerPresent &&
2206 validForCursor(ctx, mDpy, &(list->hwLayers[topIndex]))) {
2207 if(configHwCursor(ctx->dpyAttr[mDpy].fd, mDpy,
2208 &(list->hwLayers[topIndex]))) {
2209 // As cursor is configured, mark that layer as dropped, so that
2210 // it wont be considered for composition by other strategies.
2211 mCurrentFrame.hwCursorIndex = topIndex;
2212 mCurrentFrame.drop[topIndex] = true;
2213 mCurrentFrame.dropCount++;
2214 }
2215 } else {
2216 // Release the hw cursor
2217 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
2218 }
2219
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07002220 // if tryFullFrame fails, try to push all video and secure RGB layers
2221 // to MDP for composition.
2222 mModeOn = tryFullFrame(ctx, list) || tryMDPOnlyLayers(ctx, list) ||
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07002223 tryVideoOnly(ctx, list);
Raj Kamal4393eaa2014-06-06 13:45:20 +05302224 if(mModeOn) {
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002225 setMDPCompLayerFlags(ctx, list);
2226 } else {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08002227 resetROI(ctx, mDpy);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002228 reset(ctx);
2229 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
2230 mCurrentFrame.dropCount = 0;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002231 // Check if cursor is in use for primary and mark accordingly
2232 if(!mDpy && HWCursor::getInstance()->isCursorSet()) {
2233 int topIndex = ctx->listStats[mDpy].numAppLayers - 1;
2234 hwc_layer_1_t *layer = &(list->hwLayers[topIndex]);
2235 layer->compositionType = HWC_CURSOR_OVERLAY;
2236 }
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002237 ret = -1;
Saurabh Shah286cf122014-09-08 14:13:08 -07002238 ALOGE_IF(sSimulationFlags && (mDpy == HWC_DISPLAY_PRIMARY),
2239 "MDP Composition Strategies Failed");
Saurabh Shahb39f8152013-08-22 10:21:44 -07002240 }
2241 } else {
Dileep Kumar Reddi4070e932014-09-30 09:00:57 +05302242 if ((ctx->mMDP.version == qdutils::MDP_V3_0_5) && ctx->mCopyBit[mDpy] &&
2243 enablePartialUpdateForMDP3) {
2244 generateROI(ctx, list);
2245 for(int i = 0; i < ctx->listStats[mDpy].numAppLayers; i++) {
2246 ctx->copybitDrop[i] = mCurrentFrame.drop[i];
2247 }
2248 }
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002249 ALOGD_IF( isDebug(),"%s: MDP Comp not possible for this frame",
2250 __FUNCTION__);
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002251 // Release the hw cursor
2252 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002253 ret = -1;
Saurabh Shahb39f8152013-08-22 10:21:44 -07002254 }
Saurabh Shahb39f8152013-08-22 10:21:44 -07002255
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002256 if(isDebug()) {
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002257 ALOGD("GEOMETRY change: %d",
2258 (list->flags & HWC_GEOMETRY_CHANGED));
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002259 android::String8 sDump("");
Jeykumar Sankaran6850ac62014-05-27 10:07:26 -07002260 dump(sDump, ctx);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002261 ALOGD("%s",sDump.string());
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002262 }
2263
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07002264#ifdef DYNAMIC_FPS
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302265 setDynRefreshRate(ctx, list);
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07002266#endif
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08002267 setPerfHint(ctx, list);
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07002268
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002269 mCachedFrame.cacheAll(list);
2270 mCachedFrame.updateCounts(mCurrentFrame);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002271 return ret;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002272}
2273
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002274bool MDPComp::allocSplitVGPipes(hwc_context_t *ctx, int index) {
radhakrishnac9a67412013-09-25 17:40:42 +05302275
2276 bool bRet = true;
radhakrishnac9a67412013-09-25 17:40:42 +05302277 int mdpIndex = mCurrentFrame.layerToMDP[index];
2278 PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
2279 info.pipeInfo = new MdpYUVPipeInfo;
2280 info.rot = NULL;
2281 MdpYUVPipeInfo& pipe_info = *(MdpYUVPipeInfo*)info.pipeInfo;
radhakrishnac9a67412013-09-25 17:40:42 +05302282
2283 pipe_info.lIndex = ovutils::OV_INVALID;
2284 pipe_info.rIndex = ovutils::OV_INVALID;
2285
Saurabh Shahc62f3982014-03-05 14:28:26 -08002286 Overlay::PipeSpecs pipeSpecs;
2287 pipeSpecs.formatClass = Overlay::FORMAT_YUV;
2288 pipeSpecs.needsScaling = true;
2289 pipeSpecs.dpy = mDpy;
2290 pipeSpecs.fb = false;
2291
2292 pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
radhakrishnac9a67412013-09-25 17:40:42 +05302293 if(pipe_info.lIndex == ovutils::OV_INVALID){
2294 bRet = false;
2295 ALOGD_IF(isDebug(),"%s: allocating first VG pipe failed",
2296 __FUNCTION__);
2297 }
Saurabh Shahc62f3982014-03-05 14:28:26 -08002298 pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
radhakrishnac9a67412013-09-25 17:40:42 +05302299 if(pipe_info.rIndex == ovutils::OV_INVALID){
2300 bRet = false;
2301 ALOGD_IF(isDebug(),"%s: allocating second VG pipe failed",
2302 __FUNCTION__);
2303 }
2304 return bRet;
2305}
Sushil Chauhandefd3522014-05-13 18:17:12 -07002306
2307int MDPComp::drawOverlap(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
2308 int fd = -1;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002309 if (ctx->mPtorInfo.isActive()) {
2310 fd = ctx->mCopyBit[mDpy]->drawOverlap(ctx, list);
Sushil Chauhandefd3522014-05-13 18:17:12 -07002311 if (fd < 0) {
2312 ALOGD_IF(isDebug(),"%s: failed", __FUNCTION__);
Sushil Chauhandefd3522014-05-13 18:17:12 -07002313 }
2314 }
2315 return fd;
2316}
Arun Kumar K.R2aa44c62014-01-21 23:08:28 -08002317//=============MDPCompNonSplit==================================================
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002318
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002319void MDPCompNonSplit::adjustForSourceSplit(hwc_context_t *ctx,
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302320 hwc_display_contents_1_t* list) {
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002321 //If 4k2k Yuv layer split is possible, and if
2322 //fbz is above 4k2k layer, increment fb zorder by 1
2323 //as we split 4k2k layer and increment zorder for right half
2324 //of the layer
Shalaj Jaina70b4352014-06-15 13:47:47 -07002325 if(!ctx)
2326 return;
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002327 if(mCurrentFrame.fbZ >= 0) {
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302328 for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
2329 index++) {
2330 if(!mCurrentFrame.isFBComposed[index]) {
2331 if(mdpNextZOrder == mCurrentFrame.fbZ) {
2332 mdpNextZOrder++;
2333 }
2334 mdpNextZOrder++;
2335 hwc_layer_1_t* layer = &list->hwLayers[index];
2336 private_handle_t *hnd = (private_handle_t *)layer->handle;
Raj Kamal389d6e32014-08-04 14:43:24 +05302337 if(isYUVSplitNeeded(hnd)) {
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302338 if(mdpNextZOrder <= mCurrentFrame.fbZ)
2339 mCurrentFrame.fbZ += 1;
2340 mdpNextZOrder++;
2341 //As we split 4kx2k yuv layer and program to 2 VG pipes
2342 //(if available) increase mdpcount by 1.
2343 mCurrentFrame.mdpCount++;
2344 }
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002345 }
2346 }
2347 }
radhakrishnac9a67412013-09-25 17:40:42 +05302348}
2349
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002350/*
2351 * Configures pipe(s) for MDP composition
2352 */
Saurabh Shah88e4d272013-09-03 13:31:29 -07002353int MDPCompNonSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002354 PipeLayerPair& PipeLayerPair) {
Saurabh Shah88e4d272013-09-03 13:31:29 -07002355 MdpPipeInfoNonSplit& mdp_info =
2356 *(static_cast<MdpPipeInfoNonSplit*>(PipeLayerPair.pipeInfo));
Justin Philipd6166602014-08-12 13:42:21 +05302357 eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shahacf10202013-02-26 10:15:15 -08002358 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Saurabh Shahacf10202013-02-26 10:15:15 -08002359 eDest dest = mdp_info.index;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002360
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002361 ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipe: %d",
2362 __FUNCTION__, layer, zOrder, dest);
2363
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002364 return configureNonSplit(ctx, layer, mDpy, mdpFlags, zOrder, dest,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002365 &PipeLayerPair.rot);
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002366}
2367
Saurabh Shah88e4d272013-09-03 13:31:29 -07002368bool MDPCompNonSplit::allocLayerPipes(hwc_context_t *ctx,
Saurabh Shahe51f8ca2013-05-06 17:26:16 -07002369 hwc_display_contents_1_t* list) {
Saurabh Shah8cc77712015-03-31 10:48:51 -07002370 for(uint32_t formatType = FORMAT_YUV; formatType < FORMAT_MAX;
2371 formatType++) {
2372 for(int index = 0; index < mCurrentFrame.layerCount; index++) {
2373 if(mCurrentFrame.isFBComposed[index]) continue;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002374
Saurabh Shah8cc77712015-03-31 10:48:51 -07002375 hwc_layer_1_t* layer = &list->hwLayers[index];
2376 private_handle_t *hnd = (private_handle_t *)layer->handle;
2377 if(formatType == FORMAT_YUV && !isYuvBuffer(hnd))
radhakrishnac9a67412013-09-25 17:40:42 +05302378 continue;
Saurabh Shah8cc77712015-03-31 10:48:51 -07002379 if(formatType == FORMAT_RGB && isYuvBuffer(hnd))
2380 continue;
2381
2382 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
2383 if(allocSplitVGPipes(ctx, index)){
2384 continue;
2385 }
radhakrishnac9a67412013-09-25 17:40:42 +05302386 }
radhakrishnac9a67412013-09-25 17:40:42 +05302387
Saurabh Shah8cc77712015-03-31 10:48:51 -07002388 int mdpIndex = mCurrentFrame.layerToMDP[index];
2389 PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
2390 info.pipeInfo = new MdpPipeInfoNonSplit;
2391 info.rot = NULL;
2392 MdpPipeInfoNonSplit& pipe_info =
2393 *(MdpPipeInfoNonSplit*)info.pipeInfo;
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -08002394
Saurabh Shah8cc77712015-03-31 10:48:51 -07002395 Overlay::PipeSpecs pipeSpecs;
2396 pipeSpecs.formatClass = isYuvBuffer(hnd) ?
2397 Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
2398 pipeSpecs.needsScaling = qhwc::needsScaling(layer) or
2399 (qdutils::MDPVersion::getInstance().is8x26() and
2400 ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres > 1024);
2401 pipeSpecs.dpy = mDpy;
2402 pipeSpecs.fb = false;
2403 pipeSpecs.numActiveDisplays = ctx->numActiveDisplays;
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -08002404
Saurabh Shah8cc77712015-03-31 10:48:51 -07002405 pipe_info.index = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahc62f3982014-03-05 14:28:26 -08002406
Saurabh Shah8cc77712015-03-31 10:48:51 -07002407 if(pipe_info.index == ovutils::OV_INVALID) {
2408 ALOGD_IF(isDebug(), "%s: Unable to get pipe for layer %d of "\
2409 "format type %d", __FUNCTION__, index, formatType);
2410 return false;
2411 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002412 }
2413 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002414 return true;
2415}
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002416
radhakrishnac9a67412013-09-25 17:40:42 +05302417int MDPCompNonSplit::configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
2418 PipeLayerPair& PipeLayerPair) {
2419 MdpYUVPipeInfo& mdp_info =
2420 *(static_cast<MdpYUVPipeInfo*>(PipeLayerPair.pipeInfo));
2421 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Justin Philipd6166602014-08-12 13:42:21 +05302422 eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
radhakrishnac9a67412013-09-25 17:40:42 +05302423 eDest lDest = mdp_info.lIndex;
2424 eDest rDest = mdp_info.rIndex;
2425
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002426 return configureSourceSplit(ctx, layer, mDpy, mdpFlagsL, zOrder,
radhakrishnac9a67412013-09-25 17:40:42 +05302427 lDest, rDest, &PipeLayerPair.rot);
2428}
2429
Saurabh Shah88e4d272013-09-03 13:31:29 -07002430bool MDPCompNonSplit::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002431
Raj Kamal4393eaa2014-06-06 13:45:20 +05302432 if(!isEnabled() or !mModeOn) {
2433 ALOGD_IF(isDebug(),"%s: MDP Comp not enabled/configured", __FUNCTION__);
Prabhanjan Kandula08222fc2013-07-10 17:20:59 +05302434 return true;
2435 }
2436
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002437 overlay::Overlay& ov = *ctx->mOverlay;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002438 LayerProp *layerProp = ctx->layerProp[mDpy];
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002439
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002440 int numHwLayers = ctx->listStats[mDpy].numAppLayers;
2441 for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ )
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002442 {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002443 if(mCurrentFrame.isFBComposed[i]) continue;
2444
Naseer Ahmed5b6708a2012-08-02 13:46:08 -07002445 hwc_layer_1_t *layer = &list->hwLayers[i];
Saurabh Shahacf10202013-02-26 10:15:15 -08002446 private_handle_t *hnd = (private_handle_t *)layer->handle;
2447 if(!hnd) {
Sushil Chauhan897a9c32013-07-18 11:09:55 -07002448 if (!(layer->flags & HWC_COLOR_FILL)) {
2449 ALOGE("%s handle null", __FUNCTION__);
2450 return false;
2451 }
2452 // No PLAY for Color layer
2453 layerProp[i].mFlags &= ~HWC_MDPCOMP;
2454 continue;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002455 }
2456
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002457 int mdpIndex = mCurrentFrame.layerToMDP[i];
2458
Raj Kamal389d6e32014-08-04 14:43:24 +05302459 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit)
radhakrishnac9a67412013-09-25 17:40:42 +05302460 {
2461 MdpYUVPipeInfo& pipe_info =
2462 *(MdpYUVPipeInfo*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
2463 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
2464 ovutils::eDest indexL = pipe_info.lIndex;
2465 ovutils::eDest indexR = pipe_info.rIndex;
2466 int fd = hnd->fd;
Praveena Pachipulusud9443c72014-02-17 10:42:28 +05302467 uint32_t offset = (uint32_t)hnd->offset;
radhakrishnac9a67412013-09-25 17:40:42 +05302468 if(rot) {
2469 rot->queueBuffer(fd, offset);
2470 fd = rot->getDstMemId();
2471 offset = rot->getDstOffset();
2472 }
2473 if(indexL != ovutils::OV_INVALID) {
2474 ovutils::eDest destL = (ovutils::eDest)indexL;
2475 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2476 using pipe: %d", __FUNCTION__, layer, hnd, indexL );
2477 if (!ov.queueBuffer(fd, offset, destL)) {
2478 ALOGE("%s: queueBuffer failed for display:%d",
2479 __FUNCTION__, mDpy);
2480 return false;
2481 }
2482 }
2483
2484 if(indexR != ovutils::OV_INVALID) {
2485 ovutils::eDest destR = (ovutils::eDest)indexR;
2486 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2487 using pipe: %d", __FUNCTION__, layer, hnd, indexR );
2488 if (!ov.queueBuffer(fd, offset, destR)) {
2489 ALOGE("%s: queueBuffer failed for display:%d",
2490 __FUNCTION__, mDpy);
2491 return false;
2492 }
2493 }
2494 }
2495 else{
2496 MdpPipeInfoNonSplit& pipe_info =
Saurabh Shah88e4d272013-09-03 13:31:29 -07002497 *(MdpPipeInfoNonSplit*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
radhakrishnac9a67412013-09-25 17:40:42 +05302498 ovutils::eDest dest = pipe_info.index;
2499 if(dest == ovutils::OV_INVALID) {
2500 ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, dest);
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002501 return false;
radhakrishnac9a67412013-09-25 17:40:42 +05302502 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002503
radhakrishnac9a67412013-09-25 17:40:42 +05302504 if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
2505 continue;
2506 }
2507
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002508 int fd = hnd->fd;
2509 uint32_t offset = (uint32_t)hnd->offset;
2510 int index = ctx->mPtorInfo.getPTORArrayIndex(i);
2511 if (!mDpy && (index != -1)) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07002512 hnd = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002513 fd = hnd->fd;
Sushil Chauhan875a92e2014-07-25 12:20:23 -07002514 offset = 0;
Sushil Chauhandefd3522014-05-13 18:17:12 -07002515 }
2516
radhakrishnac9a67412013-09-25 17:40:42 +05302517 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2518 using pipe: %d", __FUNCTION__, layer,
2519 hnd, dest );
2520
radhakrishnac9a67412013-09-25 17:40:42 +05302521 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
2522 if(rot) {
2523 if(!rot->queueBuffer(fd, offset))
2524 return false;
2525 fd = rot->getDstMemId();
2526 offset = rot->getDstOffset();
2527 }
2528
2529 if (!ov.queueBuffer(fd, offset, dest)) {
2530 ALOGE("%s: queueBuffer failed for display:%d ",
2531 __FUNCTION__, mDpy);
2532 return false;
2533 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002534 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002535
2536 layerProp[i].mFlags &= ~HWC_MDPCOMP;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002537 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002538 return true;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002539}
2540
Saurabh Shah88e4d272013-09-03 13:31:29 -07002541//=============MDPCompSplit===================================================
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002542
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002543void MDPCompSplit::adjustForSourceSplit(hwc_context_t *ctx,
radhakrishnac9a67412013-09-25 17:40:42 +05302544 hwc_display_contents_1_t* list){
2545 //if 4kx2k yuv layer is totally present in either in left half
2546 //or right half then try splitting the yuv layer to avoid decimation
radhakrishnac9a67412013-09-25 17:40:42 +05302547 const int lSplit = getLeftSplit(ctx, mDpy);
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302548 if(mCurrentFrame.fbZ >= 0) {
2549 for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
2550 index++) {
2551 if(!mCurrentFrame.isFBComposed[index]) {
2552 if(mdpNextZOrder == mCurrentFrame.fbZ) {
2553 mdpNextZOrder++;
2554 }
2555 mdpNextZOrder++;
2556 hwc_layer_1_t* layer = &list->hwLayers[index];
2557 private_handle_t *hnd = (private_handle_t *)layer->handle;
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002558 if(isYUVSplitNeeded(hnd) ||
2559 (needs3DComposition(ctx,mDpy) &&
2560 get3DFormat(hnd) != HAL_NO_3D)) {
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302561 hwc_rect_t dst = layer->displayFrame;
2562 if((dst.left > lSplit) || (dst.right < lSplit)) {
2563 mCurrentFrame.mdpCount += 1;
2564 }
2565 if(mdpNextZOrder <= mCurrentFrame.fbZ)
2566 mCurrentFrame.fbZ += 1;
2567 mdpNextZOrder++;
2568 }
2569 }
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002570 }
radhakrishnac9a67412013-09-25 17:40:42 +05302571 }
2572}
2573
Saurabh Shah88e4d272013-09-03 13:31:29 -07002574bool MDPCompSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
Saurabh Shahc62f3982014-03-05 14:28:26 -08002575 MdpPipeInfoSplit& pipe_info) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002576
Saurabh Shahc62f3982014-03-05 14:28:26 -08002577 const int lSplit = getLeftSplit(ctx, mDpy);
2578 private_handle_t *hnd = (private_handle_t *)layer->handle;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002579 hwc_rect_t dst = layer->displayFrame;
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002580 pipe_info.lIndex = ovutils::OV_INVALID;
2581 pipe_info.rIndex = ovutils::OV_INVALID;
2582
Saurabh Shahc62f3982014-03-05 14:28:26 -08002583 Overlay::PipeSpecs pipeSpecs;
2584 pipeSpecs.formatClass = isYuvBuffer(hnd) ?
2585 Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
2586 pipeSpecs.needsScaling = qhwc::needsScalingWithSplit(ctx, layer, mDpy);
2587 pipeSpecs.dpy = mDpy;
2588 pipeSpecs.mixer = Overlay::MIXER_LEFT;
2589 pipeSpecs.fb = false;
2590
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08002591 // Acquire pipe only for the updating half
2592 hwc_rect_t l_roi = ctx->listStats[mDpy].lRoi;
2593 hwc_rect_t r_roi = ctx->listStats[mDpy].rRoi;
2594
2595 if (dst.left < lSplit && isValidRect(getIntersection(dst, l_roi))) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002596 pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002597 if(pipe_info.lIndex == ovutils::OV_INVALID)
2598 return false;
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002599 }
2600
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08002601 if(dst.right > lSplit && isValidRect(getIntersection(dst, r_roi))) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002602 pipeSpecs.mixer = Overlay::MIXER_RIGHT;
2603 pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002604 if(pipe_info.rIndex == ovutils::OV_INVALID)
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002605 return false;
2606 }
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002607
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002608 return true;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002609}
2610
Saurabh Shah88e4d272013-09-03 13:31:29 -07002611bool MDPCompSplit::allocLayerPipes(hwc_context_t *ctx,
Saurabh Shahe51f8ca2013-05-06 17:26:16 -07002612 hwc_display_contents_1_t* list) {
Saurabh Shah8cc77712015-03-31 10:48:51 -07002613 for(uint32_t formatType = FORMAT_YUV; formatType < FORMAT_MAX;
2614 formatType++) {
2615 for(int index = 0 ; index < mCurrentFrame.layerCount; index++) {
2616 if(mCurrentFrame.isFBComposed[index]) continue;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002617
Saurabh Shah8cc77712015-03-31 10:48:51 -07002618 hwc_layer_1_t* layer = &list->hwLayers[index];
2619 private_handle_t *hnd = (private_handle_t *)layer->handle;
2620 if(formatType == FORMAT_YUV && !isYuvBuffer(hnd))
2621 continue;
2622 if(formatType == FORMAT_RGB && isYuvBuffer(hnd))
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002623 continue;
2624
Saurabh Shah8cc77712015-03-31 10:48:51 -07002625 hwc_rect_t dst = layer->displayFrame;
2626 const int lSplit = getLeftSplit(ctx, mDpy);
2627 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
2628 if((dst.left > lSplit)||(dst.right < lSplit)){
2629 if(allocSplitVGPipes(ctx, index)){
2630 continue;
2631 }
2632 }
2633 }
2634 //XXX: Check for forced 2D composition
2635 if(needs3DComposition(ctx, mDpy) && get3DFormat(hnd) != HAL_NO_3D)
2636 if(allocSplitVGPipes(ctx,index))
2637 continue;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002638
Saurabh Shah8cc77712015-03-31 10:48:51 -07002639 int mdpIndex = mCurrentFrame.layerToMDP[index];
2640 PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
2641 info.pipeInfo = new MdpPipeInfoSplit;
2642 info.rot = NULL;
2643 MdpPipeInfoSplit& pipe_info = *(MdpPipeInfoSplit*)info.pipeInfo;
2644
2645 if(!acquireMDPPipes(ctx, layer, pipe_info)) {
2646 ALOGD_IF(isDebug(), "%s: Unable to get pipe for layer %d of "\
2647 "format type %d", __FUNCTION__, index, formatType);
2648 return false;
2649 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002650 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002651 }
2652 return true;
2653}
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002654
radhakrishnac9a67412013-09-25 17:40:42 +05302655int MDPCompSplit::configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
2656 PipeLayerPair& PipeLayerPair) {
2657 const int lSplit = getLeftSplit(ctx, mDpy);
2658 hwc_rect_t dst = layer->displayFrame;
2659 if((dst.left > lSplit)||(dst.right < lSplit)){
2660 MdpYUVPipeInfo& mdp_info =
2661 *(static_cast<MdpYUVPipeInfo*>(PipeLayerPair.pipeInfo));
2662 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Justin Philipd6166602014-08-12 13:42:21 +05302663 eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
radhakrishnac9a67412013-09-25 17:40:42 +05302664 eDest lDest = mdp_info.lIndex;
2665 eDest rDest = mdp_info.rIndex;
2666
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002667 return configureSourceSplit(ctx, layer, mDpy, mdpFlagsL, zOrder,
radhakrishnac9a67412013-09-25 17:40:42 +05302668 lDest, rDest, &PipeLayerPair.rot);
2669 }
2670 else{
2671 return configure(ctx, layer, PipeLayerPair);
2672 }
2673}
2674
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002675/*
2676 * Configures pipe(s) for MDP composition
2677 */
Saurabh Shah88e4d272013-09-03 13:31:29 -07002678int MDPCompSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
Saurabh Shah67a38c32013-06-10 16:23:15 -07002679 PipeLayerPair& PipeLayerPair) {
Saurabh Shah88e4d272013-09-03 13:31:29 -07002680 MdpPipeInfoSplit& mdp_info =
2681 *(static_cast<MdpPipeInfoSplit*>(PipeLayerPair.pipeInfo));
Saurabh Shahacf10202013-02-26 10:15:15 -08002682 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Justin Philipd6166602014-08-12 13:42:21 +05302683 eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shahacf10202013-02-26 10:15:15 -08002684 eDest lDest = mdp_info.lIndex;
2685 eDest rDest = mdp_info.rIndex;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002686
2687 ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
Jeykumar Sankaran39305802014-12-12 17:55:57 -08002688 "dest_pipeR: %d",__FUNCTION__, layer, zOrder, lDest, rDest);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002689
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002690 return configureSplit(ctx, layer, mDpy, mdpFlagsL, zOrder, lDest,
Jeykumar Sankaran39305802014-12-12 17:55:57 -08002691 rDest, &PipeLayerPair.rot);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002692}
2693
Saurabh Shah88e4d272013-09-03 13:31:29 -07002694bool MDPCompSplit::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002695
Raj Kamal4393eaa2014-06-06 13:45:20 +05302696 if(!isEnabled() or !mModeOn) {
2697 ALOGD_IF(isDebug(),"%s: MDP Comp not enabled/configured", __FUNCTION__);
Prabhanjan Kandula08222fc2013-07-10 17:20:59 +05302698 return true;
2699 }
2700
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002701 overlay::Overlay& ov = *ctx->mOverlay;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002702 LayerProp *layerProp = ctx->layerProp[mDpy];
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002703
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002704 int numHwLayers = ctx->listStats[mDpy].numAppLayers;
2705 for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ )
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002706 {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002707 if(mCurrentFrame.isFBComposed[i]) continue;
2708
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002709 hwc_layer_1_t *layer = &list->hwLayers[i];
Saurabh Shahacf10202013-02-26 10:15:15 -08002710 private_handle_t *hnd = (private_handle_t *)layer->handle;
2711 if(!hnd) {
2712 ALOGE("%s handle null", __FUNCTION__);
2713 return false;
2714 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002715
2716 if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
2717 continue;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002718 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002719
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002720 int mdpIndex = mCurrentFrame.layerToMDP[i];
2721
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002722 if((isYUVSplitNeeded(hnd) && sEnableYUVsplit) ||
2723 (needs3DComposition(ctx, mDpy) && get3DFormat(hnd) != HAL_NO_3D))
radhakrishnac9a67412013-09-25 17:40:42 +05302724 {
2725 MdpYUVPipeInfo& pipe_info =
2726 *(MdpYUVPipeInfo*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
2727 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
2728 ovutils::eDest indexL = pipe_info.lIndex;
2729 ovutils::eDest indexR = pipe_info.rIndex;
2730 int fd = hnd->fd;
Praveena Pachipulusud9443c72014-02-17 10:42:28 +05302731 uint32_t offset = (uint32_t)hnd->offset;
radhakrishnac9a67412013-09-25 17:40:42 +05302732 if(rot) {
2733 rot->queueBuffer(fd, offset);
2734 fd = rot->getDstMemId();
2735 offset = rot->getDstOffset();
2736 }
2737 if(indexL != ovutils::OV_INVALID) {
2738 ovutils::eDest destL = (ovutils::eDest)indexL;
2739 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2740 using pipe: %d", __FUNCTION__, layer, hnd, indexL );
2741 if (!ov.queueBuffer(fd, offset, destL)) {
2742 ALOGE("%s: queueBuffer failed for display:%d",
2743 __FUNCTION__, mDpy);
2744 return false;
2745 }
2746 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002747
radhakrishnac9a67412013-09-25 17:40:42 +05302748 if(indexR != ovutils::OV_INVALID) {
2749 ovutils::eDest destR = (ovutils::eDest)indexR;
2750 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2751 using pipe: %d", __FUNCTION__, layer, hnd, indexR );
2752 if (!ov.queueBuffer(fd, offset, destR)) {
2753 ALOGE("%s: queueBuffer failed for display:%d",
2754 __FUNCTION__, mDpy);
2755 return false;
2756 }
Saurabh Shaha9da08f2013-07-03 13:27:53 -07002757 }
2758 }
radhakrishnac9a67412013-09-25 17:40:42 +05302759 else{
2760 MdpPipeInfoSplit& pipe_info =
2761 *(MdpPipeInfoSplit*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
2762 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
Saurabh Shaha9da08f2013-07-03 13:27:53 -07002763
radhakrishnac9a67412013-09-25 17:40:42 +05302764 ovutils::eDest indexL = pipe_info.lIndex;
2765 ovutils::eDest indexR = pipe_info.rIndex;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002766
radhakrishnac9a67412013-09-25 17:40:42 +05302767 int fd = hnd->fd;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002768 uint32_t offset = (uint32_t)hnd->offset;
2769 int index = ctx->mPtorInfo.getPTORArrayIndex(i);
2770 if (!mDpy && (index != -1)) {
2771 hnd = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
2772 fd = hnd->fd;
Sushil Chauhan875a92e2014-07-25 12:20:23 -07002773 offset = 0;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002774 }
radhakrishnac9a67412013-09-25 17:40:42 +05302775
Tatenda Chipeperekwa88fe6352014-04-14 10:36:06 -07002776 if(ctx->mAD->draw(ctx, fd, offset)) {
2777 fd = ctx->mAD->getDstFd();
2778 offset = ctx->mAD->getDstOffset();
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002779 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002780
radhakrishnac9a67412013-09-25 17:40:42 +05302781 if(rot) {
2782 rot->queueBuffer(fd, offset);
2783 fd = rot->getDstMemId();
2784 offset = rot->getDstOffset();
2785 }
2786
2787 //************* play left mixer **********
2788 if(indexL != ovutils::OV_INVALID) {
2789 ovutils::eDest destL = (ovutils::eDest)indexL;
2790 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2791 using pipe: %d", __FUNCTION__, layer, hnd, indexL );
2792 if (!ov.queueBuffer(fd, offset, destL)) {
2793 ALOGE("%s: queueBuffer failed for left mixer",
2794 __FUNCTION__);
2795 return false;
2796 }
2797 }
2798
2799 //************* play right mixer **********
2800 if(indexR != ovutils::OV_INVALID) {
2801 ovutils::eDest destR = (ovutils::eDest)indexR;
2802 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2803 using pipe: %d", __FUNCTION__, layer, hnd, indexR );
2804 if (!ov.queueBuffer(fd, offset, destR)) {
2805 ALOGE("%s: queueBuffer failed for right mixer",
2806 __FUNCTION__);
2807 return false;
2808 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002809 }
2810 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002811
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002812 layerProp[i].mFlags &= ~HWC_MDPCOMP;
2813 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002814
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002815 return true;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002816}
Saurabh Shahab47c692014-02-12 18:45:57 -08002817
2818//================MDPCompSrcSplit==============================================
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08002819
2820bool MDPCompSrcSplit::validateAndApplyROI(hwc_context_t *ctx,
2821 hwc_display_contents_1_t* list) {
2822 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
2823 hwc_rect_t visibleRect = ctx->listStats[mDpy].lRoi;
2824
2825 for(int i = numAppLayers - 1; i >= 0; i--) {
2826 if(!isValidRect(visibleRect)) {
2827 mCurrentFrame.drop[i] = true;
2828 mCurrentFrame.dropCount++;
2829 continue;
2830 }
2831
2832 const hwc_layer_1_t* layer = &list->hwLayers[i];
2833 hwc_rect_t dstRect = layer->displayFrame;
2834 hwc_rect_t res = getIntersection(visibleRect, dstRect);
2835
2836 if(!isValidRect(res)) {
2837 mCurrentFrame.drop[i] = true;
2838 mCurrentFrame.dropCount++;
2839 } else {
2840 /* Reset frame ROI when any layer which needs scaling also needs ROI
2841 * cropping */
2842 if(!isSameRect(res, dstRect) && needsScaling (layer)) {
2843 ALOGI("%s: Resetting ROI due to scaling", __FUNCTION__);
2844 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
2845 mCurrentFrame.dropCount = 0;
2846 return false;
2847 }
2848
2849 /* deduct any opaque region from visibleRect */
2850 if (layer->blending == HWC_BLENDING_NONE &&
2851 layer->planeAlpha == 0xFF)
2852 visibleRect = deductRect(visibleRect, res);
2853 }
2854 }
2855 return true;
2856}
2857
2858/*
2859 * HW Limitation: ping pong split can always split the ping pong output
2860 * equally across two DSI's. So the ROI programmed should be of equal width
2861 * for both the halves
2862 */
2863void MDPCompSrcSplit::generateROI(hwc_context_t *ctx,
2864 hwc_display_contents_1_t* list) {
2865 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
2866
2867
2868 if(!canPartialUpdate(ctx, list))
2869 return;
2870
2871 struct hwc_rect roi = (struct hwc_rect){0, 0, 0, 0};
2872 hwc_rect fullFrame = (struct hwc_rect) {0, 0,(int)ctx->dpyAttr[mDpy].xres,
2873 (int)ctx->dpyAttr[mDpy].yres};
2874
2875 for(int index = 0; index < numAppLayers; index++ ) {
2876 hwc_layer_1_t* layer = &list->hwLayers[index];
2877
2878 // If we have a RGB layer which needs rotation, no partial update
2879 if(!isYuvBuffer((private_handle_t *)layer->handle) && layer->transform)
2880 return;
2881
2882 if ((mCachedFrame.hnd[index] != layer->handle) ||
2883 isYuvBuffer((private_handle_t *)layer->handle)) {
2884 hwc_rect_t dst = layer->displayFrame;
2885 hwc_rect_t updatingRect = dst;
2886
2887#ifdef QCOM_BSP
2888 if(!needsScaling(layer) && !layer->transform)
2889 {
2890 hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
2891 int x_off = dst.left - src.left;
2892 int y_off = dst.top - src.top;
2893 updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
2894 }
2895#endif
2896
2897 roi = getUnion(roi, updatingRect);
2898 }
2899 }
2900
2901 /* No layer is updating. Still SF wants a refresh.*/
2902 if(!isValidRect(roi))
2903 return;
2904
2905 roi = expandROIFromMidPoint(roi, fullFrame);
2906
2907 hwc_rect lFrame = fullFrame;
2908 lFrame.right /= 2;
2909 hwc_rect lRoi = getIntersection(roi, lFrame);
2910
2911 // Align ROI coordinates to panel restrictions
2912 lRoi = getSanitizeROI(lRoi, lFrame);
2913
2914 hwc_rect rFrame = fullFrame;
2915 rFrame.left = lFrame.right;
2916 hwc_rect rRoi = getIntersection(roi, rFrame);
2917
2918 // Align ROI coordinates to panel restrictions
2919 rRoi = getSanitizeROI(rRoi, rFrame);
2920
2921 roi = getUnion(lRoi, rRoi);
2922
2923 ctx->listStats[mDpy].lRoi = roi;
2924 if(!validateAndApplyROI(ctx, list))
2925 resetROI(ctx, mDpy);
2926
2927 ALOGD_IF(isDebug(),"%s: generated ROI: [%d, %d, %d, %d] [%d, %d, %d, %d]",
2928 __FUNCTION__,
2929 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
2930 ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom,
2931 ctx->listStats[mDpy].rRoi.left, ctx->listStats[mDpy].rRoi.top,
2932 ctx->listStats[mDpy].rRoi.right, ctx->listStats[mDpy].rRoi.bottom);
2933}
2934
Saurabh Shahab47c692014-02-12 18:45:57 -08002935bool MDPCompSrcSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
Saurabh Shahc62f3982014-03-05 14:28:26 -08002936 MdpPipeInfoSplit& pipe_info) {
Saurabh Shahab47c692014-02-12 18:45:57 -08002937 private_handle_t *hnd = (private_handle_t *)layer->handle;
2938 hwc_rect_t dst = layer->displayFrame;
2939 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
2940 pipe_info.lIndex = ovutils::OV_INVALID;
2941 pipe_info.rIndex = ovutils::OV_INVALID;
2942
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08002943 if(qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() && !mDpy)
2944 trimAgainstROI(ctx,crop, dst);
2945
Saurabh Shahab47c692014-02-12 18:45:57 -08002946 //If 2 pipes are staged on a single stage of a mixer, then the left pipe
2947 //should have a higher priority than the right one. Pipe priorities are
2948 //starting with VG0, VG1 ... , RGB0 ..., DMA1
Saurabh Shahab47c692014-02-12 18:45:57 -08002949
Saurabh Shahc62f3982014-03-05 14:28:26 -08002950 Overlay::PipeSpecs pipeSpecs;
2951 pipeSpecs.formatClass = isYuvBuffer(hnd) ?
2952 Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
2953 pipeSpecs.needsScaling = qhwc::needsScaling(layer);
2954 pipeSpecs.dpy = mDpy;
2955 pipeSpecs.fb = false;
2956
Saurabh Shahab47c692014-02-12 18:45:57 -08002957 //1 pipe by default for a layer
Saurabh Shahc62f3982014-03-05 14:28:26 -08002958 pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahab47c692014-02-12 18:45:57 -08002959 if(pipe_info.lIndex == ovutils::OV_INVALID) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002960 return false;
Saurabh Shahab47c692014-02-12 18:45:57 -08002961 }
2962
Saurabh Shahea7a01d2014-05-22 17:45:36 -07002963 /* Use 2 pipes IF
2964 a) Layer's crop width is > 2048 or
2965 b) Layer's dest width > 2048 or
2966 c) On primary, driver has indicated with caps to split always. This is
2967 based on an empirically derived value of panel height. Applied only
2968 if the layer's width is > mixer's width
2969 */
2970
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +05302971 MDPVersion& mdpHw = MDPVersion::getInstance();
Saurabh Shahea7a01d2014-05-22 17:45:36 -07002972 bool primarySplitAlways = (mDpy == HWC_DISPLAY_PRIMARY) and
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +05302973 mdpHw.isSrcSplitAlways();
Saurabh Shah514759d2014-11-11 18:02:24 -08002974 const uint32_t lSplit = getLeftSplit(ctx, mDpy);
2975 const uint32_t dstWidth = dst.right - dst.left;
2976 const uint32_t dstHeight = dst.bottom - dst.top;
Saurabh Shah05f4e222015-02-05 14:36:22 -08002977 uint32_t cropWidth = has90Transform(layer) ? crop.bottom - crop.top :
Saurabh Shah189f23d2014-09-26 17:21:00 -07002978 crop.right - crop.left;
Saurabh Shah05f4e222015-02-05 14:36:22 -08002979 uint32_t cropHeight = has90Transform(layer) ? crop.right - crop.left :
Saurabh Shah514759d2014-11-11 18:02:24 -08002980 crop.bottom - crop.top;
2981 //Approximation to actual clock, ignoring the common factors in pipe and
2982 //mixer cases like line_time
2983 const uint32_t layerClock = getLayerClock(dstWidth, dstHeight, cropHeight);
2984 const uint32_t mixerClock = lSplit;
Saurabh Shahea7a01d2014-05-22 17:45:36 -07002985
Saurabh Shah05f4e222015-02-05 14:36:22 -08002986 const uint32_t downscale = getRotDownscale(ctx, layer);
2987 if(downscale) {
2988 cropWidth /= downscale;
2989 cropHeight /= downscale;
2990 }
2991
Jeykumar Sankaran39305802014-12-12 17:55:57 -08002992 if(dstWidth > mdpHw.getMaxPipeWidth() or
2993 cropWidth > mdpHw.getMaxPipeWidth() or
Saurabh Shah514759d2014-11-11 18:02:24 -08002994 (primarySplitAlways and
2995 (cropWidth > lSplit or layerClock > mixerClock))) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002996 pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahab47c692014-02-12 18:45:57 -08002997 if(pipe_info.rIndex == ovutils::OV_INVALID) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002998 return false;
Saurabh Shahdd8237a2014-02-28 14:29:09 -08002999 }
3000
Jeykumar Sankaran89e23ab2015-01-28 15:57:46 -08003001 if(ctx->mOverlay->needsPrioritySwap(pipe_info.lIndex,
3002 pipe_info.rIndex)) {
Saurabh Shahdd8237a2014-02-28 14:29:09 -08003003 qhwc::swap(pipe_info.lIndex, pipe_info.rIndex);
Saurabh Shahab47c692014-02-12 18:45:57 -08003004 }
3005 }
3006
3007 return true;
3008}
3009
Saurabh Shahab47c692014-02-12 18:45:57 -08003010int MDPCompSrcSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
3011 PipeLayerPair& PipeLayerPair) {
3012 private_handle_t *hnd = (private_handle_t *)layer->handle;
3013 if(!hnd) {
3014 ALOGE("%s: layer handle is NULL", __FUNCTION__);
3015 return -1;
3016 }
3017 MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
3018 MdpPipeInfoSplit& mdp_info =
3019 *(static_cast<MdpPipeInfoSplit*>(PipeLayerPair.pipeInfo));
3020 Rotator **rot = &PipeLayerPair.rot;
3021 eZorder z = static_cast<eZorder>(mdp_info.zOrder);
Saurabh Shahab47c692014-02-12 18:45:57 -08003022 eDest lDest = mdp_info.lIndex;
3023 eDest rDest = mdp_info.rIndex;
3024 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
3025 hwc_rect_t dst = layer->displayFrame;
3026 int transform = layer->transform;
3027 eTransform orient = static_cast<eTransform>(transform);
Saurabh Shahab47c692014-02-12 18:45:57 -08003028 int rotFlags = ROT_FLAGS_NONE;
Sushil Chauhan65e26302015-01-14 10:48:57 -08003029 uint32_t format = ovutils::getMdpFormat(hnd->format, hnd->flags);
Saurabh Shahab47c692014-02-12 18:45:57 -08003030 Whf whf(getWidth(hnd), getHeight(hnd), format, hnd->size);
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05003031 eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shahab47c692014-02-12 18:45:57 -08003032
3033 ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
3034 "dest_pipeR: %d",__FUNCTION__, layer, z, lDest, rDest);
3035
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08003036 if(qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() && !mDpy) {
3037 /* MDP driver crops layer coordinates against ROI in Non-Split
3038 * and Split MDP comp. But HWC needs to crop them for source split.
3039 * Reason: 1) Source split is efficient only when the final effective
3040 * load is distributed evenly across mixers.
3041 * 2) We have to know the effective width of the layer that
3042 * the ROI needs to find the no. of pipes the layer needs.
3043 */
3044 trimAgainstROI(ctx, crop, dst);
3045 }
3046
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05003047 if(needs3DComposition(ctx, mDpy) &&
3048 get3DFormat(hnd) != HAL_NO_3D){
3049 return configure3DVideo(ctx, layer, mDpy, mdpFlags, z, lDest,
3050 rDest, &PipeLayerPair.rot);
3051 }
3052
Saurabh Shahab47c692014-02-12 18:45:57 -08003053 // Handle R/B swap
3054 if (layer->flags & HWC_FORMAT_RB_SWAP) {
3055 if (hnd->format == HAL_PIXEL_FORMAT_RGBA_8888)
3056 whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRA_8888);
3057 else if (hnd->format == HAL_PIXEL_FORMAT_RGBX_8888)
3058 whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
3059 }
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07003060 // update source crop and destination position of AIV video layer.
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07003061 if(ctx->listStats[mDpy].mAIVVideoMode && isYuvBuffer(hnd)) {
3062 updateCoordinates(ctx, crop, dst, mDpy);
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07003063 }
Ramkumar Radhakrishnana5c72872014-08-28 19:04:18 -07003064 /* Calculate the external display position based on MDP downscale,
3065 ActionSafe, and extorientation features. */
3066 calcExtDisplayPosition(ctx, hnd, mDpy, crop, dst, transform, orient);
Saurabh Shahab47c692014-02-12 18:45:57 -08003067
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003068 int downscale = getRotDownscale(ctx, layer);
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003069 setMdpFlags(ctx, layer, mdpFlags, downscale, transform);
Saurabh Shahab47c692014-02-12 18:45:57 -08003070
3071 if(lDest != OV_INVALID && rDest != OV_INVALID) {
3072 //Enable overfetch
Saurabh Shah97e2d802014-04-14 18:03:54 -07003073 setMdpFlags(mdpFlags, OV_MDSS_MDP_DUAL_PIPE);
Saurabh Shahab47c692014-02-12 18:45:57 -08003074 }
3075
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003076 if((has90Transform(layer) or downscale) and isRotationDoable(ctx, hnd)) {
Saurabh Shahab47c692014-02-12 18:45:57 -08003077 (*rot) = ctx->mRotMgr->getNext();
3078 if((*rot) == NULL) return -1;
Saurabh Shah39240c92014-03-31 10:31:42 -07003079 ctx->mLayerRotMap[mDpy]->add(layer, *rot);
Saurabh Shah1bd5b6f2014-05-19 12:23:13 -07003080 //If the video is using a single pipe, enable BWC
3081 if(rDest == OV_INVALID) {
Saurabh Shahcd018352014-11-11 13:54:19 -08003082 BwcPM::setBwc(ctx, mDpy, hnd, crop, dst, transform, downscale,
3083 mdpFlags);
Saurabh Shah1bd5b6f2014-05-19 12:23:13 -07003084 }
Saurabh Shahab47c692014-02-12 18:45:57 -08003085 //Configure rotator for pre-rotation
Saurabh Shah97e2d802014-04-14 18:03:54 -07003086 if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale) < 0) {
Saurabh Shahab47c692014-02-12 18:45:57 -08003087 ALOGE("%s: configRotator failed!", __FUNCTION__);
3088 return -1;
3089 }
Saurabh Shah8ec9b5e2014-06-30 14:37:17 -07003090 updateSource(orient, whf, crop, *rot);
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003091 rotFlags |= ovutils::ROT_PREROTATED;
Saurabh Shahab47c692014-02-12 18:45:57 -08003092 }
3093
3094 //If 2 pipes being used, divide layer into half, crop and dst
3095 hwc_rect_t cropL = crop;
3096 hwc_rect_t cropR = crop;
3097 hwc_rect_t dstL = dst;
3098 hwc_rect_t dstR = dst;
3099 if(lDest != OV_INVALID && rDest != OV_INVALID) {
3100 cropL.right = (crop.right + crop.left) / 2;
3101 cropR.left = cropL.right;
3102 sanitizeSourceCrop(cropL, cropR, hnd);
3103
Saurabh Shahb729b192014-08-15 18:04:24 -07003104 bool cropSwap = false;
Saurabh Shahab47c692014-02-12 18:45:57 -08003105 //Swap crops on H flip since 2 pipes are being used
3106 if((orient & OVERLAY_TRANSFORM_FLIP_H) && (*rot) == NULL) {
3107 hwc_rect_t tmp = cropL;
3108 cropL = cropR;
3109 cropR = tmp;
Saurabh Shahb729b192014-08-15 18:04:24 -07003110 cropSwap = true;
Saurabh Shahab47c692014-02-12 18:45:57 -08003111 }
3112
Saurabh Shahb729b192014-08-15 18:04:24 -07003113 //cropSwap trick: If the src and dst widths are both odd, let us say
3114 //2507, then splitting both into half would cause left width to be 1253
3115 //and right 1254. If crop is swapped because of H flip, this will cause
3116 //left crop width to be 1254, whereas left dst width remains 1253, thus
3117 //inducing a scaling that is unaccounted for. To overcome that we add 1
3118 //to the dst width if there is a cropSwap. So if the original width was
3119 //2507, the left dst width will be 1254. Even if the original width was
3120 //even for ex: 2508, the left dst width will still remain 1254.
3121 dstL.right = (dst.right + dst.left + cropSwap) / 2;
Saurabh Shahab47c692014-02-12 18:45:57 -08003122 dstR.left = dstL.right;
3123 }
3124
3125 //For the mdp, since either we are pre-rotating or MDP does flips
3126 orient = OVERLAY_TRANSFORM_0;
3127 transform = 0;
3128
3129 //configure left pipe
3130 if(lDest != OV_INVALID) {
Saurabh Shah2c8ad052014-08-15 13:27:46 -07003131 PipeArgs pargL(mdpFlags, whf, z,
Saurabh Shahab47c692014-02-12 18:45:57 -08003132 static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
3133 (ovutils::eBlending) getBlending(layer->blending));
3134
3135 if(configMdp(ctx->mOverlay, pargL, orient,
3136 cropL, dstL, metadata, lDest) < 0) {
3137 ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
3138 return -1;
3139 }
3140 }
3141
3142 //configure right pipe
3143 if(rDest != OV_INVALID) {
Saurabh Shah2c8ad052014-08-15 13:27:46 -07003144 PipeArgs pargR(mdpFlags, whf, z,
Saurabh Shahab47c692014-02-12 18:45:57 -08003145 static_cast<eRotFlags>(rotFlags),
3146 layer->planeAlpha,
3147 (ovutils::eBlending) getBlending(layer->blending));
3148 if(configMdp(ctx->mOverlay, pargR, orient,
3149 cropR, dstR, metadata, rDest) < 0) {
3150 ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
3151 return -1;
3152 }
3153 }
3154
3155 return 0;
3156}
3157
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -08003158bool MDPComp::getPartialUpdatePref(hwc_context_t *ctx) {
3159 Locker::Autolock _l(ctx->mDrawLock);
3160 const int fbNum = Overlay::getFbForDpy(Overlay::DPY_PRIMARY);
3161 char path[MAX_SYSFS_FILE_PATH];
3162 snprintf (path, sizeof(path), "sys/class/graphics/fb%d/dyn_pu", fbNum);
3163 int fd = open(path, O_RDONLY);
3164 if(fd < 0) {
3165 ALOGE("%s: Failed to open sysfd node: %s", __FUNCTION__, path);
3166 return -1;
3167 }
3168 char value[4];
3169 ssize_t size_read = read(fd, value, sizeof(value)-1);
3170 if(size_read <= 0) {
3171 ALOGE("%s: Failed to read sysfd node: %s", __FUNCTION__, path);
3172 close(fd);
3173 return -1;
3174 }
3175 close(fd);
3176 value[size_read] = '\0';
3177 return atoi(value);
3178}
3179
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003180int MDPComp::setPartialUpdatePref(hwc_context_t *ctx, bool enable) {
3181 Locker::Autolock _l(ctx->mDrawLock);
3182 const int fbNum = Overlay::getFbForDpy(Overlay::DPY_PRIMARY);
3183 char path[MAX_SYSFS_FILE_PATH];
3184 snprintf (path, sizeof(path), "sys/class/graphics/fb%d/dyn_pu", fbNum);
3185 int fd = open(path, O_WRONLY);
3186 if(fd < 0) {
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -08003187 ALOGE("%s: Failed to open sysfd node: %s", __FUNCTION__, path);
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003188 return -1;
3189 }
3190 char value[4];
3191 snprintf(value, sizeof(value), "%d", (int)enable);
3192 ssize_t ret = write(fd, value, strlen(value));
3193 if(ret <= 0) {
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -08003194 ALOGE("%s: Failed to write to sysfd nodes: %s", __FUNCTION__, path);
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003195 close(fd);
3196 return -1;
3197 }
3198 close(fd);
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003199 return 0;
3200}
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08003201
3202bool MDPComp::loadPerfLib() {
3203 char perfLibPath[PROPERTY_VALUE_MAX] = {0};
3204 bool success = false;
3205 if((property_get("ro.vendor.extension_library", perfLibPath, NULL) <= 0)) {
3206 ALOGE("vendor library not set in ro.vendor.extension_library");
3207 return false;
3208 }
3209
3210 sLibPerfHint = dlopen(perfLibPath, RTLD_NOW);
3211 if(sLibPerfHint) {
3212 *(void **)&sPerfLockAcquire = dlsym(sLibPerfHint, "perf_lock_acq");
3213 *(void **)&sPerfLockRelease = dlsym(sLibPerfHint, "perf_lock_rel");
3214 if (!sPerfLockAcquire || !sPerfLockRelease) {
3215 ALOGE("Failed to load symbols for perfLock");
3216 dlclose(sLibPerfHint);
3217 sLibPerfHint = NULL;
3218 return false;
3219 }
3220 success = true;
3221 ALOGI("Successfully Loaded perf hint API's");
3222 } else {
3223 ALOGE("Failed to open %s : %s", perfLibPath, dlerror());
3224 }
3225 return success;
3226}
3227
3228void MDPComp::setPerfHint(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
3229 if ((sPerfHintWindow < 0) || mDpy || !sLibPerfHint) {
3230 return;
3231 }
3232 static int count = sPerfHintWindow;
3233 static int perflockFlag = 0;
3234
3235 /* Send hint to mpctl when single layer is updated
3236 * for a successful number of windows. Hint release
3237 * happens immediately upon multiple layer update.
3238 */
3239 if (onlyVideosUpdating(ctx, list)) {
3240 if(count) {
3241 count--;
3242 }
3243 } else {
3244 if (perflockFlag) {
3245 perflockFlag = 0;
3246 sPerfLockRelease(sPerfLockHandle);
3247 }
3248 count = sPerfHintWindow;
3249 }
3250 if (count == 0 && !perflockFlag) {
3251 int perfHint = 0x4501; // 45-display layer hint, 01-Enable
3252 sPerfLockHandle = sPerfLockAcquire(0 /*handle*/, 0/*duration*/,
3253 &perfHint, sizeof(perfHint)/sizeof(int));
Arun Kumar K.R8b927022015-02-24 12:34:21 -08003254 if(sPerfLockHandle > 0) {
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08003255 perflockFlag = 1;
3256 }
3257 }
3258}
3259
Naseer Ahmed7c958d42012-07-31 18:57:03 -07003260}; //namespace
3261