blob: ced2e84d9aaced8a21d6406e5c8591c6ee72860b [file] [log] [blame]
Naseer Ahmed7c958d42012-07-31 18:57:03 -07001/*
Tatenda Chipeperekwa95675a72014-12-15 17:06:43 -08002 * Copyright (C) 2012-2015, The Linux Foundation. All rights reserved.
Naseer Ahmed7c958d42012-07-31 18:57:03 -07003 * Not a Contribution, Apache license notifications and license are retained
4 * for attribution purposes only.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
Saurabh Shah4fdde762013-04-30 18:47:33 -070019#include <math.h>
Naseer Ahmed7c958d42012-07-31 18:57:03 -070020#include "hwc_mdpcomp.h"
Arun Kumar K.R299bcda2014-12-18 19:36:40 -080021#include <dlfcn.h>
Tatenda Chipeperekwaaf2c0042014-09-17 12:55:01 -070022#include "hdmi.h"
Ramkumar Radhakrishnan47573e22012-11-07 11:36:41 -080023#include "qdMetaData.h"
Ramkumar Radhakrishnan288f8c72013-01-15 11:37:54 -080024#include "mdp_version.h"
Saurabh Shah2a4eb1b2013-07-22 16:33:23 -070025#include "hwc_fbupdate.h"
Saurabh Shaha9da08f2013-07-03 13:27:53 -070026#include "hwc_ad.h"
Saurabh Shahacf10202013-02-26 10:15:15 -080027#include <overlayRotator.h>
Arun Kumar K.R00b84792015-03-27 11:28:36 -070028#include <overlayCursor.h>
Sushil Chauhandefd3522014-05-13 18:17:12 -070029#include "hwc_copybit.h"
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -070030#include "qd_utils.h"
Saurabh Shahacf10202013-02-26 10:15:15 -080031
Saurabh Shah85234ec2013-04-12 17:09:00 -070032using namespace overlay;
Saurabh Shahbd2d0832013-04-04 14:33:08 -070033using namespace qdutils;
Saurabh Shahacf10202013-02-26 10:15:15 -080034using namespace overlay::utils;
35namespace ovutils = overlay::utils;
Naseer Ahmed7c958d42012-07-31 18:57:03 -070036
Naseer Ahmed7c958d42012-07-31 18:57:03 -070037namespace qhwc {
38
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -080039//==============MDPComp========================================================
40
Saurabh Shah59562ff2014-09-30 16:13:12 -070041IdleInvalidator *MDPComp::sIdleInvalidator = NULL;
Naseer Ahmed7c958d42012-07-31 18:57:03 -070042bool MDPComp::sIdleFallBack = false;
43bool MDPComp::sDebugLogs = false;
Naseer Ahmed54821fe2012-11-28 18:44:38 -050044bool MDPComp::sEnabled = false;
Jeykumar Sankaran24c199d2013-05-24 09:40:36 -070045bool MDPComp::sEnableMixedMode = true;
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -070046int MDPComp::sSimulationFlags = 0;
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -070047int MDPComp::sMaxPipesPerMixer = 0;
Raj Kamal389d6e32014-08-04 14:43:24 +053048bool MDPComp::sEnableYUVsplit = false;
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -070049bool MDPComp::sSrcSplitEnabled = false;
Saurabh Shahacec8e42014-11-25 11:07:04 -080050int MDPComp::sMaxSecLayers = 1;
Dileep Kumar Reddi4070e932014-09-30 09:00:57 +053051bool MDPComp::enablePartialUpdateForMDP3 = false;
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -070052bool MDPComp::sIsPartialUpdateActive = true;
Arun Kumar K.R299bcda2014-12-18 19:36:40 -080053void *MDPComp::sLibPerfHint = NULL;
54int MDPComp::sPerfLockHandle = 0;
55int (*MDPComp::sPerfLockAcquire)(int, int, int*, int) = NULL;
56int (*MDPComp::sPerfLockRelease)(int value) = NULL;
57int MDPComp::sPerfHintWindow = -1;
radhakrishna35e33072015-04-08 17:20:43 +053058float MDPComp::sDownscaleThreshold = 1.0;
Arun Kumar K.R299bcda2014-12-18 19:36:40 -080059
Saurabh Shah8cc77712015-03-31 10:48:51 -070060enum AllocOrder { FORMAT_YUV, FORMAT_RGB, FORMAT_MAX };
61
Saurabh Shah88e4d272013-09-03 13:31:29 -070062MDPComp* MDPComp::getObject(hwc_context_t *ctx, const int& dpy) {
Saurabh Shah60e8bde2014-04-30 14:46:03 -070063 if(qdutils::MDPVersion::getInstance().isSrcSplit()) {
64 sSrcSplitEnabled = true;
65 return new MDPCompSrcSplit(dpy);
66 } else if(isDisplaySplit(ctx, dpy)) {
Saurabh Shah88e4d272013-09-03 13:31:29 -070067 return new MDPCompSplit(dpy);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -080068 }
Saurabh Shah88e4d272013-09-03 13:31:29 -070069 return new MDPCompNonSplit(dpy);
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -080070}
71
Jeykumar Sankaran85977e32013-02-25 17:06:08 -080072MDPComp::MDPComp(int dpy):mDpy(dpy){};
73
Jeykumar Sankaran6850ac62014-05-27 10:07:26 -070074void MDPComp::dump(android::String8& buf, hwc_context_t *ctx)
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -080075{
Jeykumar Sankaran3c6bb042013-08-15 14:01:04 -070076 if(mCurrentFrame.layerCount > MAX_NUM_APP_LAYERS)
77 return;
78
Jeykumar Sankaran85977e32013-02-25 17:06:08 -080079 dumpsys_log(buf,"HWC Map for Dpy: %s \n",
Jeykumar Sankaran27dee262013-08-01 17:09:54 -070080 (mDpy == 0) ? "\"PRIMARY\"" :
81 (mDpy == 1) ? "\"EXTERNAL\"" : "\"VIRTUAL\"");
Saurabh Shahe9bc60f2013-08-29 12:58:06 -070082 dumpsys_log(buf,"CURR_FRAME: layerCount:%2d mdpCount:%2d "
Arun Kumar K.R00b84792015-03-27 11:28:36 -070083 "fbCount:%2d dropCount:%2d\n", mCurrentFrame.layerCount,
84 mCurrentFrame.mdpCount, mCurrentFrame.fbCount, mCurrentFrame.dropCount);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -080085 dumpsys_log(buf,"needsFBRedraw:%3s pipesUsed:%2d MaxPipesPerMixer: %d \n",
86 (mCurrentFrame.needsRedraw? "YES" : "NO"),
87 mCurrentFrame.mdpCount, sMaxPipesPerMixer);
Jeykumar Sankaran6850ac62014-05-27 10:07:26 -070088 if(isDisplaySplit(ctx, mDpy)) {
89 dumpsys_log(buf, "Programmed ROI's: Left: [%d, %d, %d, %d] "
90 "Right: [%d, %d, %d, %d] \n",
91 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
92 ctx->listStats[mDpy].lRoi.right,
93 ctx->listStats[mDpy].lRoi.bottom,
94 ctx->listStats[mDpy].rRoi.left,ctx->listStats[mDpy].rRoi.top,
95 ctx->listStats[mDpy].rRoi.right,
96 ctx->listStats[mDpy].rRoi.bottom);
97 } else {
98 dumpsys_log(buf, "Programmed ROI: [%d, %d, %d, %d] \n",
99 ctx->listStats[mDpy].lRoi.left,ctx->listStats[mDpy].lRoi.top,
100 ctx->listStats[mDpy].lRoi.right,
101 ctx->listStats[mDpy].lRoi.bottom);
102 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800103 dumpsys_log(buf," --------------------------------------------- \n");
104 dumpsys_log(buf," listIdx | cached? | mdpIndex | comptype | Z \n");
105 dumpsys_log(buf," --------------------------------------------- \n");
106 for(int index = 0; index < mCurrentFrame.layerCount; index++ )
107 dumpsys_log(buf," %7d | %7s | %8d | %9s | %2d \n",
108 index,
109 (mCurrentFrame.isFBComposed[index] ? "YES" : "NO"),
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700110 mCurrentFrame.layerToMDP[index],
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800111 (mCurrentFrame.isFBComposed[index] ?
Arun Kumar K.R00b84792015-03-27 11:28:36 -0700112 (mCurrentFrame.drop[index] ?
113 ((mCurrentFrame.hwCursorIndex == index) ? "CURSOR": "DROP"):
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700114 (mCurrentFrame.needsRedraw ? "GLES" : "CACHE")) : "MDP"),
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800115 (mCurrentFrame.isFBComposed[index] ? mCurrentFrame.fbZ :
116 mCurrentFrame.mdpToLayer[mCurrentFrame.layerToMDP[index]].pipeInfo->zOrder));
117 dumpsys_log(buf,"\n");
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800118}
119
120bool MDPComp::init(hwc_context_t *ctx) {
121
122 if(!ctx) {
123 ALOGE("%s: Invalid hwc context!!",__FUNCTION__);
124 return false;
125 }
126
Saurabh Shah59562ff2014-09-30 16:13:12 -0700127 char property[PROPERTY_VALUE_MAX] = {0};
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800128
129 sEnabled = false;
Dileep Kumar Reddid8e601d2014-10-28 18:20:43 +0530130 if((ctx->mMDP.version >= qdutils::MDP_V4_0) &&
131 (property_get("persist.hwc.mdpcomp.enable", property, NULL) > 0) &&
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800132 (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
133 (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800134 sEnabled = true;
135 }
136
Jeykumar Sankaran24c199d2013-05-24 09:40:36 -0700137 sEnableMixedMode = true;
138 if((property_get("debug.mdpcomp.mixedmode.disable", property, NULL) > 0) &&
139 (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
140 (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
141 sEnableMixedMode = false;
142 }
143
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700144 qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
145
Saurabh Shah2fd8a252014-12-05 13:49:53 -0800146 sMaxPipesPerMixer = (int)mdpVersion.getBlendStages();
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700147 if(property_get("persist.hwc.mdpcomp.maxpermixer", property, "-1") > 0) {
Saurabh Shah85234ec2013-04-12 17:09:00 -0700148 int val = atoi(property);
149 if(val >= 0)
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700150 sMaxPipesPerMixer = min(val, sMaxPipesPerMixer);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800151 }
152
Saurabh Shahacec8e42014-11-25 11:07:04 -0800153 /* Maximum layers allowed to use MDP on secondary panels. If property
154 * doesn't exist, default to 1. Using the property it can be set to 0 or
155 * more.
156 */
157 if(property_get("persist.hwc.maxseclayers", property, "1") > 0) {
158 int val = atoi(property);
159 sMaxSecLayers = (val >= 0) ? val : 1;
160 sMaxSecLayers = min(sMaxSecLayers, sMaxPipesPerMixer);
161 }
162
Naseer Ahmedf40f2c82013-08-14 16:42:40 -0400163 if(ctx->mMDP.panel != MIPI_CMD_PANEL) {
Saurabh Shah59562ff2014-09-30 16:13:12 -0700164 sIdleInvalidator = IdleInvalidator::getInstance();
165 if(sIdleInvalidator->init(timeout_handler, ctx) < 0) {
166 delete sIdleInvalidator;
167 sIdleInvalidator = NULL;
Naseer Ahmedf40f2c82013-08-14 16:42:40 -0400168 }
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800169 }
radhakrishnac9a67412013-09-25 17:40:42 +0530170
Saurabh Shah7c727642014-06-02 15:47:14 -0700171 if(!qdutils::MDPVersion::getInstance().isSrcSplit() &&
Saurabh Shahc46cf9d2014-07-02 15:22:34 -0700172 !qdutils::MDPVersion::getInstance().isRotDownscaleEnabled() &&
Saurabh Shah7c727642014-06-02 15:47:14 -0700173 property_get("persist.mdpcomp.4k2kSplit", property, "0") > 0 &&
174 (!strncmp(property, "1", PROPERTY_VALUE_MAX) ||
175 !strncasecmp(property,"true", PROPERTY_VALUE_MAX))) {
Raj Kamal389d6e32014-08-04 14:43:24 +0530176 sEnableYUVsplit = true;
radhakrishnac9a67412013-09-25 17:40:42 +0530177 }
Sushil Chauhandefd3522014-05-13 18:17:12 -0700178
Dileep Kumar Reddic6ef3472014-09-24 19:07:08 +0530179 bool defaultPTOR = false;
180 //Enable PTOR when "persist.hwc.ptor.enable" is not defined for
181 //8x16 and 8x39 targets by default
182 if((property_get("persist.hwc.ptor.enable", property, NULL) <= 0) &&
183 (qdutils::MDPVersion::getInstance().is8x16() ||
184 qdutils::MDPVersion::getInstance().is8x39())) {
185 defaultPTOR = true;
186 }
187
188 if (defaultPTOR || (!strncasecmp(property, "true", PROPERTY_VALUE_MAX)) ||
189 (!strncmp(property, "1", PROPERTY_VALUE_MAX ))) {
Sushil Chauhandefd3522014-05-13 18:17:12 -0700190 ctx->mCopyBit[HWC_DISPLAY_PRIMARY] = new CopyBit(ctx,
191 HWC_DISPLAY_PRIMARY);
192 }
193
Dileep Kumar Reddi4070e932014-09-30 09:00:57 +0530194 if((property_get("persist.mdp3.partialUpdate", property, NULL) <= 0) &&
195 (ctx->mMDP.version == qdutils::MDP_V3_0_5)) {
196 enablePartialUpdateForMDP3 = true;
197 }
198
199 if(!enablePartialUpdateForMDP3 &&
200 (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
201 (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
202 enablePartialUpdateForMDP3 = true;
203 }
204
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -0800205 sIsPartialUpdateActive = getPartialUpdatePref(ctx);
206
Arun Kumar K.R299bcda2014-12-18 19:36:40 -0800207 if(property_get("persist.mdpcomp_perfhint", property, "-1") > 0) {
208 int val = atoi(property);
209 if(val > 0 && loadPerfLib()) {
210 sPerfHintWindow = val;
211 ALOGI("PerfHintWindow = %d", sPerfHintWindow);
212 }
213 }
214
radhakrishna35e33072015-04-08 17:20:43 +0530215 if(property_get("persist.hwc.downscale_threshold", property, "1.0") > 0) {
216 sDownscaleThreshold = (float)atof(property);
217 }
218
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700219 return true;
220}
221
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800222void MDPComp::reset(hwc_context_t *ctx) {
223 const int numLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shah2a4eb1b2013-07-22 16:33:23 -0700224 mCurrentFrame.reset(numLayers);
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800225 ctx->mOverlay->clear(mDpy);
226 ctx->mLayerRotMap[mDpy]->clear();
Saurabh Shah2a4eb1b2013-07-22 16:33:23 -0700227}
228
Raj Kamal4393eaa2014-06-06 13:45:20 +0530229void MDPComp::reset() {
Raj Kamalfdfdddf2015-03-16 21:59:25 +0530230 mPrevModeOn = mModeOn;
Raj Kamal4393eaa2014-06-06 13:45:20 +0530231 mModeOn = false;
232}
233
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700234void MDPComp::timeout_handler(void *udata) {
235 struct hwc_context_t* ctx = (struct hwc_context_t*)(udata);
Raj Kamalfdfdddf2015-03-16 21:59:25 +0530236 bool handleTimeout = false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700237
238 if(!ctx) {
239 ALOGE("%s: received empty data in timer callback", __FUNCTION__);
240 return;
241 }
Raj Kamal58b31a02014-12-16 15:53:53 +0530242
243 ctx->mDrawLock.lock();
Raj Kamalfdfdddf2015-03-16 21:59:25 +0530244
245 /* Handle timeout event only if the previous composition
246 on any display is MDP or MIXED*/
247 for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
248 if(ctx->mMDPComp[i])
249 handleTimeout =
250 ctx->mMDPComp[i]->isMDPComp() || handleTimeout;
251 }
252
253 if(!handleTimeout) {
Ramkumar Radhakrishnan92abb4f2014-02-06 21:31:29 -0800254 ALOGD_IF(isDebug(), "%s:Do not handle this timeout", __FUNCTION__);
Raj Kamal58b31a02014-12-16 15:53:53 +0530255 ctx->mDrawLock.unlock();
Ramkumar Radhakrishnan92abb4f2014-02-06 21:31:29 -0800256 return;
257 }
Jesse Hall3be78d92012-08-21 15:12:23 -0700258 if(!ctx->proc) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700259 ALOGE("%s: HWC proc not registered", __FUNCTION__);
Raj Kamal58b31a02014-12-16 15:53:53 +0530260 ctx->mDrawLock.unlock();
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700261 return;
262 }
263 sIdleFallBack = true;
Raj Kamal58b31a02014-12-16 15:53:53 +0530264 ctx->mDrawLock.unlock();
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700265 /* Trigger SF to redraw the current frame */
Jesse Hall3be78d92012-08-21 15:12:23 -0700266 ctx->proc->invalidate(ctx->proc);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700267}
268
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700269void MDPComp::setMaxPipesPerMixer(const uint32_t value) {
270 qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
Saurabh Shah2fd8a252014-12-05 13:49:53 -0800271 uint32_t maxSupported = (int)mdpVersion.getBlendStages();
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700272 if(value > maxSupported) {
273 ALOGW("%s: Input exceeds max value supported. Setting to"
274 "max value: %d", __FUNCTION__, maxSupported);
275 }
276 sMaxPipesPerMixer = min(value, maxSupported);
277}
278
Saurabh Shah59562ff2014-09-30 16:13:12 -0700279void MDPComp::setIdleTimeout(const uint32_t& timeout) {
280 enum { ONE_REFRESH_PERIOD_MS = 17, ONE_BILLION_MS = 1000000000 };
281
282 if(sIdleInvalidator) {
283 if(timeout <= ONE_REFRESH_PERIOD_MS) {
284 //If the specified timeout is < 1 draw cycle worth, "virtually"
285 //disable idle timeout. The ideal way for clients to disable
286 //timeout is to set it to 0
287 sIdleInvalidator->setIdleTimeout(ONE_BILLION_MS);
288 ALOGI("Disabled idle timeout");
289 return;
290 }
291 sIdleInvalidator->setIdleTimeout(timeout);
292 ALOGI("Idle timeout set to %u", timeout);
293 } else {
294 ALOGW("Cannot set idle timeout, IdleInvalidator not enabled");
295 }
296}
297
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800298void MDPComp::setMDPCompLayerFlags(hwc_context_t *ctx,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800299 hwc_display_contents_1_t* list) {
300 LayerProp *layerProp = ctx->layerProp[mDpy];
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800301
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800302 for(int index = 0; index < ctx->listStats[mDpy].numAppLayers; index++) {
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800303 hwc_layer_1_t* layer = &(list->hwLayers[index]);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800304 if(!mCurrentFrame.isFBComposed[index]) {
305 layerProp[index].mFlags |= HWC_MDPCOMP;
306 layer->compositionType = HWC_OVERLAY;
307 layer->hints |= HWC_HINT_CLEAR_FB;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800308 } else {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700309 /* Drop the layer when its already present in FB OR when it lies
310 * outside frame's ROI */
311 if(!mCurrentFrame.needsRedraw || mCurrentFrame.drop[index]) {
Arun Kumar K.R00b84792015-03-27 11:28:36 -0700312 if(index == mCurrentFrame.hwCursorIndex) {
313 layer->compositionType = HWC_CURSOR_OVERLAY;
314 } else {
315 layer->compositionType = HWC_OVERLAY;
316 }
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700317 }
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800318 }
319 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700320}
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500321
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800322void MDPComp::setRedraw(hwc_context_t *ctx,
323 hwc_display_contents_1_t* list) {
324 mCurrentFrame.needsRedraw = false;
325 if(!mCachedFrame.isSameFrame(mCurrentFrame, list) ||
326 (list->flags & HWC_GEOMETRY_CHANGED) ||
327 isSkipPresent(ctx, mDpy)) {
328 mCurrentFrame.needsRedraw = true;
329 }
330}
331
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800332MDPComp::FrameInfo::FrameInfo() {
Saurabh Shahf7fad542014-08-14 10:11:36 -0700333 memset(&mdpToLayer, 0, sizeof(mdpToLayer));
Saurabh Shahaa236822013-04-24 18:07:26 -0700334 reset(0);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800335}
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800336
Saurabh Shahaa236822013-04-24 18:07:26 -0700337void MDPComp::FrameInfo::reset(const int& numLayers) {
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700338 for(int i = 0 ; i < MAX_NUM_BLEND_STAGES; i++ ) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800339 if(mdpToLayer[i].pipeInfo) {
340 delete mdpToLayer[i].pipeInfo;
341 mdpToLayer[i].pipeInfo = NULL;
342 //We dont own the rotator
343 mdpToLayer[i].rot = NULL;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800344 }
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800345 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800346
347 memset(&mdpToLayer, 0, sizeof(mdpToLayer));
348 memset(&layerToMDP, -1, sizeof(layerToMDP));
Saurabh Shahaa236822013-04-24 18:07:26 -0700349 memset(&isFBComposed, 1, sizeof(isFBComposed));
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800350
Saurabh Shahaa236822013-04-24 18:07:26 -0700351 layerCount = numLayers;
352 fbCount = numLayers;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800353 mdpCount = 0;
Saurabh Shah2f3895f2013-05-02 10:13:31 -0700354 needsRedraw = true;
Saurabh Shahd53bc5f2014-02-05 10:17:43 -0800355 fbZ = -1;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800356}
357
Saurabh Shahaa236822013-04-24 18:07:26 -0700358void MDPComp::FrameInfo::map() {
359 // populate layer and MDP maps
360 int mdpIdx = 0;
361 for(int idx = 0; idx < layerCount; idx++) {
362 if(!isFBComposed[idx]) {
363 mdpToLayer[mdpIdx].listIndex = idx;
364 layerToMDP[idx] = mdpIdx++;
365 }
366 }
367}
368
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800369MDPComp::LayerCache::LayerCache() {
370 reset();
371}
372
373void MDPComp::LayerCache::reset() {
Saurabh Shahaa236822013-04-24 18:07:26 -0700374 memset(&hnd, 0, sizeof(hnd));
Prabhanjan Kandula2243aa62013-10-24 12:58:55 +0530375 memset(&isFBComposed, true, sizeof(isFBComposed));
376 memset(&drop, false, sizeof(drop));
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800377 layerCount = 0;
Saurabh Shahaa236822013-04-24 18:07:26 -0700378}
379
380void MDPComp::LayerCache::cacheAll(hwc_display_contents_1_t* list) {
Praveena Pachipulusud9443c72014-02-17 10:42:28 +0530381 const int numAppLayers = (int)list->numHwLayers - 1;
Saurabh Shahaa236822013-04-24 18:07:26 -0700382 for(int i = 0; i < numAppLayers; i++) {
383 hnd[i] = list->hwLayers[i].handle;
384 }
385}
386
387void MDPComp::LayerCache::updateCounts(const FrameInfo& curFrame) {
Saurabh Shahaa236822013-04-24 18:07:26 -0700388 layerCount = curFrame.layerCount;
Prabhanjan Kandula2243aa62013-10-24 12:58:55 +0530389 memcpy(&isFBComposed, &curFrame.isFBComposed, sizeof(isFBComposed));
390 memcpy(&drop, &curFrame.drop, sizeof(drop));
391}
392
Jeykumar Sankaran988d3682013-11-15 11:57:16 -0800393bool MDPComp::LayerCache::isSameFrame(const FrameInfo& curFrame,
394 hwc_display_contents_1_t* list) {
Prabhanjan Kandula2243aa62013-10-24 12:58:55 +0530395 if(layerCount != curFrame.layerCount)
396 return false;
397 for(int i = 0; i < curFrame.layerCount; i++) {
398 if((curFrame.isFBComposed[i] != isFBComposed[i]) ||
399 (curFrame.drop[i] != drop[i])) {
400 return false;
401 }
Jeykumar Sankaran988d3682013-11-15 11:57:16 -0800402 if(curFrame.isFBComposed[i] &&
403 (hnd[i] != list->hwLayers[i].handle)){
404 return false;
405 }
Prabhanjan Kandula2243aa62013-10-24 12:58:55 +0530406 }
407 return true;
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800408}
409
Raj Kamalfdfdddf2015-03-16 21:59:25 +0530410bool MDPComp::LayerCache::isSameFrame(hwc_context_t *ctx, int dpy,
411 hwc_display_contents_1_t* list) {
412
413 if(layerCount != ctx->listStats[dpy].numAppLayers)
414 return false;
415
416 if((list->flags & HWC_GEOMETRY_CHANGED) ||
417 isSkipPresent(ctx, dpy)) {
418 return false;
419 }
420
421 for(int i = 0; i < layerCount; i++) {
422 if(hnd[i] != list->hwLayers[i].handle)
423 return false;
424 }
425
426 return true;
427}
428
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700429bool MDPComp::isSupportedForMDPComp(hwc_context_t *ctx, hwc_layer_1_t* layer) {
430 private_handle_t *hnd = (private_handle_t *)layer->handle;
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800431 if((has90Transform(layer) and (not isRotationDoable(ctx, hnd))) ||
Raj Kamal1179d9c2014-10-28 15:31:35 +0530432 (not isValidDimension(ctx,layer)) ||
433 isSkipLayer(layer)) {
434 //More conditions here, sRGB+Blend etc
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700435 return false;
436 }
radhakrishna35e33072015-04-08 17:20:43 +0530437
438 //In targets with fewer pipes, frequent composition switch between MDP/GPU
439 //can happen for a layer due to lack of pipes. When this switch happens
440 //continuously for RGB downscaled layer with downscale greater than
441 //threshold, it appears as flicker as output
442 //of MDP and GPU are different as they use different filters for downscale.
443 //To avoid this flicker, punt RGB downscaled layer with downscale greater
444 //than threshold value to GPU always.
445 if((sDownscaleThreshold > 1.0)) {
446 if(((not isYuvBuffer(hnd))
447 and (not isDownscaleWithinThreshold(layer,
448 sDownscaleThreshold)))) {
449 ALOGD_IF(isDebug(), "%s: required downscale is greater than \
450 threshold %f", __FUNCTION__, sDownscaleThreshold);
451 return false;
452 }
453 }
454
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700455 return true;
456}
457
Sravan Kumar D.V.Nad5d9292013-04-24 14:23:04 +0530458bool MDPComp::isValidDimension(hwc_context_t *ctx, hwc_layer_1_t *layer) {
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800459 private_handle_t *hnd = (private_handle_t *)layer->handle;
460
461 if(!hnd) {
Sushil Chauhan897a9c32013-07-18 11:09:55 -0700462 if (layer->flags & HWC_COLOR_FILL) {
463 // Color layer
464 return true;
465 }
Ramkumar Radhakrishnan0cabf212014-09-08 20:07:49 -0700466 ALOGD_IF(isDebug(), "%s: layer handle is NULL", __FUNCTION__);
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800467 return false;
468 }
469
Naseer Ahmede850a802013-09-06 13:12:52 -0400470 //XXX: Investigate doing this with pixel phase on MDSS
Naseer Ahmede77f8082013-10-10 13:42:48 -0400471 if(!isSecureBuffer(hnd) && isNonIntegralSourceCrop(layer->sourceCropf))
Naseer Ahmede850a802013-09-06 13:12:52 -0400472 return false;
473
Saurabh Shah62e1d732013-09-17 10:44:05 -0700474 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
Saurabh Shah4fdde762013-04-30 18:47:33 -0700475 hwc_rect_t dst = layer->displayFrame;
Saurabh Shahb6810df2014-06-17 16:00:22 -0700476 bool rotated90 = (bool)(layer->transform & HAL_TRANSFORM_ROT_90);
Saurabh Shahe28a4022014-06-13 11:41:13 -0700477 int crop_w = rotated90 ? crop.bottom - crop.top : crop.right - crop.left;
478 int crop_h = rotated90 ? crop.right - crop.left : crop.bottom - crop.top;
Saurabh Shah4fdde762013-04-30 18:47:33 -0700479 int dst_w = dst.right - dst.left;
480 int dst_h = dst.bottom - dst.top;
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800481 float w_scale = ((float)crop_w / (float)dst_w);
482 float h_scale = ((float)crop_h / (float)dst_h);
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530483 MDPVersion& mdpHw = MDPVersion::getInstance();
Saurabh Shah4fdde762013-04-30 18:47:33 -0700484
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800485 /* Workaround for MDP HW limitation in DSI command mode panels where
486 * FPS will not go beyond 30 if buffers on RGB pipes are of width or height
487 * less than 5 pixels
Sravan Kumar D.V.Nad5d9292013-04-24 14:23:04 +0530488 * There also is a HW limilation in MDP, minimum block size is 2x2
489 * Fallback to GPU if height is less than 2.
490 */
Saurabh Shah189f23d2014-09-26 17:21:00 -0700491 if(mdpHw.hasMinCropWidthLimitation() and (crop_w < 5 or crop_h < 5))
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800492 return false;
493
Ramkumar Radhakrishnan1a763e92015-03-19 16:46:46 -0700494 /* crop_w and crop_h should be even for yuv layer, so fallback to GPU for
495 * those cases
496 */
497 if(isYuvBuffer(hnd) && (crop_w < 2 || crop_h < 2)) {
498 return false;
499 }
500
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800501 if((w_scale > 1.0f) || (h_scale > 1.0f)) {
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530502 const uint32_t maxMDPDownscale = mdpHw.getMaxMDPDownscale();
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800503 const float w_dscale = w_scale;
504 const float h_dscale = h_scale;
505
Jeykumar Sankaran1706a772013-11-27 12:55:19 -0800506 if(ctx->mMDP.version >= qdutils::MDSS_V5) {
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700507
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530508 if(!mdpHw.supportsDecimation()) {
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700509 /* On targets that doesnt support Decimation (eg.,8x26)
510 * maximum downscale support is overlay pipe downscale.
511 */
Jeykumar Sankaran39305802014-12-12 17:55:57 -0800512 if(crop_w > (int) mdpHw.getMaxPipeWidth() ||
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530513 w_dscale > maxMDPDownscale ||
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700514 h_dscale > maxMDPDownscale)
Jeykumar Sankaran1706a772013-11-27 12:55:19 -0800515 return false;
516 } else {
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700517 // Decimation on macrotile format layers is not supported.
518 if(isTileRendered(hnd)) {
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530519 /* Bail out if
520 * 1. Src crop > Mixer limit on nonsplit MDPComp
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700521 * 2. exceeds maximum downscale limit
522 */
Jeykumar Sankaran39305802014-12-12 17:55:57 -0800523 if(((crop_w > (int) mdpHw.getMaxPipeWidth()) &&
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530524 !sSrcSplitEnabled) ||
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700525 w_dscale > maxMDPDownscale ||
526 h_dscale > maxMDPDownscale) {
527 return false;
528 }
529 } else if(w_dscale > 64 || h_dscale > 64)
Jeykumar Sankaran1706a772013-11-27 12:55:19 -0800530 return false;
531 }
532 } else { //A-family
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700533 if(w_dscale > maxMDPDownscale || h_dscale > maxMDPDownscale)
Saurabh Shah4fdde762013-04-30 18:47:33 -0700534 return false;
535 }
Saurabh Shah4fdde762013-04-30 18:47:33 -0700536 }
537
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800538 if((w_scale < 1.0f) || (h_scale < 1.0f)) {
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530539 const uint32_t upscale = mdpHw.getMaxMDPUpscale();
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800540 const float w_uscale = 1.0f / w_scale;
541 const float h_uscale = 1.0f / h_scale;
542
543 if(w_uscale > upscale || h_uscale > upscale)
544 return false;
545 }
546
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800547 return true;
548}
549
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800550bool MDPComp::isFrameDoable(hwc_context_t *ctx) {
Saurabh Shahaa236822013-04-24 18:07:26 -0700551 bool ret = true;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800552
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800553 if(!isEnabled()) {
554 ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
Saurabh Shahaa236822013-04-24 18:07:26 -0700555 ret = false;
Raj Kamal068f4572014-04-14 16:14:06 +0530556 } else if((qdutils::MDPVersion::getInstance().is8x26() ||
Prabhanjan Kandula958ffa92014-05-12 14:56:56 +0530557 qdutils::MDPVersion::getInstance().is8x16() ||
558 qdutils::MDPVersion::getInstance().is8x39()) &&
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800559 ctx->mVideoTransFlag &&
560 isSecondaryConnected(ctx)) {
Saurabh Shahd4e65852013-06-17 11:33:53 -0700561 //1 Padding round to shift pipes across mixers
562 ALOGD_IF(isDebug(),"%s: MDP Comp. video transition padding round",
563 __FUNCTION__);
564 ret = false;
Raj Kamalc0d34242015-03-17 20:53:14 +0530565 } else if((qdutils::MDPVersion::getInstance().is8x26() ||
566 qdutils::MDPVersion::getInstance().is8x16() ||
567 qdutils::MDPVersion::getInstance().is8x39()) &&
568 !mDpy && isSecondaryAnimating(ctx) &&
569 isYuvPresent(ctx,HWC_DISPLAY_VIRTUAL)) {
570 ALOGD_IF(isDebug(),"%s: Display animation in progress",
571 __FUNCTION__);
572 ret = false;
Ramkumar Radhakrishnanf26fe9e2014-09-09 13:47:54 -0700573 } else if(qdutils::MDPVersion::getInstance().getTotalPipes() < 8) {
574 /* TODO: freeing up all the resources only for the targets having total
575 number of pipes < 8. Need to analyze number of VIG pipes used
576 for primary in previous draw cycle and accordingly decide
577 whether to fall back to full GPU comp or video only comp
578 */
579 if(isSecondaryConfiguring(ctx)) {
580 ALOGD_IF( isDebug(),"%s: External Display connection is pending",
581 __FUNCTION__);
582 ret = false;
583 } else if(ctx->isPaddingRound) {
584 ALOGD_IF(isDebug(), "%s: padding round invoked for dpy %d",
585 __FUNCTION__,mDpy);
586 ret = false;
587 }
Tatenda Chipeperekwadc8d7082014-11-04 16:41:50 -0800588 } else if (ctx->isDMAStateChanging) {
589 // Bail out if a padding round has been invoked in order to switch DMA
590 // state to block mode. We need this to cater for the case when a layer
591 // requires rotation in the current frame.
592 ALOGD_IF(isDebug(), "%s: padding round invoked to switch DMA state",
593 __FUNCTION__);
594 return false;
Saurabh Shah0ceeb6a2013-04-23 10:46:07 -0700595 }
Tatenda Chipeperekwadc8d7082014-11-04 16:41:50 -0800596
Saurabh Shahaa236822013-04-24 18:07:26 -0700597 return ret;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800598}
599
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800600void MDPCompNonSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect &crop,
601 hwc_rect &dst) {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800602 hwc_rect_t roi = ctx->listStats[mDpy].lRoi;
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800603 dst = getIntersection(dst, roi);
604 crop = dst;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800605}
606
607/* 1) Identify layers that are not visible or lying outside the updating ROI and
608 * drop them from composition.
609 * 2) If we have a scaling layer which needs cropping against generated
610 * ROI, reset ROI to full resolution. */
611bool MDPCompNonSplit::validateAndApplyROI(hwc_context_t *ctx,
612 hwc_display_contents_1_t* list) {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700613 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800614 hwc_rect_t visibleRect = ctx->listStats[mDpy].lRoi;
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800615
616 for(int i = numAppLayers - 1; i >= 0; i--){
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800617 if(!isValidRect(visibleRect)) {
618 mCurrentFrame.drop[i] = true;
619 mCurrentFrame.dropCount++;
Jeykumar Sankaran0b961452014-01-21 17:26:12 -0800620 continue;
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800621 }
622
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700623 const hwc_layer_1_t* layer = &list->hwLayers[i];
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700624 hwc_rect_t dstRect = layer->displayFrame;
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800625 hwc_rect_t res = getIntersection(visibleRect, dstRect);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700626
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700627 if(!isValidRect(res)) {
628 mCurrentFrame.drop[i] = true;
629 mCurrentFrame.dropCount++;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800630 } else {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700631 /* Reset frame ROI when any layer which needs scaling also needs ROI
632 * cropping */
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800633 if(!isSameRect(res, dstRect) && needsScaling (layer)) {
Arpita Banerjeed8965982013-11-08 17:27:33 -0800634 ALOGI("%s: Resetting ROI due to scaling", __FUNCTION__);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700635 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
636 mCurrentFrame.dropCount = 0;
637 return false;
638 }
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800639
Jeykumar Sankaran0b961452014-01-21 17:26:12 -0800640 /* deduct any opaque region from visibleRect */
radhakrishna4efbdd62014-11-03 13:19:27 +0530641 if (layer->blending == HWC_BLENDING_NONE &&
642 layer->planeAlpha == 0xFF)
Jeykumar Sankaran0b961452014-01-21 17:26:12 -0800643 visibleRect = deductRect(visibleRect, res);
644 }
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700645 }
646 return true;
647}
648
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800649/* Calculate ROI for the frame by accounting all the layer's dispalyFrame which
650 * are updating. If DirtyRegion is applicable, calculate it by accounting all
651 * the changing layer's dirtyRegion. */
652void MDPCompNonSplit::generateROI(hwc_context_t *ctx,
653 hwc_display_contents_1_t* list) {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700654 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800655 if(!canPartialUpdate(ctx, list))
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700656 return;
657
658 struct hwc_rect roi = (struct hwc_rect){0, 0, 0, 0};
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800659 hwc_rect fullFrame = (struct hwc_rect) {0, 0,(int)ctx->dpyAttr[mDpy].xres,
660 (int)ctx->dpyAttr[mDpy].yres};
661
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700662 for(int index = 0; index < numAppLayers; index++ ) {
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800663 hwc_layer_1_t* layer = &list->hwLayers[index];
664 if ((mCachedFrame.hnd[index] != layer->handle) ||
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800665 isYuvBuffer((private_handle_t *)layer->handle)) {
Jeykumar Sankaran455678c2014-05-30 10:22:38 -0700666 hwc_rect_t dst = layer->displayFrame;
667 hwc_rect_t updatingRect = dst;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800668
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800669#ifdef QCOM_BSP
Dileep Kumar Reddi7399d5c2014-12-31 18:01:19 +0530670 if(!needsScaling(layer) && !layer->transform &&
671 (!isYuvBuffer((private_handle_t *)layer->handle)))
Jeykumar Sankaran455678c2014-05-30 10:22:38 -0700672 {
673 hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
674 int x_off = dst.left - src.left;
675 int y_off = dst.top - src.top;
676 updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
677 }
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800678#endif
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800679
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800680 roi = getUnion(roi, updatingRect);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700681 }
682 }
683
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800684 /* No layer is updating. Still SF wants a refresh.*/
685 if(!isValidRect(roi))
686 return;
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800687
688 // Align ROI coordinates to panel restrictions
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800689 roi = getSanitizeROI(roi, fullFrame);
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800690
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800691 ctx->listStats[mDpy].lRoi = roi;
692 if(!validateAndApplyROI(ctx, list))
693 resetROI(ctx, mDpy);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700694
695 ALOGD_IF(isDebug(),"%s: generated ROI: [%d, %d, %d, %d]", __FUNCTION__,
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800696 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
697 ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom);
698}
699
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800700void MDPCompSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect &crop,
701 hwc_rect &dst) {
702 hwc_rect roi = getUnion(ctx->listStats[mDpy].lRoi,
703 ctx->listStats[mDpy].rRoi);
704 hwc_rect tmpDst = getIntersection(dst, roi);
705 if(!isSameRect(dst, tmpDst)) {
706 crop.left = crop.left + (tmpDst.left - dst.left);
707 crop.top = crop.top + (tmpDst.top - dst.top);
708 crop.right = crop.left + (tmpDst.right - tmpDst.left);
709 crop.bottom = crop.top + (tmpDst.bottom - tmpDst.top);
710 dst = tmpDst;
711 }
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800712}
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800713
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800714/* 1) Identify layers that are not visible or lying outside BOTH the updating
715 * ROI's and drop them from composition. If a layer is spanning across both
716 * the halves of the screen but needed by only ROI, the non-contributing
717 * half will not be programmed for MDP.
718 * 2) If we have a scaling layer which needs cropping against generated
719 * ROI, reset ROI to full resolution. */
720bool MDPCompSplit::validateAndApplyROI(hwc_context_t *ctx,
721 hwc_display_contents_1_t* list) {
722
723 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
724
725 hwc_rect_t visibleRectL = ctx->listStats[mDpy].lRoi;
726 hwc_rect_t visibleRectR = ctx->listStats[mDpy].rRoi;
727
728 for(int i = numAppLayers - 1; i >= 0; i--){
729 if(!isValidRect(visibleRectL) && !isValidRect(visibleRectR))
730 {
731 mCurrentFrame.drop[i] = true;
732 mCurrentFrame.dropCount++;
733 continue;
734 }
735
736 const hwc_layer_1_t* layer = &list->hwLayers[i];
737 hwc_rect_t dstRect = layer->displayFrame;
738
739 hwc_rect_t l_res = getIntersection(visibleRectL, dstRect);
740 hwc_rect_t r_res = getIntersection(visibleRectR, dstRect);
741 hwc_rect_t res = getUnion(l_res, r_res);
742
743 if(!isValidRect(l_res) && !isValidRect(r_res)) {
744 mCurrentFrame.drop[i] = true;
745 mCurrentFrame.dropCount++;
746 } else {
747 /* Reset frame ROI when any layer which needs scaling also needs ROI
748 * cropping */
749 if(!isSameRect(res, dstRect) && needsScaling (layer)) {
750 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
751 mCurrentFrame.dropCount = 0;
752 return false;
753 }
754
radhakrishna4efbdd62014-11-03 13:19:27 +0530755 if (layer->blending == HWC_BLENDING_NONE &&
756 layer->planeAlpha == 0xFF) {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800757 visibleRectL = deductRect(visibleRectL, l_res);
758 visibleRectR = deductRect(visibleRectR, r_res);
759 }
760 }
761 }
762 return true;
763}
764/* Calculate ROI for the frame by accounting all the layer's dispalyFrame which
765 * are updating. If DirtyRegion is applicable, calculate it by accounting all
766 * the changing layer's dirtyRegion. */
767void MDPCompSplit::generateROI(hwc_context_t *ctx,
768 hwc_display_contents_1_t* list) {
769 if(!canPartialUpdate(ctx, list))
770 return;
771
772 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
773 int lSplit = getLeftSplit(ctx, mDpy);
774
775 int hw_h = (int)ctx->dpyAttr[mDpy].yres;
776 int hw_w = (int)ctx->dpyAttr[mDpy].xres;
777
778 struct hwc_rect l_frame = (struct hwc_rect){0, 0, lSplit, hw_h};
779 struct hwc_rect r_frame = (struct hwc_rect){lSplit, 0, hw_w, hw_h};
780
781 struct hwc_rect l_roi = (struct hwc_rect){0, 0, 0, 0};
782 struct hwc_rect r_roi = (struct hwc_rect){0, 0, 0, 0};
783
784 for(int index = 0; index < numAppLayers; index++ ) {
785 hwc_layer_1_t* layer = &list->hwLayers[index];
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800786 private_handle_t *hnd = (private_handle_t *)layer->handle;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800787 if ((mCachedFrame.hnd[index] != layer->handle) ||
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800788 isYuvBuffer(hnd)) {
Jeykumar Sankaran71e597c2014-05-07 16:23:14 -0700789 hwc_rect_t dst = layer->displayFrame;
790 hwc_rect_t updatingRect = dst;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800791
792#ifdef QCOM_BSP
793 if(!needsScaling(layer) && !layer->transform)
Jeykumar Sankaran71e597c2014-05-07 16:23:14 -0700794 {
795 hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
796 int x_off = dst.left - src.left;
797 int y_off = dst.top - src.top;
798 updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
799 }
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800800#endif
801
802 hwc_rect_t l_dst = getIntersection(l_frame, updatingRect);
803 if(isValidRect(l_dst))
804 l_roi = getUnion(l_roi, l_dst);
805
806 hwc_rect_t r_dst = getIntersection(r_frame, updatingRect);
807 if(isValidRect(r_dst))
808 r_roi = getUnion(r_roi, r_dst);
809 }
810 }
811
Jeykumar Sankarana40a9342014-04-25 09:37:10 -0700812 /* For panels that cannot accept commands in both the interfaces, we cannot
813 * send two ROI's (for each half). We merge them into single ROI and split
814 * them across lSplit for MDP mixer use. The ROI's will be merged again
815 * finally before udpating the panel in the driver. */
816 if(qdutils::MDPVersion::getInstance().needsROIMerge()) {
817 hwc_rect_t temp_roi = getUnion(l_roi, r_roi);
818 l_roi = getIntersection(temp_roi, l_frame);
819 r_roi = getIntersection(temp_roi, r_frame);
820 }
821
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800822 /* No layer is updating. Still SF wants a refresh. */
823 if(!isValidRect(l_roi) && !isValidRect(r_roi))
824 return;
825
826 l_roi = getSanitizeROI(l_roi, l_frame);
827 r_roi = getSanitizeROI(r_roi, r_frame);
828
829 ctx->listStats[mDpy].lRoi = l_roi;
830 ctx->listStats[mDpy].rRoi = r_roi;
831
832 if(!validateAndApplyROI(ctx, list))
833 resetROI(ctx, mDpy);
834
835 ALOGD_IF(isDebug(),"%s: generated L_ROI: [%d, %d, %d, %d]"
836 "R_ROI: [%d, %d, %d, %d]", __FUNCTION__,
837 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
838 ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom,
839 ctx->listStats[mDpy].rRoi.left, ctx->listStats[mDpy].rRoi.top,
840 ctx->listStats[mDpy].rRoi.right, ctx->listStats[mDpy].rRoi.bottom);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700841}
842
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800843/* Checks for conditions where all the layers marked for MDP comp cannot be
844 * bypassed. On such conditions we try to bypass atleast YUV layers */
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800845bool MDPComp::tryFullFrame(hwc_context_t *ctx,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800846 hwc_display_contents_1_t* list){
847
Saurabh Shahaa236822013-04-24 18:07:26 -0700848 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800849
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -0700850 // Fall back to video only composition, if AIV video mode is enabled
851 if(ctx->listStats[mDpy].mAIVVideoMode) {
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -0700852 ALOGD_IF(isDebug(), "%s: AIV Video Mode enabled dpy %d",
853 __FUNCTION__, mDpy);
854 return false;
855 }
856
Praveena Pachipulusu47346c22014-12-04 11:06:41 +0530857 /* No Idle fall back if secure display or secure RGB layers are present
858 * or if there is only a single layer being composed */
859 if(sIdleFallBack && !ctx->listStats[mDpy].secureUI &&
860 !ctx->listStats[mDpy].secureRGBCount &&
861 (ctx->listStats[mDpy].numAppLayers > 1)) {
Saurabh Shah2d998a92013-05-14 17:55:58 -0700862 ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
863 return false;
864 }
865
Raj Kamalc0d34242015-03-17 20:53:14 +0530866 if(!mDpy && isSecondaryAnimating(ctx) &&
867 (isYuvPresent(ctx,HWC_DISPLAY_EXTERNAL) ||
868 isYuvPresent(ctx,HWC_DISPLAY_VIRTUAL)) ) {
869 ALOGD_IF(isDebug(),"%s: Display animation in progress",
870 __FUNCTION__);
871 return false;
872 }
873
Ramkumar Radhakrishnanf26fe9e2014-09-09 13:47:54 -0700874 // if secondary is configuring or Padding round, fall back to video only
875 // composition and release all assigned non VIG pipes from primary.
876 if(isSecondaryConfiguring(ctx)) {
877 ALOGD_IF( isDebug(),"%s: External Display connection is pending",
878 __FUNCTION__);
879 return false;
880 } else if(ctx->isPaddingRound) {
881 ALOGD_IF(isDebug(), "%s: padding round invoked for dpy %d",
882 __FUNCTION__,mDpy);
883 return false;
884 }
885
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -0500886 // No MDP composition for 3D
887 if(needs3DComposition(ctx, mDpy))
888 return false;
889
Tatenda Chipeperekwacb2a2432014-08-06 17:45:58 -0700890 // check for action safe flag and MDP scaling mode which requires scaling.
Ramkumar Radhakrishnan4af1ef02013-12-12 11:53:08 -0800891 if(ctx->dpyAttr[mDpy].mActionSafePresent
Tatenda Chipeperekwacb2a2432014-08-06 17:45:58 -0700892 || ctx->dpyAttr[mDpy].mMDPScalingMode) {
Ramkumar Radhakrishnan4af1ef02013-12-12 11:53:08 -0800893 ALOGD_IF(isDebug(), "%s: Scaling needed for this frame",__FUNCTION__);
894 return false;
895 }
896
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800897 for(int i = 0; i < numAppLayers; ++i) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800898 hwc_layer_1_t* layer = &list->hwLayers[i];
899 private_handle_t *hnd = (private_handle_t *)layer->handle;
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -0800900
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800901 if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700902 if(!canUseRotator(ctx, mDpy)) {
903 ALOGD_IF(isDebug(), "%s: Can't use rotator for dpy %d",
904 __FUNCTION__, mDpy);
Amara Venkata Mastan Manoj Kumar9d373c02013-08-20 14:30:09 -0700905 return false;
906 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800907 }
Prabhanjan Kandula9fb032a2013-06-18 17:37:22 +0530908
909 //For 8x26 with panel width>1k, if RGB layer needs HFLIP fail mdp comp
910 // may not need it if Gfx pre-rotation can handle all flips & rotations
Saurabh Shahcad57772014-12-01 14:19:51 -0800911 MDPVersion& mdpHw = MDPVersion::getInstance();
Sushil Chauhanfda00fc2014-03-20 11:08:41 -0700912 int transform = (layer->flags & HWC_COLOR_FILL) ? 0 : layer->transform;
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530913 if( mdpHw.is8x26() && (ctx->dpyAttr[mDpy].xres > 1024) &&
914 (transform & HWC_TRANSFORM_FLIP_H) && (!isYuvBuffer(hnd)))
915 return false;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800916 }
Saurabh Shahaa236822013-04-24 18:07:26 -0700917
Saurabh Shaha9da08f2013-07-03 13:27:53 -0700918 if(ctx->mAD->isDoable()) {
919 return false;
920 }
921
Saurabh Shahaa236822013-04-24 18:07:26 -0700922 //If all above hard conditions are met we can do full or partial MDP comp.
923 bool ret = false;
924 if(fullMDPComp(ctx, list)) {
925 ret = true;
Sushil Chauhandefd3522014-05-13 18:17:12 -0700926 } else if(fullMDPCompWithPTOR(ctx, list)) {
927 ret = true;
Jeykumar Sankaran24c199d2013-05-24 09:40:36 -0700928 } else if(partialMDPComp(ctx, list)) {
Saurabh Shahaa236822013-04-24 18:07:26 -0700929 ret = true;
930 }
Prabhanjan Kandula21918db2013-11-26 15:51:58 +0530931
Saurabh Shahaa236822013-04-24 18:07:26 -0700932 return ret;
933}
934
935bool MDPComp::fullMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -0700936
937 if(sSimulationFlags & MDPCOMP_AVOID_FULL_MDP)
938 return false;
939
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700940 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
941 for(int i = 0; i < numAppLayers; i++) {
942 hwc_layer_1_t* layer = &list->hwLayers[i];
Jeykumar Sankaran880da832014-04-18 10:22:35 -0700943 if(not mCurrentFrame.drop[i] and
944 not isSupportedForMDPComp(ctx, layer)) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700945 ALOGD_IF(isDebug(), "%s: Unsupported layer in list",__FUNCTION__);
946 return false;
947 }
948 }
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800949
Saurabh Shahaa236822013-04-24 18:07:26 -0700950 mCurrentFrame.fbCount = 0;
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700951 memcpy(&mCurrentFrame.isFBComposed, &mCurrentFrame.drop,
952 sizeof(mCurrentFrame.isFBComposed));
953 mCurrentFrame.mdpCount = mCurrentFrame.layerCount - mCurrentFrame.fbCount -
954 mCurrentFrame.dropCount;
Saurabh Shahaa236822013-04-24 18:07:26 -0700955
Raj Kamal389d6e32014-08-04 14:43:24 +0530956 if(sEnableYUVsplit){
Saurabh Shah3d4b8042013-12-10 15:19:17 -0800957 adjustForSourceSplit(ctx, list);
radhakrishnac9a67412013-09-25 17:40:42 +0530958 }
959
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800960 if(!postHeuristicsHandling(ctx, list)) {
961 ALOGD_IF(isDebug(), "post heuristic handling failed");
962 reset(ctx);
Saurabh Shah8c5c8522013-08-29 17:32:49 -0700963 return false;
964 }
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -0700965 ALOGD_IF(sSimulationFlags,"%s: FULL_MDP_COMP SUCCEEDED",
966 __FUNCTION__);
Saurabh Shahaa236822013-04-24 18:07:26 -0700967 return true;
968}
969
Sushil Chauhandefd3522014-05-13 18:17:12 -0700970/* Full MDP Composition with Peripheral Tiny Overlap Removal.
971 * MDP bandwidth limitations can be avoided, if the overlap region
972 * covered by the smallest layer at a higher z-order, gets composed
973 * by Copybit on a render buffer, which can be queued to MDP.
974 */
975bool MDPComp::fullMDPCompWithPTOR(hwc_context_t *ctx,
976 hwc_display_contents_1_t* list) {
977
978 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Arun Kumar K.R00b84792015-03-27 11:28:36 -0700979 // PTOR does not qualify when there are layers dropped, but if
980 // dropped layer is only a cursor, PTOR could qualify
981 const int numNonCursorLayers = numAppLayers - mCurrentFrame.dropCount;
Sushil Chauhandefd3522014-05-13 18:17:12 -0700982 const int stagesForMDP = min(sMaxPipesPerMixer,
983 ctx->mOverlay->availablePipes(mDpy, Overlay::MIXER_DEFAULT));
984
985 // Hard checks where we cannot use this mode
Sushil Chauhanbfc2de02014-07-24 11:52:58 -0700986 if (mDpy || !ctx->mCopyBit[mDpy]) {
Sushil Chauhandefd3522014-05-13 18:17:12 -0700987 ALOGD_IF(isDebug(), "%s: Feature not supported!", __FUNCTION__);
988 return false;
989 }
990
Arun Kumar K.R00b84792015-03-27 11:28:36 -0700991 // Frame level checks - consider PTOR in case of dropCount only if the cursor
992 // layer is dropped, otherwise bail out of PTOR
Sushil Chauhandefd3522014-05-13 18:17:12 -0700993 if ((numAppLayers > stagesForMDP) || isSkipPresent(ctx, mDpy) ||
Arun Kumar K.R00b84792015-03-27 11:28:36 -0700994 isYuvPresent(ctx, mDpy) || isSecurePresent(ctx, mDpy) ||
995 (mCurrentFrame.dropCount - (int)isCursorPresent(ctx, mDpy))) {
Sushil Chauhandefd3522014-05-13 18:17:12 -0700996 ALOGD_IF(isDebug(), "%s: Frame not supported!", __FUNCTION__);
997 return false;
998 }
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -0700999 // MDP comp checks
1000 for(int i = 0; i < numAppLayers; i++) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001001 hwc_layer_1_t* layer = &list->hwLayers[i];
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001002 if(not isSupportedForMDPComp(ctx, layer)) {
1003 ALOGD_IF(isDebug(), "%s: Unsupported layer in list",__FUNCTION__);
1004 return false;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001005 }
1006 }
1007
Sushil Chauhandefd3522014-05-13 18:17:12 -07001008 /* We cannot use this composition mode, if:
1009 1. A below layer needs scaling.
1010 2. Overlap is not peripheral to display.
1011 3. Overlap or a below layer has 90 degree transform.
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001012 4. Overlap area > (1/3 * FrameBuffer) area, based on Perf inputs.
Sushil Chauhandefd3522014-05-13 18:17:12 -07001013 */
1014
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001015 int minLayerIndex[MAX_PTOR_LAYERS] = { -1, -1};
1016 hwc_rect_t overlapRect[MAX_PTOR_LAYERS];
1017 memset(overlapRect, 0, sizeof(overlapRect));
1018 int layerPixelCount, minPixelCount = 0;
1019 int numPTORLayersFound = 0;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001020 for (int i = numNonCursorLayers - 1; (i >= 0 &&
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001021 numPTORLayersFound < MAX_PTOR_LAYERS); i--) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001022 hwc_layer_1_t* layer = &list->hwLayers[i];
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001023 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
Sushil Chauhandefd3522014-05-13 18:17:12 -07001024 hwc_rect_t dispFrame = layer->displayFrame;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001025 layerPixelCount = (crop.right - crop.left) * (crop.bottom - crop.top);
1026 // PTOR layer should be peripheral and cannot have transform
1027 if (!isPeripheral(dispFrame, ctx->mViewFrame[mDpy]) ||
1028 has90Transform(layer)) {
1029 continue;
1030 }
1031 if((3 * (layerPixelCount + minPixelCount)) >
1032 ((int)ctx->dpyAttr[mDpy].xres * (int)ctx->dpyAttr[mDpy].yres)) {
1033 // Overlap area > (1/3 * FrameBuffer) area, based on Perf inputs.
1034 continue;
1035 }
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001036 bool found = false;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001037 for (int j = i-1; j >= 0; j--) {
1038 // Check if the layers below this layer qualifies for PTOR comp
1039 hwc_layer_1_t* layer = &list->hwLayers[j];
1040 hwc_rect_t disFrame = layer->displayFrame;
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001041 // Layer below PTOR is intersecting and has 90 degree transform or
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001042 // needs scaling cannot be supported.
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001043 if (isValidRect(getIntersection(dispFrame, disFrame))) {
1044 if (has90Transform(layer) || needsScaling(layer)) {
1045 found = false;
1046 break;
1047 }
1048 found = true;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001049 }
1050 }
1051 // Store the minLayer Index
1052 if(found) {
1053 minLayerIndex[numPTORLayersFound] = i;
1054 overlapRect[numPTORLayersFound] = list->hwLayers[i].displayFrame;
1055 minPixelCount += layerPixelCount;
1056 numPTORLayersFound++;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001057 }
1058 }
1059
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001060 // No overlap layers
1061 if (!numPTORLayersFound)
1062 return false;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001063
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001064 // Store the displayFrame and the sourceCrops of the layers
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001065 hwc_rect_t displayFrame[numNonCursorLayers];
1066 hwc_rect_t sourceCrop[numNonCursorLayers];
1067 for(int i = 0; i < numNonCursorLayers; i++) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001068 hwc_layer_1_t* layer = &list->hwLayers[i];
1069 displayFrame[i] = layer->displayFrame;
1070 sourceCrop[i] = integerizeSourceCrop(layer->sourceCropf);
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001071 }
Sushil Chauhandefd3522014-05-13 18:17:12 -07001072
Prabhanjan Kandula9889a202014-09-04 21:50:35 +05301073 /**
1074 * It's possible that 2 PTOR layers might have overlapping.
1075 * In such case, remove the intersection(again if peripheral)
1076 * from the lower PTOR layer to avoid overlapping.
1077 * If intersection is not on peripheral then compromise
1078 * by reducing number of PTOR layers.
1079 **/
1080 hwc_rect_t commonRect = getIntersection(overlapRect[0], overlapRect[1]);
1081 if(isValidRect(commonRect)) {
1082 overlapRect[1] = deductRect(overlapRect[1], commonRect);
1083 list->hwLayers[minLayerIndex[1]].displayFrame = overlapRect[1];
1084 }
1085
1086 ctx->mPtorInfo.count = numPTORLayersFound;
1087 for(int i = 0; i < MAX_PTOR_LAYERS; i++) {
1088 ctx->mPtorInfo.layerIndex[i] = minLayerIndex[i];
1089 }
1090
1091 if (!ctx->mCopyBit[mDpy]->prepareOverlap(ctx, list)) {
1092 // reset PTOR
1093 ctx->mPtorInfo.count = 0;
1094 if(isValidRect(commonRect)) {
1095 // If PTORs are intersecting restore displayframe of PTOR[1]
1096 // before returning, as we have modified it above.
1097 list->hwLayers[minLayerIndex[1]].displayFrame =
1098 displayFrame[minLayerIndex[1]];
1099 }
1100 return false;
1101 }
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001102 private_handle_t *renderBuf = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
1103 Whf layerWhf[numPTORLayersFound]; // To store w,h,f of PTOR layers
1104
Xu Yangcda012c2014-07-30 21:57:21 +08001105 // Store the blending mode, planeAlpha, and transform of PTOR layers
1106 int32_t blending[numPTORLayersFound];
1107 uint8_t planeAlpha[numPTORLayersFound];
1108 uint32_t transform[numPTORLayersFound];
1109
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001110 for(int j = 0; j < numPTORLayersFound; j++) {
1111 int index = ctx->mPtorInfo.layerIndex[j];
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001112
1113 // Update src crop of PTOR layer
1114 hwc_layer_1_t* layer = &list->hwLayers[index];
1115 layer->sourceCropf.left = (float)ctx->mPtorInfo.displayFrame[j].left;
1116 layer->sourceCropf.top = (float)ctx->mPtorInfo.displayFrame[j].top;
1117 layer->sourceCropf.right = (float)ctx->mPtorInfo.displayFrame[j].right;
1118 layer->sourceCropf.bottom =(float)ctx->mPtorInfo.displayFrame[j].bottom;
1119
1120 // Store & update w, h, format of PTOR layer
1121 private_handle_t *hnd = (private_handle_t *)layer->handle;
1122 Whf whf(hnd->width, hnd->height, hnd->format, hnd->size);
1123 layerWhf[j] = whf;
1124 hnd->width = renderBuf->width;
1125 hnd->height = renderBuf->height;
1126 hnd->format = renderBuf->format;
1127
Xu Yangcda012c2014-07-30 21:57:21 +08001128 // Store & update blending mode, planeAlpha and transform of PTOR layer
1129 blending[j] = layer->blending;
1130 planeAlpha[j] = layer->planeAlpha;
1131 transform[j] = layer->transform;
1132 layer->blending = HWC_BLENDING_NONE;
1133 layer->planeAlpha = 0xFF;
1134 layer->transform = 0;
1135
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001136 // Remove overlap from crop & displayFrame of below layers
1137 for (int i = 0; i < index && index !=-1; i++) {
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001138 layer = &list->hwLayers[i];
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001139 if(!isValidRect(getIntersection(layer->displayFrame,
1140 overlapRect[j]))) {
1141 continue;
1142 }
1143 // Update layer attributes
1144 hwc_rect_t srcCrop = integerizeSourceCrop(layer->sourceCropf);
1145 hwc_rect_t destRect = deductRect(layer->displayFrame,
Dileep Kumar Reddi72058b82014-11-11 16:03:03 +05301146 getIntersection(layer->displayFrame, overlapRect[j]));
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001147 qhwc::calculate_crop_rects(srcCrop, layer->displayFrame, destRect,
1148 layer->transform);
1149 layer->sourceCropf.left = (float)srcCrop.left;
1150 layer->sourceCropf.top = (float)srcCrop.top;
1151 layer->sourceCropf.right = (float)srcCrop.right;
1152 layer->sourceCropf.bottom = (float)srcCrop.bottom;
1153 }
Sushil Chauhandefd3522014-05-13 18:17:12 -07001154 }
1155
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001156 mCurrentFrame.mdpCount = numNonCursorLayers;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001157 mCurrentFrame.fbCount = 0;
1158 mCurrentFrame.fbZ = -1;
1159
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001160 for (int j = 0; j < numNonCursorLayers; j++) {
Dileep Kumar Reddi72058b82014-11-11 16:03:03 +05301161 if(isValidRect(list->hwLayers[j].displayFrame)) {
1162 mCurrentFrame.isFBComposed[j] = false;
1163 } else {
1164 mCurrentFrame.mdpCount--;
1165 mCurrentFrame.drop[j] = true;
1166 }
1167 }
Sushil Chauhandefd3522014-05-13 18:17:12 -07001168
1169 bool result = postHeuristicsHandling(ctx, list);
1170
1171 // Restore layer attributes
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001172 for(int i = 0; i < numNonCursorLayers; i++) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001173 hwc_layer_1_t* layer = &list->hwLayers[i];
1174 layer->displayFrame = displayFrame[i];
1175 layer->sourceCropf.left = (float)sourceCrop[i].left;
1176 layer->sourceCropf.top = (float)sourceCrop[i].top;
1177 layer->sourceCropf.right = (float)sourceCrop[i].right;
1178 layer->sourceCropf.bottom = (float)sourceCrop[i].bottom;
1179 }
1180
Xu Yangcda012c2014-07-30 21:57:21 +08001181 // Restore w,h,f, blending attributes, and transform of PTOR layers
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001182 for (int i = 0; i < numPTORLayersFound; i++) {
1183 int idx = ctx->mPtorInfo.layerIndex[i];
Xu Yangcda012c2014-07-30 21:57:21 +08001184 hwc_layer_1_t* layer = &list->hwLayers[idx];
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001185 private_handle_t *hnd = (private_handle_t *)list->hwLayers[idx].handle;
1186 hnd->width = layerWhf[i].w;
1187 hnd->height = layerWhf[i].h;
1188 hnd->format = layerWhf[i].format;
Xu Yangcda012c2014-07-30 21:57:21 +08001189 layer->blending = blending[i];
1190 layer->planeAlpha = planeAlpha[i];
1191 layer->transform = transform[i];
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001192 }
1193
Sushil Chauhandefd3522014-05-13 18:17:12 -07001194 if (!result) {
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001195 // reset PTOR
1196 ctx->mPtorInfo.count = 0;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001197 reset(ctx);
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001198 } else {
1199 ALOGD_IF(isDebug(), "%s: PTOR Indexes: %d and %d", __FUNCTION__,
1200 ctx->mPtorInfo.layerIndex[0], ctx->mPtorInfo.layerIndex[1]);
Sushil Chauhandefd3522014-05-13 18:17:12 -07001201 }
1202
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001203 ALOGD_IF(isDebug(), "%s: Postheuristics %s!", __FUNCTION__,
1204 (result ? "successful" : "failed"));
Sushil Chauhandefd3522014-05-13 18:17:12 -07001205 return result;
1206}
1207
Saurabh Shahaa236822013-04-24 18:07:26 -07001208bool MDPComp::partialMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list)
1209{
radhakrishnac3198ff2015-03-10 17:10:02 +05301210 if(!sEnableMixedMode || !isAlphaPresentinFB(ctx, mDpy)) {
1211 //Mixed mode is disabled/can't be used. No need to even try caching.
Jeykumar Sankaran24c199d2013-05-24 09:40:36 -07001212 return false;
1213 }
1214
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001215 bool ret = false;
Raj Kamal1179d9c2014-10-28 15:31:35 +05301216 if(isSkipPresent(ctx, mDpy) or list->flags & HWC_GEOMETRY_CHANGED) {
1217 //Try load based first
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001218 ret = loadBasedComp(ctx, list) or
Saurabh Shahf2de00f2013-12-11 17:52:53 -08001219 cacheBasedComp(ctx, list);
1220 } else {
1221 ret = cacheBasedComp(ctx, list) or
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001222 loadBasedComp(ctx, list);
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001223 }
1224
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001225 return ret;
1226}
1227
1228bool MDPComp::cacheBasedComp(hwc_context_t *ctx,
1229 hwc_display_contents_1_t* list) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001230 if(sSimulationFlags & MDPCOMP_AVOID_CACHE_MDP)
1231 return false;
1232
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001233 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shahaa236822013-04-24 18:07:26 -07001234 mCurrentFrame.reset(numAppLayers);
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001235 updateLayerCache(ctx, list, mCurrentFrame);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001236
1237 //If an MDP marked layer is unsupported cannot do partial MDP Comp
1238 for(int i = 0; i < numAppLayers; i++) {
1239 if(!mCurrentFrame.isFBComposed[i]) {
1240 hwc_layer_1_t* layer = &list->hwLayers[i];
1241 if(not isSupportedForMDPComp(ctx, layer)) {
1242 ALOGD_IF(isDebug(), "%s: Unsupported layer in list",
1243 __FUNCTION__);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001244 reset(ctx);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001245 return false;
1246 }
1247 }
1248 }
1249
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001250 updateYUV(ctx, list, false /*secure only*/, mCurrentFrame);
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001251 /* mark secure RGB layers for MDP comp */
1252 updateSecureRGB(ctx, list);
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301253 bool ret = markLayersForCaching(ctx, list); //sets up fbZ also
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001254 if(!ret) {
1255 ALOGD_IF(isDebug(),"%s: batching failed, dpy %d",__FUNCTION__, mDpy);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001256 reset(ctx);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001257 return false;
1258 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001259
1260 int mdpCount = mCurrentFrame.mdpCount;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001261
Raj Kamal389d6e32014-08-04 14:43:24 +05301262 if(sEnableYUVsplit){
Saurabh Shah3d4b8042013-12-10 15:19:17 -08001263 adjustForSourceSplit(ctx, list);
radhakrishnac9a67412013-09-25 17:40:42 +05301264 }
1265
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001266 if(!postHeuristicsHandling(ctx, list)) {
1267 ALOGD_IF(isDebug(), "post heuristic handling failed");
1268 reset(ctx);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07001269 return false;
1270 }
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001271 ALOGD_IF(sSimulationFlags,"%s: CACHE_MDP_COMP SUCCEEDED",
1272 __FUNCTION__);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07001273
Saurabh Shahaa236822013-04-24 18:07:26 -07001274 return true;
1275}
1276
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001277bool MDPComp::loadBasedComp(hwc_context_t *ctx,
Saurabh Shahb772ae32013-11-18 15:40:02 -08001278 hwc_display_contents_1_t* list) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001279 if(sSimulationFlags & MDPCOMP_AVOID_LOAD_MDP)
1280 return false;
1281
Arun Kumar K.R2aa44c62014-01-21 23:08:28 -08001282 if(not isLoadBasedCompDoable(ctx)) {
Saurabh Shahf2de00f2013-12-11 17:52:53 -08001283 return false;
1284 }
1285
Saurabh Shahb772ae32013-11-18 15:40:02 -08001286 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001287 const int numNonDroppedLayers = numAppLayers - mCurrentFrame.dropCount;
1288 const int stagesForMDP = min(sMaxPipesPerMixer,
1289 ctx->mOverlay->availablePipes(mDpy, Overlay::MIXER_DEFAULT));
Saurabh Shahf2de00f2013-12-11 17:52:53 -08001290
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001291 int mdpBatchSize = stagesForMDP - 1; //1 stage for FB
1292 int fbBatchSize = numNonDroppedLayers - mdpBatchSize;
1293 int lastMDPSupportedIndex = numAppLayers;
1294 int dropCount = 0;
Saurabh Shahb772ae32013-11-18 15:40:02 -08001295
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001296 //Find the minimum MDP batch size
1297 for(int i = 0; i < numAppLayers;i++) {
1298 if(mCurrentFrame.drop[i]) {
1299 dropCount++;
Jeykumar Sankaran846e2792014-01-23 21:59:58 -08001300 continue;
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001301 }
1302 hwc_layer_1_t* layer = &list->hwLayers[i];
1303 if(not isSupportedForMDPComp(ctx, layer)) {
1304 lastMDPSupportedIndex = i;
1305 mdpBatchSize = min(i - dropCount, stagesForMDP - 1);
1306 fbBatchSize = numNonDroppedLayers - mdpBatchSize;
Jeykumar Sankaran846e2792014-01-23 21:59:58 -08001307 break;
Saurabh Shahb772ae32013-11-18 15:40:02 -08001308 }
Saurabh Shahb772ae32013-11-18 15:40:02 -08001309 }
1310
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001311 ALOGD_IF(isDebug(), "%s:Before optimizing fbBatch, mdpbatch %d, fbbatch %d "
1312 "dropped %d", __FUNCTION__, mdpBatchSize, fbBatchSize,
1313 mCurrentFrame.dropCount);
1314
1315 //Start at a point where the fb batch should at least have 2 layers, for
1316 //this mode to be justified.
1317 while(fbBatchSize < 2) {
1318 ++fbBatchSize;
1319 --mdpBatchSize;
Jeykumar Sankaran846e2792014-01-23 21:59:58 -08001320 }
Saurabh Shahb772ae32013-11-18 15:40:02 -08001321
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001322 //If there are no layers for MDP, this mode doesnt make sense.
1323 if(mdpBatchSize < 1) {
1324 ALOGD_IF(isDebug(), "%s: No MDP layers after optimizing for fbBatch",
1325 __FUNCTION__);
Saurabh Shahb772ae32013-11-18 15:40:02 -08001326 return false;
1327 }
1328
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001329 mCurrentFrame.reset(numAppLayers);
1330
1331 //Try with successively smaller mdp batch sizes until we succeed or reach 1
1332 while(mdpBatchSize > 0) {
1333 //Mark layers for MDP comp
1334 int mdpBatchLeft = mdpBatchSize;
1335 for(int i = 0; i < lastMDPSupportedIndex and mdpBatchLeft; i++) {
1336 if(mCurrentFrame.drop[i]) {
1337 continue;
1338 }
1339 mCurrentFrame.isFBComposed[i] = false;
1340 --mdpBatchLeft;
1341 }
1342
1343 mCurrentFrame.fbZ = mdpBatchSize;
1344 mCurrentFrame.fbCount = fbBatchSize;
1345 mCurrentFrame.mdpCount = mdpBatchSize;
1346
1347 ALOGD_IF(isDebug(), "%s:Trying with: mdpbatch %d fbbatch %d dropped %d",
1348 __FUNCTION__, mdpBatchSize, fbBatchSize,
1349 mCurrentFrame.dropCount);
1350
1351 if(postHeuristicsHandling(ctx, list)) {
1352 ALOGD_IF(isDebug(), "%s: Postheuristics handling succeeded",
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001353 __FUNCTION__);
1354 ALOGD_IF(sSimulationFlags,"%s: LOAD_MDP_COMP SUCCEEDED",
1355 __FUNCTION__);
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001356 return true;
1357 }
1358
1359 reset(ctx);
1360 --mdpBatchSize;
1361 ++fbBatchSize;
1362 }
1363
1364 return false;
Saurabh Shahb772ae32013-11-18 15:40:02 -08001365}
1366
Arun Kumar K.R2aa44c62014-01-21 23:08:28 -08001367bool MDPComp::isLoadBasedCompDoable(hwc_context_t *ctx) {
Prabhanjan Kandula3dbbd882013-12-11 14:43:46 +05301368 if(mDpy or isSecurePresent(ctx, mDpy) or
1369 isYuvPresent(ctx, mDpy)) {
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001370 return false;
1371 }
1372 return true;
1373}
1374
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001375bool MDPComp::canPartialUpdate(hwc_context_t *ctx,
1376 hwc_display_contents_1_t* list){
1377 if(!qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() ||
1378 isSkipPresent(ctx, mDpy) || (list->flags & HWC_GEOMETRY_CHANGED) ||
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001379 isCursorPresent(ctx, mDpy) || !sIsPartialUpdateActive || mDpy) {
1380 // On Async position update, the ROI becomes invalid, hence disable PU
1381 // when cursor is present
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001382 return false;
1383 }
Jeykumar Sankaran4dd10ab2014-07-02 12:23:09 -07001384 if(ctx->listStats[mDpy].secureUI)
1385 return false;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001386 return true;
1387}
1388
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001389bool MDPComp::tryVideoOnly(hwc_context_t *ctx,
1390 hwc_display_contents_1_t* list) {
1391 const bool secureOnly = true;
1392 return videoOnlyComp(ctx, list, not secureOnly) or
1393 videoOnlyComp(ctx, list, secureOnly);
1394}
1395
1396bool MDPComp::videoOnlyComp(hwc_context_t *ctx,
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001397 hwc_display_contents_1_t* list, bool secureOnly) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001398 if(sSimulationFlags & MDPCOMP_AVOID_VIDEO_ONLY)
1399 return false;
Praveena Pachipulusu47346c22014-12-04 11:06:41 +05301400
Saurabh Shahaa236822013-04-24 18:07:26 -07001401 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Praveena Pachipulusu47346c22014-12-04 11:06:41 +05301402 if(!isSecurePresent(ctx, mDpy)) {
1403 /* Bail out if we are processing only secured video layers
1404 * and we dont have any */
1405 if(secureOnly) {
1406 ALOGD_IF(isDebug(),"%s: No Secure Video Layers", __FUNCTION__);
1407 return false;
1408 }
1409 /* No Idle fall back for secure video layers and if there is only
1410 * single layer being composed. */
1411 if(sIdleFallBack && (ctx->listStats[mDpy].numAppLayers > 1)) {
1412 ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
1413 return false;
1414 }
1415 }
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001416
Saurabh Shahaa236822013-04-24 18:07:26 -07001417 mCurrentFrame.reset(numAppLayers);
Jeykumar Sankaraneb3a5e22014-04-08 16:07:55 -07001418 mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001419 updateYUV(ctx, list, secureOnly, mCurrentFrame);
Saurabh Shah4fdde762013-04-30 18:47:33 -07001420 int mdpCount = mCurrentFrame.mdpCount;
Saurabh Shahaa236822013-04-24 18:07:26 -07001421
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001422 if(!isYuvPresent(ctx, mDpy) or (mdpCount == 0)) {
1423 reset(ctx);
Saurabh Shahaa236822013-04-24 18:07:26 -07001424 return false;
1425 }
1426
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001427 if(mCurrentFrame.fbCount)
1428 mCurrentFrame.fbZ = mCurrentFrame.mdpCount;
Saurabh Shah4fdde762013-04-30 18:47:33 -07001429
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05001430 if(sEnableYUVsplit || needs3DComposition(ctx, mDpy)){
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001431 adjustForSourceSplit(ctx, list);
1432 }
1433
1434 if(!postHeuristicsHandling(ctx, list)) {
1435 ALOGD_IF(isDebug(), "post heuristic handling failed");
Justin Philip37ab9a82015-01-06 11:55:12 +05301436 if(errno == ENOBUFS) {
1437 ALOGD_IF(isDebug(), "SMP Allocation failed");
1438 //On SMP allocation failure in video only comp add padding round
1439 ctx->isPaddingRound = true;
1440 }
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001441 reset(ctx);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07001442 return false;
1443 }
1444
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001445 ALOGD_IF(sSimulationFlags,"%s: VIDEO_ONLY_COMP SUCCEEDED",
1446 __FUNCTION__);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001447 return true;
1448}
1449
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001450/* if tryFullFrame fails, try to push all video and secure RGB layers to MDP */
1451bool MDPComp::tryMDPOnlyLayers(hwc_context_t *ctx,
1452 hwc_display_contents_1_t* list) {
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001453 // Fall back to video only composition, if AIV video mode is enabled
1454 if(ctx->listStats[mDpy].mAIVVideoMode) {
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07001455 ALOGD_IF(isDebug(), "%s: AIV Video Mode enabled dpy %d",
1456 __FUNCTION__, mDpy);
1457 return false;
1458 }
1459
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05001460 // No MDP composition for 3D
1461 if(needs3DComposition(ctx,mDpy))
1462 return false;
1463
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001464 const bool secureOnly = true;
1465 return mdpOnlyLayersComp(ctx, list, not secureOnly) or
1466 mdpOnlyLayersComp(ctx, list, secureOnly);
1467
1468}
1469
1470bool MDPComp::mdpOnlyLayersComp(hwc_context_t *ctx,
1471 hwc_display_contents_1_t* list, bool secureOnly) {
1472
1473 if(sSimulationFlags & MDPCOMP_AVOID_MDP_ONLY_LAYERS)
1474 return false;
1475
Praveena Pachipulusu47346c22014-12-04 11:06:41 +05301476 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
1477 if(!isSecurePresent(ctx, mDpy) && !ctx->listStats[mDpy].secureUI) {
1478 /* Bail out if we are processing only secured video/ui layers
1479 * and we dont have any */
1480 if(secureOnly) {
1481 ALOGD_IF(isDebug(), "%s: No secure video/ui layers");
1482 return false;
1483 }
1484 /* No Idle fall back for secure video/ui layers and if there is only
1485 * single layer being composed. */
1486 if(sIdleFallBack && (ctx->listStats[mDpy].numAppLayers > 1)) {
1487 ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
1488 return false;
1489 }
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001490 }
1491
Tatenda Chipeperekwa95675a72014-12-15 17:06:43 -08001492 /* Bail out if we dont have any secure RGB layers */
1493 if (!ctx->listStats[mDpy].secureRGBCount) {
1494 reset(ctx);
1495 return false;
1496 }
1497
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001498 mCurrentFrame.reset(numAppLayers);
1499 mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
1500
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001501 updateYUV(ctx, list, secureOnly, mCurrentFrame);
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001502 /* mark secure RGB layers for MDP comp */
1503 updateSecureRGB(ctx, list);
1504
1505 if(mCurrentFrame.mdpCount == 0) {
1506 reset(ctx);
1507 return false;
1508 }
1509
1510 /* find the maximum batch of layers to be marked for framebuffer */
1511 bool ret = markLayersForCaching(ctx, list); //sets up fbZ also
1512 if(!ret) {
1513 ALOGD_IF(isDebug(),"%s: batching failed, dpy %d",__FUNCTION__, mDpy);
1514 reset(ctx);
1515 return false;
1516 }
1517
1518 if(sEnableYUVsplit){
1519 adjustForSourceSplit(ctx, list);
1520 }
1521
1522 if(!postHeuristicsHandling(ctx, list)) {
1523 ALOGD_IF(isDebug(), "post heuristic handling failed");
1524 reset(ctx);
1525 return false;
1526 }
1527
1528 ALOGD_IF(sSimulationFlags,"%s: MDP_ONLY_LAYERS_COMP SUCCEEDED",
1529 __FUNCTION__);
1530 return true;
1531}
1532
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001533/* Checks for conditions where YUV layers cannot be bypassed */
1534bool MDPComp::isYUVDoable(hwc_context_t* ctx, hwc_layer_1_t* layer) {
Ramkumar Radhakrishnana70981a2013-08-28 11:33:53 -07001535 if(isSkipLayer(layer)) {
Saurabh Shahe2474082013-05-15 16:32:13 -07001536 ALOGD_IF(isDebug(), "%s: Video marked SKIP dpy %d", __FUNCTION__, mDpy);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001537 return false;
1538 }
1539
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08001540 if(has90Transform(layer) && !canUseRotator(ctx, mDpy)) {
Amara Venkata Mastan Manoj Kumar9d373c02013-08-20 14:30:09 -07001541 ALOGD_IF(isDebug(), "%s: no free DMA pipe",__FUNCTION__);
1542 return false;
1543 }
1544
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001545 if(isSecuring(ctx, layer)) {
1546 ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
1547 return false;
1548 }
1549
Saurabh Shah4fdde762013-04-30 18:47:33 -07001550 if(!isValidDimension(ctx, layer)) {
1551 ALOGD_IF(isDebug(), "%s: Buffer is of invalid width",
1552 __FUNCTION__);
1553 return false;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001554 }
Saurabh Shah4fdde762013-04-30 18:47:33 -07001555
Naseer Ahmeddc61a972013-07-10 17:50:54 -04001556 if(layer->planeAlpha < 0xFF) {
1557 ALOGD_IF(isDebug(), "%s: Cannot handle YUV layer with plane alpha\
1558 in video only mode",
1559 __FUNCTION__);
1560 return false;
1561 }
1562
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001563 return true;
1564}
1565
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001566/* Checks for conditions where Secure RGB layers cannot be bypassed */
1567bool MDPComp::isSecureRGBDoable(hwc_context_t* ctx, hwc_layer_1_t* layer) {
1568 if(isSkipLayer(layer)) {
1569 ALOGD_IF(isDebug(), "%s: Secure RGB layer marked SKIP dpy %d",
1570 __FUNCTION__, mDpy);
1571 return false;
1572 }
1573
1574 if(isSecuring(ctx, layer)) {
1575 ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
1576 return false;
1577 }
1578
1579 if(not isSupportedForMDPComp(ctx, layer)) {
1580 ALOGD_IF(isDebug(), "%s: Unsupported secure RGB layer",
1581 __FUNCTION__);
1582 return false;
1583 }
1584 return true;
1585}
1586
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301587/* starts at fromIndex and check for each layer to find
1588 * if it it has overlapping with any Updating layer above it in zorder
1589 * till the end of the batch. returns true if it finds any intersection */
1590bool MDPComp::canPushBatchToTop(const hwc_display_contents_1_t* list,
1591 int fromIndex, int toIndex) {
1592 for(int i = fromIndex; i < toIndex; i++) {
1593 if(mCurrentFrame.isFBComposed[i] && !mCurrentFrame.drop[i]) {
1594 if(intersectingUpdatingLayers(list, i+1, toIndex, i)) {
1595 return false;
1596 }
1597 }
1598 }
1599 return true;
1600}
1601
1602/* Checks if given layer at targetLayerIndex has any
1603 * intersection with all the updating layers in beween
1604 * fromIndex and toIndex. Returns true if it finds intersectiion */
1605bool MDPComp::intersectingUpdatingLayers(const hwc_display_contents_1_t* list,
1606 int fromIndex, int toIndex, int targetLayerIndex) {
1607 for(int i = fromIndex; i <= toIndex; i++) {
1608 if(!mCurrentFrame.isFBComposed[i]) {
1609 if(areLayersIntersecting(&list->hwLayers[i],
1610 &list->hwLayers[targetLayerIndex])) {
1611 return true;
1612 }
1613 }
1614 }
1615 return false;
1616}
1617
1618int MDPComp::getBatch(hwc_display_contents_1_t* list,
1619 int& maxBatchStart, int& maxBatchEnd,
1620 int& maxBatchCount) {
1621 int i = 0;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301622 int fbZOrder =-1;
Jeykumar Sankaran9502f352014-01-20 12:25:32 -08001623 int droppedLayerCt = 0;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301624 while (i < mCurrentFrame.layerCount) {
1625 int batchCount = 0;
1626 int batchStart = i;
1627 int batchEnd = i;
Jeykumar Sankaran9502f352014-01-20 12:25:32 -08001628 /* Adjust batch Z order with the dropped layers so far */
1629 int fbZ = batchStart - droppedLayerCt;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301630 int firstZReverseIndex = -1;
Prabhanjan Kandula0ed2cc92013-12-06 12:39:04 +05301631 int updatingLayersAbove = 0;//Updating layer count in middle of batch
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301632 while(i < mCurrentFrame.layerCount) {
1633 if(!mCurrentFrame.isFBComposed[i]) {
1634 if(!batchCount) {
1635 i++;
1636 break;
1637 }
1638 updatingLayersAbove++;
1639 i++;
1640 continue;
1641 } else {
1642 if(mCurrentFrame.drop[i]) {
1643 i++;
Jeykumar Sankaran9502f352014-01-20 12:25:32 -08001644 droppedLayerCt++;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301645 continue;
1646 } else if(updatingLayersAbove <= 0) {
1647 batchCount++;
1648 batchEnd = i;
1649 i++;
1650 continue;
1651 } else { //Layer is FBComposed, not a drop & updatingLayer > 0
1652
1653 // We have a valid updating layer already. If layer-i not
1654 // have overlapping with all updating layers in between
1655 // batch-start and i, then we can add layer i to batch.
1656 if(!intersectingUpdatingLayers(list, batchStart, i-1, i)) {
1657 batchCount++;
1658 batchEnd = i;
1659 i++;
1660 continue;
1661 } else if(canPushBatchToTop(list, batchStart, i)) {
1662 //If All the non-updating layers with in this batch
1663 //does not have intersection with the updating layers
1664 //above in z-order, then we can safely move the batch to
1665 //higher z-order. Increment fbZ as it is moving up.
1666 if( firstZReverseIndex < 0) {
1667 firstZReverseIndex = i;
1668 }
1669 batchCount++;
1670 batchEnd = i;
1671 fbZ += updatingLayersAbove;
1672 i++;
1673 updatingLayersAbove = 0;
1674 continue;
1675 } else {
1676 //both failed.start the loop again from here.
1677 if(firstZReverseIndex >= 0) {
1678 i = firstZReverseIndex;
1679 }
1680 break;
1681 }
1682 }
1683 }
1684 }
1685 if(batchCount > maxBatchCount) {
1686 maxBatchCount = batchCount;
1687 maxBatchStart = batchStart;
1688 maxBatchEnd = batchEnd;
1689 fbZOrder = fbZ;
1690 }
1691 }
1692 return fbZOrder;
1693}
1694
1695bool MDPComp::markLayersForCaching(hwc_context_t* ctx,
1696 hwc_display_contents_1_t* list) {
1697 /* Idea is to keep as many non-updating(cached) layers in FB and
1698 * send rest of them through MDP. This is done in 2 steps.
1699 * 1. Find the maximum contiguous batch of non-updating layers.
1700 * 2. See if we can improve this batch size for caching by adding
1701 * opaque layers around the batch, if they don't have
1702 * any overlapping with the updating layers in between.
1703 * NEVER mark an updating layer for caching.
1704 * But cached ones can be marked for MDP */
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001705
1706 int maxBatchStart = -1;
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001707 int maxBatchEnd = -1;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001708 int maxBatchCount = 0;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301709 int fbZ = -1;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001710
Saurabh Shahd53bc5f2014-02-05 10:17:43 -08001711 /* Nothing is cached. No batching needed */
1712 if(mCurrentFrame.fbCount == 0) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001713 return true;
Saurabh Shahaa236822013-04-24 18:07:26 -07001714 }
Saurabh Shahd53bc5f2014-02-05 10:17:43 -08001715
1716 /* No MDP comp layers, try to use other comp modes */
1717 if(mCurrentFrame.mdpCount == 0) {
1718 return false;
Saurabh Shahaa236822013-04-24 18:07:26 -07001719 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001720
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301721 fbZ = getBatch(list, maxBatchStart, maxBatchEnd, maxBatchCount);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001722
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301723 /* reset rest of the layers lying inside ROI for MDP comp */
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001724 for(int i = 0; i < mCurrentFrame.layerCount; i++) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001725 hwc_layer_1_t* layer = &list->hwLayers[i];
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001726 if((i < maxBatchStart || i > maxBatchEnd) &&
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301727 mCurrentFrame.isFBComposed[i]){
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001728 if(!mCurrentFrame.drop[i]){
1729 //If an unsupported layer is being attempted to
1730 //be pulled out we should fail
1731 if(not isSupportedForMDPComp(ctx, layer)) {
1732 return false;
1733 }
1734 mCurrentFrame.isFBComposed[i] = false;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001735 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001736 }
1737 }
1738
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301739 // update the frame data
1740 mCurrentFrame.fbZ = fbZ;
1741 mCurrentFrame.fbCount = maxBatchCount;
Saurabh Shahaa236822013-04-24 18:07:26 -07001742 mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001743 mCurrentFrame.fbCount - mCurrentFrame.dropCount;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001744
1745 ALOGD_IF(isDebug(),"%s: cached count: %d",__FUNCTION__,
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301746 mCurrentFrame.fbCount);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001747
1748 return true;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001749}
Saurabh Shah85234ec2013-04-12 17:09:00 -07001750
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001751void MDPComp::updateLayerCache(hwc_context_t* ctx,
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001752 hwc_display_contents_1_t* list, FrameInfo& frame) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001753 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001754 int fbCount = 0;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001755
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001756 for(int i = 0; i < numAppLayers; i++) {
1757 if (mCachedFrame.hnd[i] == list->hwLayers[i].handle) {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001758 if(!frame.drop[i])
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001759 fbCount++;
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001760 frame.isFBComposed[i] = true;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001761 } else {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001762 frame.isFBComposed[i] = false;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001763 }
1764 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001765
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001766 frame.fbCount = fbCount;
1767 frame.mdpCount = frame.layerCount - frame.fbCount
1768 - frame.dropCount;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001769
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001770 ALOGD_IF(isDebug(),"%s: MDP count: %d FB count %d drop count: %d",
1771 __FUNCTION__, frame.mdpCount, frame.fbCount, frame.dropCount);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001772}
1773
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001774// drop other non-AIV layers from external display list.
1775void MDPComp::dropNonAIVLayers(hwc_context_t* ctx,
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07001776 hwc_display_contents_1_t* list) {
1777 for (size_t i = 0; i < (size_t)ctx->listStats[mDpy].numAppLayers; i++) {
1778 hwc_layer_1_t * layer = &list->hwLayers[i];
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001779 if(!(isAIVVideoLayer(layer) || isAIVCCLayer(layer))) {
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07001780 mCurrentFrame.dropCount++;
1781 mCurrentFrame.drop[i] = true;
1782 }
1783 }
1784 mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
1785 mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
1786 mCurrentFrame.fbCount - mCurrentFrame.dropCount;
1787 ALOGD_IF(isDebug(),"%s: fb count: %d mdp count %d drop count %d",
1788 __FUNCTION__, mCurrentFrame.fbCount, mCurrentFrame.mdpCount,
1789 mCurrentFrame.dropCount);
1790}
1791
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001792void MDPComp::updateYUV(hwc_context_t* ctx, hwc_display_contents_1_t* list,
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001793 bool secureOnly, FrameInfo& frame) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001794 int nYuvCount = ctx->listStats[mDpy].yuvCount;
1795 for(int index = 0;index < nYuvCount; index++){
1796 int nYuvIndex = ctx->listStats[mDpy].yuvIndices[index];
1797 hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
1798
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001799 if(mCurrentFrame.drop[nYuvIndex]) {
1800 continue;
1801 }
1802
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001803 if(!isYUVDoable(ctx, layer)) {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001804 if(!frame.isFBComposed[nYuvIndex]) {
1805 frame.isFBComposed[nYuvIndex] = true;
1806 frame.fbCount++;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001807 }
1808 } else {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001809 if(frame.isFBComposed[nYuvIndex]) {
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001810 private_handle_t *hnd = (private_handle_t *)layer->handle;
1811 if(!secureOnly || isSecureBuffer(hnd)) {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001812 frame.isFBComposed[nYuvIndex] = false;
1813 frame.fbCount--;
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001814 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001815 }
1816 }
1817 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001818
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001819 frame.mdpCount = frame.layerCount - frame.fbCount - frame.dropCount;
1820 ALOGD_IF(isDebug(),"%s: fb count: %d",__FUNCTION__, frame.fbCount);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001821}
1822
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001823void MDPComp::updateSecureRGB(hwc_context_t* ctx,
1824 hwc_display_contents_1_t* list) {
1825 int nSecureRGBCount = ctx->listStats[mDpy].secureRGBCount;
1826 for(int index = 0;index < nSecureRGBCount; index++){
1827 int nSecureRGBIndex = ctx->listStats[mDpy].secureRGBIndices[index];
1828 hwc_layer_1_t* layer = &list->hwLayers[nSecureRGBIndex];
1829
1830 if(!isSecureRGBDoable(ctx, layer)) {
1831 if(!mCurrentFrame.isFBComposed[nSecureRGBIndex]) {
1832 mCurrentFrame.isFBComposed[nSecureRGBIndex] = true;
1833 mCurrentFrame.fbCount++;
1834 }
1835 } else {
1836 if(mCurrentFrame.isFBComposed[nSecureRGBIndex]) {
1837 mCurrentFrame.isFBComposed[nSecureRGBIndex] = false;
1838 mCurrentFrame.fbCount--;
1839 }
1840 }
1841 }
1842
1843 mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
1844 mCurrentFrame.fbCount - mCurrentFrame.dropCount;
1845 ALOGD_IF(isDebug(),"%s: fb count: %d",__FUNCTION__,
1846 mCurrentFrame.fbCount);
1847}
1848
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001849hwc_rect_t MDPComp::getUpdatingFBRect(hwc_context_t *ctx,
1850 hwc_display_contents_1_t* list){
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001851 hwc_rect_t fbRect = (struct hwc_rect){0, 0, 0, 0};
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001852
1853 /* Update only the region of FB needed for composition */
1854 for(int i = 0; i < mCurrentFrame.layerCount; i++ ) {
1855 if(mCurrentFrame.isFBComposed[i] && !mCurrentFrame.drop[i]) {
1856 hwc_layer_1_t* layer = &list->hwLayers[i];
1857 hwc_rect_t dst = layer->displayFrame;
1858 fbRect = getUnion(fbRect, dst);
1859 }
1860 }
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08001861 trimAgainstROI(ctx, fbRect, fbRect);
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001862 return fbRect;
1863}
1864
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001865bool MDPComp::postHeuristicsHandling(hwc_context_t *ctx,
1866 hwc_display_contents_1_t* list) {
1867
1868 //Capability checks
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08001869 if(!resourceCheck(ctx, list)) {
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001870 ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
1871 return false;
1872 }
1873
1874 //Limitations checks
1875 if(!hwLimitationsCheck(ctx, list)) {
1876 ALOGD_IF(isDebug(), "%s: HW limitations",__FUNCTION__);
1877 return false;
1878 }
1879
Saurabh Shah3d4b8042013-12-10 15:19:17 -08001880 //Configure framebuffer first if applicable
1881 if(mCurrentFrame.fbZ >= 0) {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001882 hwc_rect_t fbRect = getUpdatingFBRect(ctx, list);
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001883 if(!ctx->mFBUpdate[mDpy]->prepare(ctx, list, fbRect, mCurrentFrame.fbZ))
1884 {
Saurabh Shah3d4b8042013-12-10 15:19:17 -08001885 ALOGD_IF(isDebug(), "%s configure framebuffer failed",
1886 __FUNCTION__);
1887 return false;
1888 }
1889 }
1890
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001891 mCurrentFrame.map();
1892
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001893 if(!allocLayerPipes(ctx, list)) {
1894 ALOGD_IF(isDebug(), "%s: Unable to allocate MDP pipes", __FUNCTION__);
Saurabh Shahaa236822013-04-24 18:07:26 -07001895 return false;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001896 }
1897
1898 for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
Saurabh Shahaa236822013-04-24 18:07:26 -07001899 index++) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001900 if(!mCurrentFrame.isFBComposed[index]) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001901 int mdpIndex = mCurrentFrame.layerToMDP[index];
1902 hwc_layer_1_t* layer = &list->hwLayers[index];
1903
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301904 //Leave fbZ for framebuffer. CACHE/GLES layers go here.
1905 if(mdpNextZOrder == mCurrentFrame.fbZ) {
1906 mdpNextZOrder++;
1907 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001908 MdpPipeInfo* cur_pipe = mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
1909 cur_pipe->zOrder = mdpNextZOrder++;
1910
radhakrishnac9a67412013-09-25 17:40:42 +05301911 private_handle_t *hnd = (private_handle_t *)layer->handle;
Raj Kamal389d6e32014-08-04 14:43:24 +05301912 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
radhakrishnac9a67412013-09-25 17:40:42 +05301913 if(configure4k2kYuv(ctx, layer,
1914 mCurrentFrame.mdpToLayer[mdpIndex])
1915 != 0 ){
1916 ALOGD_IF(isDebug(), "%s: Failed to configure split pipes \
1917 for layer %d",__FUNCTION__, index);
1918 return false;
1919 }
1920 else{
1921 mdpNextZOrder++;
1922 }
1923 continue;
1924 }
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05001925 if(needs3DComposition(ctx,mDpy) && get3DFormat(hnd) != HAL_NO_3D) {
1926 mdpNextZOrder++;
1927 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001928 if(configure(ctx, layer, mCurrentFrame.mdpToLayer[mdpIndex]) != 0 ){
1929 ALOGD_IF(isDebug(), "%s: Failed to configure overlay for \
radhakrishnac9a67412013-09-25 17:40:42 +05301930 layer %d",__FUNCTION__, index);
Saurabh Shahaa236822013-04-24 18:07:26 -07001931 return false;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001932 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001933 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001934 }
1935
Saurabh Shaha36be922013-12-16 18:18:39 -08001936 if(!ctx->mOverlay->validateAndSet(mDpy, ctx->dpyAttr[mDpy].fd)) {
1937 ALOGD_IF(isDebug(), "%s: Failed to validate and set overlay for dpy %d"
1938 ,__FUNCTION__, mDpy);
1939 return false;
1940 }
1941
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001942 setRedraw(ctx, list);
Saurabh Shahaa236822013-04-24 18:07:26 -07001943 return true;
1944}
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001945
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08001946bool MDPComp::resourceCheck(hwc_context_t* ctx,
1947 hwc_display_contents_1_t* list) {
Saurabh Shah173f4242013-11-20 09:50:12 -08001948 const bool fbUsed = mCurrentFrame.fbCount;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001949 int cursorInUse = 0;
1950 if(mDpy == HWC_DISPLAY_PRIMARY) {
1951 // check if cursor is in use for primary
1952 cursorInUse = HWCursor::getInstance()->isCursorSet();
1953 }
1954 int maxStages = qdutils::MDPVersion::getInstance().getBlendStages();
1955 // HW Cursor needs one blending stage, account for that in the check below
1956 // On high end targets(8994) has 8 blending stages, HAL is configured to use < 8.
1957 // Make use of the remaining stages for HW Cursor so that the composition
1958 // strategy would not fail due to this limitation.
1959 if (maxStages > sMaxPipesPerMixer) {
1960 cursorInUse = 0;
1961 }
1962 if(mCurrentFrame.mdpCount > (sMaxPipesPerMixer - fbUsed - cursorInUse)) {
Saurabh Shah173f4242013-11-20 09:50:12 -08001963 ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
1964 return false;
1965 }
Saurabh Shahacec8e42014-11-25 11:07:04 -08001966
1967 //Will benefit cases where a video has non-updating background.
1968 if((mDpy > HWC_DISPLAY_PRIMARY) and
1969 (mCurrentFrame.mdpCount > sMaxSecLayers)) {
1970 ALOGD_IF(isDebug(), "%s: Exceeds max secondary pipes",__FUNCTION__);
1971 return false;
1972 }
1973
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08001974 // Init rotCount to number of rotate sessions used by other displays
1975 int rotCount = ctx->mRotMgr->getNumActiveSessions();
1976 // Count the number of rotator sessions required for current display
1977 for (int index = 0; index < mCurrentFrame.layerCount; index++) {
1978 if(!mCurrentFrame.isFBComposed[index]) {
1979 hwc_layer_1_t* layer = &list->hwLayers[index];
1980 private_handle_t *hnd = (private_handle_t *)layer->handle;
1981 if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
1982 rotCount++;
1983 }
1984 }
1985 }
1986 // if number of layers to rotate exceeds max rotator sessions, bail out.
1987 if(rotCount > RotMgr::MAX_ROT_SESS) {
1988 ALOGD_IF(isDebug(), "%s: Exceeds max rotator sessions %d",
1989 __FUNCTION__, mDpy);
1990 return false;
1991 }
Saurabh Shah173f4242013-11-20 09:50:12 -08001992 return true;
1993}
1994
Prabhanjan Kandula21918db2013-11-26 15:51:58 +05301995bool MDPComp::hwLimitationsCheck(hwc_context_t* ctx,
1996 hwc_display_contents_1_t* list) {
1997
1998 //A-family hw limitation:
1999 //If a layer need alpha scaling, MDP can not support.
2000 if(ctx->mMDP.version < qdutils::MDSS_V5) {
2001 for(int i = 0; i < mCurrentFrame.layerCount; ++i) {
2002 if(!mCurrentFrame.isFBComposed[i] &&
2003 isAlphaScaled( &list->hwLayers[i])) {
2004 ALOGD_IF(isDebug(), "%s:frame needs alphaScaling",__FUNCTION__);
2005 return false;
2006 }
2007 }
2008 }
2009
2010 // On 8x26 & 8974 hw, we have a limitation of downscaling+blending.
2011 //If multiple layers requires downscaling and also they are overlapping
2012 //fall back to GPU since MDSS can not handle it.
2013 if(qdutils::MDPVersion::getInstance().is8x74v2() ||
2014 qdutils::MDPVersion::getInstance().is8x26()) {
2015 for(int i = 0; i < mCurrentFrame.layerCount-1; ++i) {
2016 hwc_layer_1_t* botLayer = &list->hwLayers[i];
2017 if(!mCurrentFrame.isFBComposed[i] &&
2018 isDownscaleRequired(botLayer)) {
2019 //if layer-i is marked for MDP and needs downscaling
2020 //check if any MDP layer on top of i & overlaps with layer-i
2021 for(int j = i+1; j < mCurrentFrame.layerCount; ++j) {
2022 hwc_layer_1_t* topLayer = &list->hwLayers[j];
2023 if(!mCurrentFrame.isFBComposed[j] &&
2024 isDownscaleRequired(topLayer)) {
2025 hwc_rect_t r = getIntersection(botLayer->displayFrame,
2026 topLayer->displayFrame);
2027 if(isValidRect(r))
2028 return false;
2029 }
2030 }
2031 }
2032 }
2033 }
2034 return true;
2035}
2036
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002037static bool validForCursor(hwc_context_t* ctx, int dpy, hwc_layer_1_t* layer) {
2038 private_handle_t *hnd = (private_handle_t *)layer->handle;
2039 hwc_rect dst = layer->displayFrame;
2040 hwc_rect src = integerizeSourceCrop(layer->sourceCropf);
2041 int srcW = src.right - src.left;
2042 int srcH = src.bottom - src.top;
2043 int dstW = dst.right - dst.left;
2044 int dstH = dst.bottom - dst.top;
2045 qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
2046 uint32_t maxCursorSize = mdpVersion.getMaxCursorSize();
2047 uint32_t numHwCursors = mdpVersion.getCursorPipes();
2048 bool primarySplit = isDisplaySplit(ctx, HWC_DISPLAY_PRIMARY);
2049 uint32_t cursorPipesNeeded = 1; // One cursor pipe needed(default)
2050 bool ret = false;
2051
2052 if(dpy > HWC_DISPLAY_PRIMARY) {
2053 // Cursor not supported on secondary displays, as it involves scaling
2054 // in most of the cases
2055 return false;
2056 } else if (isSkipLayer(layer)) {
2057 return false;
2058 // Checks for HW limitation
2059 } else if (numHwCursors == 0 || maxCursorSize <= 0) {
2060 return false;
2061 } else if (needsScaling(layer)) {
2062 return false;
2063 } else if (layer->transform != 0) {
2064 return false;
2065 } else if (hnd->format != HAL_PIXEL_FORMAT_RGBA_8888) {
2066 return false;
2067 } else if (srcW > (int)maxCursorSize || srcH > (int)maxCursorSize) {
2068 return false;
2069 }
2070
2071 if (isDisplaySplit(ctx, dpy) && !mdpVersion.isSrcSplit()) {
2072 // In case of split display with no srcSplit, the driver allocates two
2073 // pipes to support async position update across mixers, hence
2074 // need to account for that here.
2075 cursorPipesNeeded = 2;
2076 }
2077 if (cursorPipesNeeded <= numHwCursors) {
2078 ret = true;
2079 }
2080 return ret;
2081}
2082
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08002083// Checks only if videos or single layer(RGB) is updating
2084// which is used for setting dynamic fps or perf hint for single
2085// layer video playback
2086bool MDPComp::onlyVideosUpdating(hwc_context_t *ctx,
2087 hwc_display_contents_1_t* list) {
2088 bool support = false;
2089 FrameInfo frame;
2090 frame.reset(mCurrentFrame.layerCount);
2091 memset(&frame.drop, 0, sizeof(frame.drop));
2092 frame.dropCount = 0;
2093 ALOGD_IF(isDebug(), "%s: Update Cache and YUVInfo", __FUNCTION__);
2094 updateLayerCache(ctx, list, frame);
2095 updateYUV(ctx, list, false /*secure only*/, frame);
2096 // There are only updating YUV layers or there is single RGB
2097 // Layer(Youtube)
2098 if((ctx->listStats[mDpy].yuvCount == frame.mdpCount) ||
2099 (frame.layerCount == 1)) {
2100 support = true;
2101 }
2102 return support;
2103}
2104
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302105void MDPComp::setDynRefreshRate(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
2106 //For primary display, set the dynamic refreshrate
2107 if(!mDpy && qdutils::MDPVersion::getInstance().isDynFpsSupported() &&
2108 ctx->mUseMetaDataRefreshRate) {
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302109 uint32_t refreshRate = ctx->dpyAttr[mDpy].refreshRate;
2110 MDPVersion& mdpHw = MDPVersion::getInstance();
2111 if(sIdleFallBack) {
2112 //Set minimum panel refresh rate during idle timeout
2113 refreshRate = mdpHw.getMinFpsSupported();
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08002114 } else if(onlyVideosUpdating(ctx, list)) {
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302115 //Set the new fresh rate, if there is only one updating YUV layer
2116 //or there is one single RGB layer with this request
2117 refreshRate = ctx->listStats[mDpy].refreshRateRequest;
2118 }
2119 setRefreshRate(ctx, mDpy, refreshRate);
2120 }
2121}
2122
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002123int MDPComp::prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002124 int ret = 0;
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07002125 char property[PROPERTY_VALUE_MAX];
2126
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002127 if(!list) {
2128 ALOGE("%s: Invalid list", __FUNCTION__);
Raj Kamal4393eaa2014-06-06 13:45:20 +05302129 mCachedFrame.reset();
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002130 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Raj Kamal4393eaa2014-06-06 13:45:20 +05302131 return -1;
2132 }
2133
2134 const int numLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shah286cf122014-09-08 14:13:08 -07002135 if(mDpy == HWC_DISPLAY_PRIMARY) {
2136 sSimulationFlags = 0;
2137 if(property_get("debug.hwc.simulate", property, NULL) > 0) {
2138 int currentFlags = atoi(property);
2139 if(currentFlags != sSimulationFlags) {
2140 sSimulationFlags = currentFlags;
2141 ALOGI("%s: Simulation Flag read: 0x%x (%d)", __FUNCTION__,
2142 sSimulationFlags, sSimulationFlags);
2143 }
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07002144 }
2145 }
Ramkumar Radhakrishnanc5893f12013-06-06 19:43:53 -07002146
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302147 //reset old data
2148 mCurrentFrame.reset(numLayers);
2149 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
2150 mCurrentFrame.dropCount = 0;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002151 mCurrentFrame.hwCursorIndex = -1;
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302152
Raj Kamal9ed3d6b2014-02-07 16:15:17 +05302153 //Do not cache the information for next draw cycle.
2154 if(numLayers > MAX_NUM_APP_LAYERS or (!numLayers)) {
2155 ALOGI("%s: Unsupported layer count for mdp composition",
2156 __FUNCTION__);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002157 mCachedFrame.reset();
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302158#ifdef DYNAMIC_FPS
2159 setDynRefreshRate(ctx, list);
2160#endif
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002161 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002162 return -1;
2163 }
2164
Ramkumar Radhakrishnana70981a2013-08-28 11:33:53 -07002165 // Detect the start of animation and fall back to GPU only once to cache
2166 // all the layers in FB and display FB content untill animation completes.
2167 if(ctx->listStats[mDpy].isDisplayAnimating) {
2168 mCurrentFrame.needsRedraw = false;
2169 if(ctx->mAnimationState[mDpy] == ANIMATION_STOPPED) {
2170 mCurrentFrame.needsRedraw = true;
2171 ctx->mAnimationState[mDpy] = ANIMATION_STARTED;
2172 }
2173 setMDPCompLayerFlags(ctx, list);
2174 mCachedFrame.updateCounts(mCurrentFrame);
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302175#ifdef DYNAMIC_FPS
2176 setDynRefreshRate(ctx, list);
2177#endif
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002178 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Ramkumar Radhakrishnana70981a2013-08-28 11:33:53 -07002179 ret = -1;
2180 return ret;
2181 } else {
2182 ctx->mAnimationState[mDpy] = ANIMATION_STOPPED;
2183 }
2184
Raj Kamalfdfdddf2015-03-16 21:59:25 +05302185 if(!mDpy and !isSecondaryConnected(ctx) and !mPrevModeOn and
2186 mCachedFrame.isSameFrame(ctx,mDpy,list)) {
2187
2188 ALOGD_IF(isDebug(),"%s: Avoid new composition",__FUNCTION__);
2189 mCurrentFrame.needsRedraw = false;
2190 setMDPCompLayerFlags(ctx, list);
2191 mCachedFrame.updateCounts(mCurrentFrame);
2192#ifdef DYNAMIC_FPS
2193 setDynRefreshRate(ctx, list);
2194#endif
2195 return -1;
2196
2197 }
2198
Saurabh Shahb39f8152013-08-22 10:21:44 -07002199 //Hard conditions, if not met, cannot do MDP comp
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002200 if(isFrameDoable(ctx)) {
2201 generateROI(ctx, list);
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07002202 // if AIV Video mode is enabled, drop all non AIV layers from the
2203 // external display list.
2204 if(ctx->listStats[mDpy].mAIVVideoMode) {
2205 dropNonAIVLayers(ctx, list);
2206 }
Saurabh Shahb39f8152013-08-22 10:21:44 -07002207
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002208 // Configure the cursor if present
2209 int topIndex = ctx->listStats[mDpy].numAppLayers - 1;
2210 if(ctx->listStats[mDpy].cursorLayerPresent &&
2211 validForCursor(ctx, mDpy, &(list->hwLayers[topIndex]))) {
2212 if(configHwCursor(ctx->dpyAttr[mDpy].fd, mDpy,
2213 &(list->hwLayers[topIndex]))) {
2214 // As cursor is configured, mark that layer as dropped, so that
2215 // it wont be considered for composition by other strategies.
2216 mCurrentFrame.hwCursorIndex = topIndex;
2217 mCurrentFrame.drop[topIndex] = true;
2218 mCurrentFrame.dropCount++;
2219 }
2220 } else {
2221 // Release the hw cursor
2222 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
2223 }
2224
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07002225 // if tryFullFrame fails, try to push all video and secure RGB layers
2226 // to MDP for composition.
2227 mModeOn = tryFullFrame(ctx, list) || tryMDPOnlyLayers(ctx, list) ||
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07002228 tryVideoOnly(ctx, list);
Raj Kamal4393eaa2014-06-06 13:45:20 +05302229 if(mModeOn) {
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002230 setMDPCompLayerFlags(ctx, list);
2231 } else {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08002232 resetROI(ctx, mDpy);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002233 reset(ctx);
2234 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
2235 mCurrentFrame.dropCount = 0;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002236 // Check if cursor is in use for primary and mark accordingly
2237 if(!mDpy && HWCursor::getInstance()->isCursorSet()) {
2238 int topIndex = ctx->listStats[mDpy].numAppLayers - 1;
2239 hwc_layer_1_t *layer = &(list->hwLayers[topIndex]);
2240 layer->compositionType = HWC_CURSOR_OVERLAY;
2241 }
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002242 ret = -1;
Saurabh Shah286cf122014-09-08 14:13:08 -07002243 ALOGE_IF(sSimulationFlags && (mDpy == HWC_DISPLAY_PRIMARY),
2244 "MDP Composition Strategies Failed");
Saurabh Shahb39f8152013-08-22 10:21:44 -07002245 }
2246 } else {
Dileep Kumar Reddi4070e932014-09-30 09:00:57 +05302247 if ((ctx->mMDP.version == qdutils::MDP_V3_0_5) && ctx->mCopyBit[mDpy] &&
2248 enablePartialUpdateForMDP3) {
2249 generateROI(ctx, list);
2250 for(int i = 0; i < ctx->listStats[mDpy].numAppLayers; i++) {
2251 ctx->copybitDrop[i] = mCurrentFrame.drop[i];
2252 }
2253 }
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002254 ALOGD_IF( isDebug(),"%s: MDP Comp not possible for this frame",
2255 __FUNCTION__);
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002256 // Release the hw cursor
2257 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002258 ret = -1;
Saurabh Shahb39f8152013-08-22 10:21:44 -07002259 }
Saurabh Shahb39f8152013-08-22 10:21:44 -07002260
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002261 if(isDebug()) {
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002262 ALOGD("GEOMETRY change: %d",
2263 (list->flags & HWC_GEOMETRY_CHANGED));
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002264 android::String8 sDump("");
Jeykumar Sankaran6850ac62014-05-27 10:07:26 -07002265 dump(sDump, ctx);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002266 ALOGD("%s",sDump.string());
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002267 }
2268
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07002269#ifdef DYNAMIC_FPS
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302270 setDynRefreshRate(ctx, list);
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07002271#endif
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08002272 setPerfHint(ctx, list);
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07002273
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002274 mCachedFrame.cacheAll(list);
2275 mCachedFrame.updateCounts(mCurrentFrame);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002276 return ret;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002277}
2278
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002279bool MDPComp::allocSplitVGPipes(hwc_context_t *ctx, int index) {
radhakrishnac9a67412013-09-25 17:40:42 +05302280
2281 bool bRet = true;
radhakrishnac9a67412013-09-25 17:40:42 +05302282 int mdpIndex = mCurrentFrame.layerToMDP[index];
2283 PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
2284 info.pipeInfo = new MdpYUVPipeInfo;
2285 info.rot = NULL;
2286 MdpYUVPipeInfo& pipe_info = *(MdpYUVPipeInfo*)info.pipeInfo;
radhakrishnac9a67412013-09-25 17:40:42 +05302287
2288 pipe_info.lIndex = ovutils::OV_INVALID;
2289 pipe_info.rIndex = ovutils::OV_INVALID;
2290
Saurabh Shahc62f3982014-03-05 14:28:26 -08002291 Overlay::PipeSpecs pipeSpecs;
2292 pipeSpecs.formatClass = Overlay::FORMAT_YUV;
2293 pipeSpecs.needsScaling = true;
2294 pipeSpecs.dpy = mDpy;
2295 pipeSpecs.fb = false;
2296
2297 pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
radhakrishnac9a67412013-09-25 17:40:42 +05302298 if(pipe_info.lIndex == ovutils::OV_INVALID){
2299 bRet = false;
2300 ALOGD_IF(isDebug(),"%s: allocating first VG pipe failed",
2301 __FUNCTION__);
2302 }
Saurabh Shahc62f3982014-03-05 14:28:26 -08002303 pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
radhakrishnac9a67412013-09-25 17:40:42 +05302304 if(pipe_info.rIndex == ovutils::OV_INVALID){
2305 bRet = false;
2306 ALOGD_IF(isDebug(),"%s: allocating second VG pipe failed",
2307 __FUNCTION__);
2308 }
2309 return bRet;
2310}
Sushil Chauhandefd3522014-05-13 18:17:12 -07002311
2312int MDPComp::drawOverlap(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
2313 int fd = -1;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002314 if (ctx->mPtorInfo.isActive()) {
2315 fd = ctx->mCopyBit[mDpy]->drawOverlap(ctx, list);
Sushil Chauhandefd3522014-05-13 18:17:12 -07002316 if (fd < 0) {
2317 ALOGD_IF(isDebug(),"%s: failed", __FUNCTION__);
Sushil Chauhandefd3522014-05-13 18:17:12 -07002318 }
2319 }
2320 return fd;
2321}
Arun Kumar K.R2aa44c62014-01-21 23:08:28 -08002322//=============MDPCompNonSplit==================================================
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002323
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002324void MDPCompNonSplit::adjustForSourceSplit(hwc_context_t *ctx,
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302325 hwc_display_contents_1_t* list) {
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002326 //If 4k2k Yuv layer split is possible, and if
2327 //fbz is above 4k2k layer, increment fb zorder by 1
2328 //as we split 4k2k layer and increment zorder for right half
2329 //of the layer
Shalaj Jaina70b4352014-06-15 13:47:47 -07002330 if(!ctx)
2331 return;
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002332 if(mCurrentFrame.fbZ >= 0) {
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302333 for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
2334 index++) {
2335 if(!mCurrentFrame.isFBComposed[index]) {
2336 if(mdpNextZOrder == mCurrentFrame.fbZ) {
2337 mdpNextZOrder++;
2338 }
2339 mdpNextZOrder++;
2340 hwc_layer_1_t* layer = &list->hwLayers[index];
2341 private_handle_t *hnd = (private_handle_t *)layer->handle;
Raj Kamal389d6e32014-08-04 14:43:24 +05302342 if(isYUVSplitNeeded(hnd)) {
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302343 if(mdpNextZOrder <= mCurrentFrame.fbZ)
2344 mCurrentFrame.fbZ += 1;
2345 mdpNextZOrder++;
2346 //As we split 4kx2k yuv layer and program to 2 VG pipes
2347 //(if available) increase mdpcount by 1.
2348 mCurrentFrame.mdpCount++;
2349 }
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002350 }
2351 }
2352 }
radhakrishnac9a67412013-09-25 17:40:42 +05302353}
2354
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002355/*
2356 * Configures pipe(s) for MDP composition
2357 */
Saurabh Shah88e4d272013-09-03 13:31:29 -07002358int MDPCompNonSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002359 PipeLayerPair& PipeLayerPair) {
Saurabh Shah88e4d272013-09-03 13:31:29 -07002360 MdpPipeInfoNonSplit& mdp_info =
2361 *(static_cast<MdpPipeInfoNonSplit*>(PipeLayerPair.pipeInfo));
Justin Philipd6166602014-08-12 13:42:21 +05302362 eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shahacf10202013-02-26 10:15:15 -08002363 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Saurabh Shahacf10202013-02-26 10:15:15 -08002364 eDest dest = mdp_info.index;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002365
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002366 ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipe: %d",
2367 __FUNCTION__, layer, zOrder, dest);
2368
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002369 return configureNonSplit(ctx, layer, mDpy, mdpFlags, zOrder, dest,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002370 &PipeLayerPair.rot);
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002371}
2372
Saurabh Shah88e4d272013-09-03 13:31:29 -07002373bool MDPCompNonSplit::allocLayerPipes(hwc_context_t *ctx,
Saurabh Shahe51f8ca2013-05-06 17:26:16 -07002374 hwc_display_contents_1_t* list) {
Saurabh Shah8cc77712015-03-31 10:48:51 -07002375 for(uint32_t formatType = FORMAT_YUV; formatType < FORMAT_MAX;
2376 formatType++) {
2377 for(int index = 0; index < mCurrentFrame.layerCount; index++) {
2378 if(mCurrentFrame.isFBComposed[index]) continue;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002379
Saurabh Shah8cc77712015-03-31 10:48:51 -07002380 hwc_layer_1_t* layer = &list->hwLayers[index];
2381 private_handle_t *hnd = (private_handle_t *)layer->handle;
2382 if(formatType == FORMAT_YUV && !isYuvBuffer(hnd))
radhakrishnac9a67412013-09-25 17:40:42 +05302383 continue;
Saurabh Shah8cc77712015-03-31 10:48:51 -07002384 if(formatType == FORMAT_RGB && isYuvBuffer(hnd))
2385 continue;
2386
2387 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
2388 if(allocSplitVGPipes(ctx, index)){
2389 continue;
2390 }
radhakrishnac9a67412013-09-25 17:40:42 +05302391 }
radhakrishnac9a67412013-09-25 17:40:42 +05302392
Saurabh Shah8cc77712015-03-31 10:48:51 -07002393 int mdpIndex = mCurrentFrame.layerToMDP[index];
2394 PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
2395 info.pipeInfo = new MdpPipeInfoNonSplit;
2396 info.rot = NULL;
2397 MdpPipeInfoNonSplit& pipe_info =
2398 *(MdpPipeInfoNonSplit*)info.pipeInfo;
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -08002399
Saurabh Shah8cc77712015-03-31 10:48:51 -07002400 Overlay::PipeSpecs pipeSpecs;
2401 pipeSpecs.formatClass = isYuvBuffer(hnd) ?
2402 Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
2403 pipeSpecs.needsScaling = qhwc::needsScaling(layer) or
2404 (qdutils::MDPVersion::getInstance().is8x26() and
2405 ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres > 1024);
2406 pipeSpecs.dpy = mDpy;
2407 pipeSpecs.fb = false;
2408 pipeSpecs.numActiveDisplays = ctx->numActiveDisplays;
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -08002409
Saurabh Shah8cc77712015-03-31 10:48:51 -07002410 pipe_info.index = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahc62f3982014-03-05 14:28:26 -08002411
Saurabh Shah8cc77712015-03-31 10:48:51 -07002412 if(pipe_info.index == ovutils::OV_INVALID) {
2413 ALOGD_IF(isDebug(), "%s: Unable to get pipe for layer %d of "\
2414 "format type %d", __FUNCTION__, index, formatType);
2415 return false;
2416 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002417 }
2418 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002419 return true;
2420}
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002421
radhakrishnac9a67412013-09-25 17:40:42 +05302422int MDPCompNonSplit::configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
2423 PipeLayerPair& PipeLayerPair) {
2424 MdpYUVPipeInfo& mdp_info =
2425 *(static_cast<MdpYUVPipeInfo*>(PipeLayerPair.pipeInfo));
2426 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Justin Philipd6166602014-08-12 13:42:21 +05302427 eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
radhakrishnac9a67412013-09-25 17:40:42 +05302428 eDest lDest = mdp_info.lIndex;
2429 eDest rDest = mdp_info.rIndex;
2430
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002431 return configureSourceSplit(ctx, layer, mDpy, mdpFlagsL, zOrder,
radhakrishnac9a67412013-09-25 17:40:42 +05302432 lDest, rDest, &PipeLayerPair.rot);
2433}
2434
Saurabh Shah88e4d272013-09-03 13:31:29 -07002435bool MDPCompNonSplit::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002436
Raj Kamal4393eaa2014-06-06 13:45:20 +05302437 if(!isEnabled() or !mModeOn) {
2438 ALOGD_IF(isDebug(),"%s: MDP Comp not enabled/configured", __FUNCTION__);
Prabhanjan Kandula08222fc2013-07-10 17:20:59 +05302439 return true;
2440 }
2441
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002442 overlay::Overlay& ov = *ctx->mOverlay;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002443 LayerProp *layerProp = ctx->layerProp[mDpy];
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002444
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002445 int numHwLayers = ctx->listStats[mDpy].numAppLayers;
2446 for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ )
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002447 {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002448 if(mCurrentFrame.isFBComposed[i]) continue;
2449
Naseer Ahmed5b6708a2012-08-02 13:46:08 -07002450 hwc_layer_1_t *layer = &list->hwLayers[i];
Saurabh Shahacf10202013-02-26 10:15:15 -08002451 private_handle_t *hnd = (private_handle_t *)layer->handle;
2452 if(!hnd) {
Sushil Chauhan897a9c32013-07-18 11:09:55 -07002453 if (!(layer->flags & HWC_COLOR_FILL)) {
2454 ALOGE("%s handle null", __FUNCTION__);
2455 return false;
2456 }
2457 // No PLAY for Color layer
2458 layerProp[i].mFlags &= ~HWC_MDPCOMP;
2459 continue;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002460 }
2461
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002462 int mdpIndex = mCurrentFrame.layerToMDP[i];
2463
Raj Kamal389d6e32014-08-04 14:43:24 +05302464 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit)
radhakrishnac9a67412013-09-25 17:40:42 +05302465 {
2466 MdpYUVPipeInfo& pipe_info =
2467 *(MdpYUVPipeInfo*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
2468 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
2469 ovutils::eDest indexL = pipe_info.lIndex;
2470 ovutils::eDest indexR = pipe_info.rIndex;
2471 int fd = hnd->fd;
Praveena Pachipulusud9443c72014-02-17 10:42:28 +05302472 uint32_t offset = (uint32_t)hnd->offset;
radhakrishnac9a67412013-09-25 17:40:42 +05302473 if(rot) {
2474 rot->queueBuffer(fd, offset);
2475 fd = rot->getDstMemId();
2476 offset = rot->getDstOffset();
2477 }
2478 if(indexL != ovutils::OV_INVALID) {
2479 ovutils::eDest destL = (ovutils::eDest)indexL;
2480 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2481 using pipe: %d", __FUNCTION__, layer, hnd, indexL );
2482 if (!ov.queueBuffer(fd, offset, destL)) {
2483 ALOGE("%s: queueBuffer failed for display:%d",
2484 __FUNCTION__, mDpy);
2485 return false;
2486 }
2487 }
2488
2489 if(indexR != ovutils::OV_INVALID) {
2490 ovutils::eDest destR = (ovutils::eDest)indexR;
2491 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2492 using pipe: %d", __FUNCTION__, layer, hnd, indexR );
2493 if (!ov.queueBuffer(fd, offset, destR)) {
2494 ALOGE("%s: queueBuffer failed for display:%d",
2495 __FUNCTION__, mDpy);
2496 return false;
2497 }
2498 }
2499 }
2500 else{
2501 MdpPipeInfoNonSplit& pipe_info =
Saurabh Shah88e4d272013-09-03 13:31:29 -07002502 *(MdpPipeInfoNonSplit*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
radhakrishnac9a67412013-09-25 17:40:42 +05302503 ovutils::eDest dest = pipe_info.index;
2504 if(dest == ovutils::OV_INVALID) {
2505 ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, dest);
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002506 return false;
radhakrishnac9a67412013-09-25 17:40:42 +05302507 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002508
radhakrishnac9a67412013-09-25 17:40:42 +05302509 if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
2510 continue;
2511 }
2512
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002513 int fd = hnd->fd;
2514 uint32_t offset = (uint32_t)hnd->offset;
2515 int index = ctx->mPtorInfo.getPTORArrayIndex(i);
2516 if (!mDpy && (index != -1)) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07002517 hnd = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002518 fd = hnd->fd;
Sushil Chauhan875a92e2014-07-25 12:20:23 -07002519 offset = 0;
Sushil Chauhandefd3522014-05-13 18:17:12 -07002520 }
2521
radhakrishnac9a67412013-09-25 17:40:42 +05302522 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2523 using pipe: %d", __FUNCTION__, layer,
2524 hnd, dest );
2525
radhakrishnac9a67412013-09-25 17:40:42 +05302526 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
2527 if(rot) {
2528 if(!rot->queueBuffer(fd, offset))
2529 return false;
2530 fd = rot->getDstMemId();
2531 offset = rot->getDstOffset();
2532 }
2533
2534 if (!ov.queueBuffer(fd, offset, dest)) {
2535 ALOGE("%s: queueBuffer failed for display:%d ",
2536 __FUNCTION__, mDpy);
2537 return false;
2538 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002539 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002540
2541 layerProp[i].mFlags &= ~HWC_MDPCOMP;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002542 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002543 return true;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002544}
2545
Saurabh Shah88e4d272013-09-03 13:31:29 -07002546//=============MDPCompSplit===================================================
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002547
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002548void MDPCompSplit::adjustForSourceSplit(hwc_context_t *ctx,
radhakrishnac9a67412013-09-25 17:40:42 +05302549 hwc_display_contents_1_t* list){
2550 //if 4kx2k yuv layer is totally present in either in left half
2551 //or right half then try splitting the yuv layer to avoid decimation
radhakrishnac9a67412013-09-25 17:40:42 +05302552 const int lSplit = getLeftSplit(ctx, mDpy);
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302553 if(mCurrentFrame.fbZ >= 0) {
2554 for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
2555 index++) {
2556 if(!mCurrentFrame.isFBComposed[index]) {
2557 if(mdpNextZOrder == mCurrentFrame.fbZ) {
2558 mdpNextZOrder++;
2559 }
2560 mdpNextZOrder++;
2561 hwc_layer_1_t* layer = &list->hwLayers[index];
2562 private_handle_t *hnd = (private_handle_t *)layer->handle;
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002563 if(isYUVSplitNeeded(hnd) ||
2564 (needs3DComposition(ctx,mDpy) &&
2565 get3DFormat(hnd) != HAL_NO_3D)) {
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302566 hwc_rect_t dst = layer->displayFrame;
2567 if((dst.left > lSplit) || (dst.right < lSplit)) {
2568 mCurrentFrame.mdpCount += 1;
2569 }
2570 if(mdpNextZOrder <= mCurrentFrame.fbZ)
2571 mCurrentFrame.fbZ += 1;
2572 mdpNextZOrder++;
2573 }
2574 }
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002575 }
radhakrishnac9a67412013-09-25 17:40:42 +05302576 }
2577}
2578
Saurabh Shah88e4d272013-09-03 13:31:29 -07002579bool MDPCompSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
Saurabh Shahc62f3982014-03-05 14:28:26 -08002580 MdpPipeInfoSplit& pipe_info) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002581
Saurabh Shahc62f3982014-03-05 14:28:26 -08002582 const int lSplit = getLeftSplit(ctx, mDpy);
2583 private_handle_t *hnd = (private_handle_t *)layer->handle;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002584 hwc_rect_t dst = layer->displayFrame;
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002585 pipe_info.lIndex = ovutils::OV_INVALID;
2586 pipe_info.rIndex = ovutils::OV_INVALID;
2587
Saurabh Shahc62f3982014-03-05 14:28:26 -08002588 Overlay::PipeSpecs pipeSpecs;
2589 pipeSpecs.formatClass = isYuvBuffer(hnd) ?
2590 Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
2591 pipeSpecs.needsScaling = qhwc::needsScalingWithSplit(ctx, layer, mDpy);
2592 pipeSpecs.dpy = mDpy;
2593 pipeSpecs.mixer = Overlay::MIXER_LEFT;
2594 pipeSpecs.fb = false;
2595
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08002596 // Acquire pipe only for the updating half
2597 hwc_rect_t l_roi = ctx->listStats[mDpy].lRoi;
2598 hwc_rect_t r_roi = ctx->listStats[mDpy].rRoi;
2599
2600 if (dst.left < lSplit && isValidRect(getIntersection(dst, l_roi))) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002601 pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002602 if(pipe_info.lIndex == ovutils::OV_INVALID)
2603 return false;
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002604 }
2605
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08002606 if(dst.right > lSplit && isValidRect(getIntersection(dst, r_roi))) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002607 pipeSpecs.mixer = Overlay::MIXER_RIGHT;
2608 pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002609 if(pipe_info.rIndex == ovutils::OV_INVALID)
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002610 return false;
2611 }
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002612
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002613 return true;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002614}
2615
Saurabh Shah88e4d272013-09-03 13:31:29 -07002616bool MDPCompSplit::allocLayerPipes(hwc_context_t *ctx,
Saurabh Shahe51f8ca2013-05-06 17:26:16 -07002617 hwc_display_contents_1_t* list) {
Saurabh Shah8cc77712015-03-31 10:48:51 -07002618 for(uint32_t formatType = FORMAT_YUV; formatType < FORMAT_MAX;
2619 formatType++) {
2620 for(int index = 0 ; index < mCurrentFrame.layerCount; index++) {
2621 if(mCurrentFrame.isFBComposed[index]) continue;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002622
Saurabh Shah8cc77712015-03-31 10:48:51 -07002623 hwc_layer_1_t* layer = &list->hwLayers[index];
2624 private_handle_t *hnd = (private_handle_t *)layer->handle;
2625 if(formatType == FORMAT_YUV && !isYuvBuffer(hnd))
2626 continue;
2627 if(formatType == FORMAT_RGB && isYuvBuffer(hnd))
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002628 continue;
2629
Saurabh Shah8cc77712015-03-31 10:48:51 -07002630 hwc_rect_t dst = layer->displayFrame;
2631 const int lSplit = getLeftSplit(ctx, mDpy);
2632 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
2633 if((dst.left > lSplit)||(dst.right < lSplit)){
2634 if(allocSplitVGPipes(ctx, index)){
2635 continue;
2636 }
2637 }
2638 }
2639 //XXX: Check for forced 2D composition
2640 if(needs3DComposition(ctx, mDpy) && get3DFormat(hnd) != HAL_NO_3D)
2641 if(allocSplitVGPipes(ctx,index))
2642 continue;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002643
Saurabh Shah8cc77712015-03-31 10:48:51 -07002644 int mdpIndex = mCurrentFrame.layerToMDP[index];
2645 PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
2646 info.pipeInfo = new MdpPipeInfoSplit;
2647 info.rot = NULL;
2648 MdpPipeInfoSplit& pipe_info = *(MdpPipeInfoSplit*)info.pipeInfo;
2649
2650 if(!acquireMDPPipes(ctx, layer, pipe_info)) {
2651 ALOGD_IF(isDebug(), "%s: Unable to get pipe for layer %d of "\
2652 "format type %d", __FUNCTION__, index, formatType);
2653 return false;
2654 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002655 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002656 }
2657 return true;
2658}
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002659
radhakrishnac9a67412013-09-25 17:40:42 +05302660int MDPCompSplit::configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
2661 PipeLayerPair& PipeLayerPair) {
2662 const int lSplit = getLeftSplit(ctx, mDpy);
2663 hwc_rect_t dst = layer->displayFrame;
2664 if((dst.left > lSplit)||(dst.right < lSplit)){
2665 MdpYUVPipeInfo& mdp_info =
2666 *(static_cast<MdpYUVPipeInfo*>(PipeLayerPair.pipeInfo));
2667 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Justin Philipd6166602014-08-12 13:42:21 +05302668 eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
radhakrishnac9a67412013-09-25 17:40:42 +05302669 eDest lDest = mdp_info.lIndex;
2670 eDest rDest = mdp_info.rIndex;
2671
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002672 return configureSourceSplit(ctx, layer, mDpy, mdpFlagsL, zOrder,
radhakrishnac9a67412013-09-25 17:40:42 +05302673 lDest, rDest, &PipeLayerPair.rot);
2674 }
2675 else{
2676 return configure(ctx, layer, PipeLayerPair);
2677 }
2678}
2679
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002680/*
2681 * Configures pipe(s) for MDP composition
2682 */
Saurabh Shah88e4d272013-09-03 13:31:29 -07002683int MDPCompSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
Saurabh Shah67a38c32013-06-10 16:23:15 -07002684 PipeLayerPair& PipeLayerPair) {
Saurabh Shah88e4d272013-09-03 13:31:29 -07002685 MdpPipeInfoSplit& mdp_info =
2686 *(static_cast<MdpPipeInfoSplit*>(PipeLayerPair.pipeInfo));
Saurabh Shahacf10202013-02-26 10:15:15 -08002687 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Justin Philipd6166602014-08-12 13:42:21 +05302688 eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shahacf10202013-02-26 10:15:15 -08002689 eDest lDest = mdp_info.lIndex;
2690 eDest rDest = mdp_info.rIndex;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002691
2692 ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
Jeykumar Sankaran39305802014-12-12 17:55:57 -08002693 "dest_pipeR: %d",__FUNCTION__, layer, zOrder, lDest, rDest);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002694
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002695 return configureSplit(ctx, layer, mDpy, mdpFlagsL, zOrder, lDest,
Jeykumar Sankaran39305802014-12-12 17:55:57 -08002696 rDest, &PipeLayerPair.rot);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002697}
2698
Saurabh Shah88e4d272013-09-03 13:31:29 -07002699bool MDPCompSplit::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002700
Raj Kamal4393eaa2014-06-06 13:45:20 +05302701 if(!isEnabled() or !mModeOn) {
2702 ALOGD_IF(isDebug(),"%s: MDP Comp not enabled/configured", __FUNCTION__);
Prabhanjan Kandula08222fc2013-07-10 17:20:59 +05302703 return true;
2704 }
2705
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002706 overlay::Overlay& ov = *ctx->mOverlay;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002707 LayerProp *layerProp = ctx->layerProp[mDpy];
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002708
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002709 int numHwLayers = ctx->listStats[mDpy].numAppLayers;
2710 for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ )
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002711 {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002712 if(mCurrentFrame.isFBComposed[i]) continue;
2713
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002714 hwc_layer_1_t *layer = &list->hwLayers[i];
Saurabh Shahacf10202013-02-26 10:15:15 -08002715 private_handle_t *hnd = (private_handle_t *)layer->handle;
2716 if(!hnd) {
2717 ALOGE("%s handle null", __FUNCTION__);
2718 return false;
2719 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002720
2721 if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
2722 continue;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002723 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002724
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002725 int mdpIndex = mCurrentFrame.layerToMDP[i];
2726
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002727 if((isYUVSplitNeeded(hnd) && sEnableYUVsplit) ||
2728 (needs3DComposition(ctx, mDpy) && get3DFormat(hnd) != HAL_NO_3D))
radhakrishnac9a67412013-09-25 17:40:42 +05302729 {
2730 MdpYUVPipeInfo& pipe_info =
2731 *(MdpYUVPipeInfo*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
2732 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
2733 ovutils::eDest indexL = pipe_info.lIndex;
2734 ovutils::eDest indexR = pipe_info.rIndex;
2735 int fd = hnd->fd;
Praveena Pachipulusud9443c72014-02-17 10:42:28 +05302736 uint32_t offset = (uint32_t)hnd->offset;
radhakrishnac9a67412013-09-25 17:40:42 +05302737 if(rot) {
2738 rot->queueBuffer(fd, offset);
2739 fd = rot->getDstMemId();
2740 offset = rot->getDstOffset();
2741 }
2742 if(indexL != ovutils::OV_INVALID) {
2743 ovutils::eDest destL = (ovutils::eDest)indexL;
2744 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2745 using pipe: %d", __FUNCTION__, layer, hnd, indexL );
2746 if (!ov.queueBuffer(fd, offset, destL)) {
2747 ALOGE("%s: queueBuffer failed for display:%d",
2748 __FUNCTION__, mDpy);
2749 return false;
2750 }
2751 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002752
radhakrishnac9a67412013-09-25 17:40:42 +05302753 if(indexR != ovutils::OV_INVALID) {
2754 ovutils::eDest destR = (ovutils::eDest)indexR;
2755 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2756 using pipe: %d", __FUNCTION__, layer, hnd, indexR );
2757 if (!ov.queueBuffer(fd, offset, destR)) {
2758 ALOGE("%s: queueBuffer failed for display:%d",
2759 __FUNCTION__, mDpy);
2760 return false;
2761 }
Saurabh Shaha9da08f2013-07-03 13:27:53 -07002762 }
2763 }
radhakrishnac9a67412013-09-25 17:40:42 +05302764 else{
2765 MdpPipeInfoSplit& pipe_info =
2766 *(MdpPipeInfoSplit*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
2767 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
Saurabh Shaha9da08f2013-07-03 13:27:53 -07002768
radhakrishnac9a67412013-09-25 17:40:42 +05302769 ovutils::eDest indexL = pipe_info.lIndex;
2770 ovutils::eDest indexR = pipe_info.rIndex;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002771
radhakrishnac9a67412013-09-25 17:40:42 +05302772 int fd = hnd->fd;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002773 uint32_t offset = (uint32_t)hnd->offset;
2774 int index = ctx->mPtorInfo.getPTORArrayIndex(i);
2775 if (!mDpy && (index != -1)) {
2776 hnd = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
2777 fd = hnd->fd;
Sushil Chauhan875a92e2014-07-25 12:20:23 -07002778 offset = 0;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002779 }
radhakrishnac9a67412013-09-25 17:40:42 +05302780
Tatenda Chipeperekwa88fe6352014-04-14 10:36:06 -07002781 if(ctx->mAD->draw(ctx, fd, offset)) {
2782 fd = ctx->mAD->getDstFd();
2783 offset = ctx->mAD->getDstOffset();
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002784 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002785
radhakrishnac9a67412013-09-25 17:40:42 +05302786 if(rot) {
2787 rot->queueBuffer(fd, offset);
2788 fd = rot->getDstMemId();
2789 offset = rot->getDstOffset();
2790 }
2791
2792 //************* play left mixer **********
2793 if(indexL != ovutils::OV_INVALID) {
2794 ovutils::eDest destL = (ovutils::eDest)indexL;
2795 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2796 using pipe: %d", __FUNCTION__, layer, hnd, indexL );
2797 if (!ov.queueBuffer(fd, offset, destL)) {
2798 ALOGE("%s: queueBuffer failed for left mixer",
2799 __FUNCTION__);
2800 return false;
2801 }
2802 }
2803
2804 //************* play right mixer **********
2805 if(indexR != ovutils::OV_INVALID) {
2806 ovutils::eDest destR = (ovutils::eDest)indexR;
2807 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2808 using pipe: %d", __FUNCTION__, layer, hnd, indexR );
2809 if (!ov.queueBuffer(fd, offset, destR)) {
2810 ALOGE("%s: queueBuffer failed for right mixer",
2811 __FUNCTION__);
2812 return false;
2813 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002814 }
2815 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002816
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002817 layerProp[i].mFlags &= ~HWC_MDPCOMP;
2818 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002819
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002820 return true;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002821}
Saurabh Shahab47c692014-02-12 18:45:57 -08002822
2823//================MDPCompSrcSplit==============================================
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08002824
2825bool MDPCompSrcSplit::validateAndApplyROI(hwc_context_t *ctx,
2826 hwc_display_contents_1_t* list) {
2827 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
2828 hwc_rect_t visibleRect = ctx->listStats[mDpy].lRoi;
2829
2830 for(int i = numAppLayers - 1; i >= 0; i--) {
2831 if(!isValidRect(visibleRect)) {
2832 mCurrentFrame.drop[i] = true;
2833 mCurrentFrame.dropCount++;
2834 continue;
2835 }
2836
2837 const hwc_layer_1_t* layer = &list->hwLayers[i];
2838 hwc_rect_t dstRect = layer->displayFrame;
2839 hwc_rect_t res = getIntersection(visibleRect, dstRect);
2840
2841 if(!isValidRect(res)) {
2842 mCurrentFrame.drop[i] = true;
2843 mCurrentFrame.dropCount++;
2844 } else {
2845 /* Reset frame ROI when any layer which needs scaling also needs ROI
2846 * cropping */
2847 if(!isSameRect(res, dstRect) && needsScaling (layer)) {
2848 ALOGI("%s: Resetting ROI due to scaling", __FUNCTION__);
2849 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
2850 mCurrentFrame.dropCount = 0;
2851 return false;
2852 }
2853
2854 /* deduct any opaque region from visibleRect */
2855 if (layer->blending == HWC_BLENDING_NONE &&
2856 layer->planeAlpha == 0xFF)
2857 visibleRect = deductRect(visibleRect, res);
2858 }
2859 }
2860 return true;
2861}
2862
2863/*
2864 * HW Limitation: ping pong split can always split the ping pong output
2865 * equally across two DSI's. So the ROI programmed should be of equal width
2866 * for both the halves
2867 */
2868void MDPCompSrcSplit::generateROI(hwc_context_t *ctx,
2869 hwc_display_contents_1_t* list) {
2870 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
2871
2872
2873 if(!canPartialUpdate(ctx, list))
2874 return;
2875
2876 struct hwc_rect roi = (struct hwc_rect){0, 0, 0, 0};
2877 hwc_rect fullFrame = (struct hwc_rect) {0, 0,(int)ctx->dpyAttr[mDpy].xres,
2878 (int)ctx->dpyAttr[mDpy].yres};
2879
2880 for(int index = 0; index < numAppLayers; index++ ) {
2881 hwc_layer_1_t* layer = &list->hwLayers[index];
2882
2883 // If we have a RGB layer which needs rotation, no partial update
2884 if(!isYuvBuffer((private_handle_t *)layer->handle) && layer->transform)
2885 return;
2886
2887 if ((mCachedFrame.hnd[index] != layer->handle) ||
2888 isYuvBuffer((private_handle_t *)layer->handle)) {
2889 hwc_rect_t dst = layer->displayFrame;
2890 hwc_rect_t updatingRect = dst;
2891
2892#ifdef QCOM_BSP
2893 if(!needsScaling(layer) && !layer->transform)
2894 {
2895 hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
2896 int x_off = dst.left - src.left;
2897 int y_off = dst.top - src.top;
2898 updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
2899 }
2900#endif
2901
2902 roi = getUnion(roi, updatingRect);
2903 }
2904 }
2905
2906 /* No layer is updating. Still SF wants a refresh.*/
2907 if(!isValidRect(roi))
2908 return;
2909
2910 roi = expandROIFromMidPoint(roi, fullFrame);
2911
2912 hwc_rect lFrame = fullFrame;
2913 lFrame.right /= 2;
2914 hwc_rect lRoi = getIntersection(roi, lFrame);
2915
2916 // Align ROI coordinates to panel restrictions
2917 lRoi = getSanitizeROI(lRoi, lFrame);
2918
2919 hwc_rect rFrame = fullFrame;
2920 rFrame.left = lFrame.right;
2921 hwc_rect rRoi = getIntersection(roi, rFrame);
2922
2923 // Align ROI coordinates to panel restrictions
2924 rRoi = getSanitizeROI(rRoi, rFrame);
2925
2926 roi = getUnion(lRoi, rRoi);
2927
2928 ctx->listStats[mDpy].lRoi = roi;
2929 if(!validateAndApplyROI(ctx, list))
2930 resetROI(ctx, mDpy);
2931
2932 ALOGD_IF(isDebug(),"%s: generated ROI: [%d, %d, %d, %d] [%d, %d, %d, %d]",
2933 __FUNCTION__,
2934 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
2935 ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom,
2936 ctx->listStats[mDpy].rRoi.left, ctx->listStats[mDpy].rRoi.top,
2937 ctx->listStats[mDpy].rRoi.right, ctx->listStats[mDpy].rRoi.bottom);
2938}
2939
Saurabh Shahab47c692014-02-12 18:45:57 -08002940bool MDPCompSrcSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
Saurabh Shahc62f3982014-03-05 14:28:26 -08002941 MdpPipeInfoSplit& pipe_info) {
Saurabh Shahab47c692014-02-12 18:45:57 -08002942 private_handle_t *hnd = (private_handle_t *)layer->handle;
2943 hwc_rect_t dst = layer->displayFrame;
2944 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
2945 pipe_info.lIndex = ovutils::OV_INVALID;
2946 pipe_info.rIndex = ovutils::OV_INVALID;
2947
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08002948 if(qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() && !mDpy)
2949 trimAgainstROI(ctx,crop, dst);
2950
Saurabh Shahab47c692014-02-12 18:45:57 -08002951 //If 2 pipes are staged on a single stage of a mixer, then the left pipe
2952 //should have a higher priority than the right one. Pipe priorities are
2953 //starting with VG0, VG1 ... , RGB0 ..., DMA1
Saurabh Shahab47c692014-02-12 18:45:57 -08002954
Saurabh Shahc62f3982014-03-05 14:28:26 -08002955 Overlay::PipeSpecs pipeSpecs;
2956 pipeSpecs.formatClass = isYuvBuffer(hnd) ?
2957 Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
2958 pipeSpecs.needsScaling = qhwc::needsScaling(layer);
2959 pipeSpecs.dpy = mDpy;
2960 pipeSpecs.fb = false;
2961
Saurabh Shahab47c692014-02-12 18:45:57 -08002962 //1 pipe by default for a layer
Saurabh Shahc62f3982014-03-05 14:28:26 -08002963 pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahab47c692014-02-12 18:45:57 -08002964 if(pipe_info.lIndex == ovutils::OV_INVALID) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002965 return false;
Saurabh Shahab47c692014-02-12 18:45:57 -08002966 }
2967
Saurabh Shahea7a01d2014-05-22 17:45:36 -07002968 /* Use 2 pipes IF
2969 a) Layer's crop width is > 2048 or
2970 b) Layer's dest width > 2048 or
2971 c) On primary, driver has indicated with caps to split always. This is
2972 based on an empirically derived value of panel height. Applied only
2973 if the layer's width is > mixer's width
2974 */
2975
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +05302976 MDPVersion& mdpHw = MDPVersion::getInstance();
Saurabh Shahea7a01d2014-05-22 17:45:36 -07002977 bool primarySplitAlways = (mDpy == HWC_DISPLAY_PRIMARY) and
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +05302978 mdpHw.isSrcSplitAlways();
Saurabh Shah514759d2014-11-11 18:02:24 -08002979 const uint32_t lSplit = getLeftSplit(ctx, mDpy);
2980 const uint32_t dstWidth = dst.right - dst.left;
2981 const uint32_t dstHeight = dst.bottom - dst.top;
Saurabh Shah05f4e222015-02-05 14:36:22 -08002982 uint32_t cropWidth = has90Transform(layer) ? crop.bottom - crop.top :
Saurabh Shah189f23d2014-09-26 17:21:00 -07002983 crop.right - crop.left;
Saurabh Shah05f4e222015-02-05 14:36:22 -08002984 uint32_t cropHeight = has90Transform(layer) ? crop.right - crop.left :
Saurabh Shah514759d2014-11-11 18:02:24 -08002985 crop.bottom - crop.top;
2986 //Approximation to actual clock, ignoring the common factors in pipe and
2987 //mixer cases like line_time
2988 const uint32_t layerClock = getLayerClock(dstWidth, dstHeight, cropHeight);
2989 const uint32_t mixerClock = lSplit;
Saurabh Shahea7a01d2014-05-22 17:45:36 -07002990
Saurabh Shah05f4e222015-02-05 14:36:22 -08002991 const uint32_t downscale = getRotDownscale(ctx, layer);
2992 if(downscale) {
2993 cropWidth /= downscale;
2994 cropHeight /= downscale;
2995 }
2996
Jeykumar Sankaran39305802014-12-12 17:55:57 -08002997 if(dstWidth > mdpHw.getMaxPipeWidth() or
2998 cropWidth > mdpHw.getMaxPipeWidth() or
Saurabh Shah514759d2014-11-11 18:02:24 -08002999 (primarySplitAlways and
3000 (cropWidth > lSplit or layerClock > mixerClock))) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08003001 pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahab47c692014-02-12 18:45:57 -08003002 if(pipe_info.rIndex == ovutils::OV_INVALID) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08003003 return false;
Saurabh Shahdd8237a2014-02-28 14:29:09 -08003004 }
3005
Jeykumar Sankaran89e23ab2015-01-28 15:57:46 -08003006 if(ctx->mOverlay->needsPrioritySwap(pipe_info.lIndex,
3007 pipe_info.rIndex)) {
Saurabh Shahdd8237a2014-02-28 14:29:09 -08003008 qhwc::swap(pipe_info.lIndex, pipe_info.rIndex);
Saurabh Shahab47c692014-02-12 18:45:57 -08003009 }
3010 }
3011
3012 return true;
3013}
3014
Saurabh Shahab47c692014-02-12 18:45:57 -08003015int MDPCompSrcSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
3016 PipeLayerPair& PipeLayerPair) {
3017 private_handle_t *hnd = (private_handle_t *)layer->handle;
3018 if(!hnd) {
3019 ALOGE("%s: layer handle is NULL", __FUNCTION__);
3020 return -1;
3021 }
3022 MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
3023 MdpPipeInfoSplit& mdp_info =
3024 *(static_cast<MdpPipeInfoSplit*>(PipeLayerPair.pipeInfo));
3025 Rotator **rot = &PipeLayerPair.rot;
3026 eZorder z = static_cast<eZorder>(mdp_info.zOrder);
Saurabh Shahab47c692014-02-12 18:45:57 -08003027 eDest lDest = mdp_info.lIndex;
3028 eDest rDest = mdp_info.rIndex;
3029 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
3030 hwc_rect_t dst = layer->displayFrame;
3031 int transform = layer->transform;
3032 eTransform orient = static_cast<eTransform>(transform);
Saurabh Shahab47c692014-02-12 18:45:57 -08003033 int rotFlags = ROT_FLAGS_NONE;
Sushil Chauhan65e26302015-01-14 10:48:57 -08003034 uint32_t format = ovutils::getMdpFormat(hnd->format, hnd->flags);
Saurabh Shahab47c692014-02-12 18:45:57 -08003035 Whf whf(getWidth(hnd), getHeight(hnd), format, hnd->size);
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05003036 eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shahab47c692014-02-12 18:45:57 -08003037
3038 ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
3039 "dest_pipeR: %d",__FUNCTION__, layer, z, lDest, rDest);
3040
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08003041 if(qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() && !mDpy) {
3042 /* MDP driver crops layer coordinates against ROI in Non-Split
3043 * and Split MDP comp. But HWC needs to crop them for source split.
3044 * Reason: 1) Source split is efficient only when the final effective
3045 * load is distributed evenly across mixers.
3046 * 2) We have to know the effective width of the layer that
3047 * the ROI needs to find the no. of pipes the layer needs.
3048 */
3049 trimAgainstROI(ctx, crop, dst);
3050 }
3051
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05003052 if(needs3DComposition(ctx, mDpy) &&
3053 get3DFormat(hnd) != HAL_NO_3D){
3054 return configure3DVideo(ctx, layer, mDpy, mdpFlags, z, lDest,
3055 rDest, &PipeLayerPair.rot);
3056 }
3057
Saurabh Shahab47c692014-02-12 18:45:57 -08003058 // Handle R/B swap
3059 if (layer->flags & HWC_FORMAT_RB_SWAP) {
3060 if (hnd->format == HAL_PIXEL_FORMAT_RGBA_8888)
3061 whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRA_8888);
3062 else if (hnd->format == HAL_PIXEL_FORMAT_RGBX_8888)
3063 whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
3064 }
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07003065 // update source crop and destination position of AIV video layer.
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07003066 if(ctx->listStats[mDpy].mAIVVideoMode && isYuvBuffer(hnd)) {
3067 updateCoordinates(ctx, crop, dst, mDpy);
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07003068 }
Ramkumar Radhakrishnana5c72872014-08-28 19:04:18 -07003069 /* Calculate the external display position based on MDP downscale,
3070 ActionSafe, and extorientation features. */
3071 calcExtDisplayPosition(ctx, hnd, mDpy, crop, dst, transform, orient);
Saurabh Shahab47c692014-02-12 18:45:57 -08003072
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003073 int downscale = getRotDownscale(ctx, layer);
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003074 setMdpFlags(ctx, layer, mdpFlags, downscale, transform);
Saurabh Shahab47c692014-02-12 18:45:57 -08003075
3076 if(lDest != OV_INVALID && rDest != OV_INVALID) {
3077 //Enable overfetch
Saurabh Shah97e2d802014-04-14 18:03:54 -07003078 setMdpFlags(mdpFlags, OV_MDSS_MDP_DUAL_PIPE);
Saurabh Shahab47c692014-02-12 18:45:57 -08003079 }
3080
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003081 if((has90Transform(layer) or downscale) and isRotationDoable(ctx, hnd)) {
Saurabh Shahab47c692014-02-12 18:45:57 -08003082 (*rot) = ctx->mRotMgr->getNext();
3083 if((*rot) == NULL) return -1;
Saurabh Shah39240c92014-03-31 10:31:42 -07003084 ctx->mLayerRotMap[mDpy]->add(layer, *rot);
Saurabh Shah1bd5b6f2014-05-19 12:23:13 -07003085 //If the video is using a single pipe, enable BWC
3086 if(rDest == OV_INVALID) {
Saurabh Shahcd018352014-11-11 13:54:19 -08003087 BwcPM::setBwc(ctx, mDpy, hnd, crop, dst, transform, downscale,
3088 mdpFlags);
Saurabh Shah1bd5b6f2014-05-19 12:23:13 -07003089 }
Saurabh Shahab47c692014-02-12 18:45:57 -08003090 //Configure rotator for pre-rotation
Saurabh Shah97e2d802014-04-14 18:03:54 -07003091 if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale) < 0) {
Saurabh Shahab47c692014-02-12 18:45:57 -08003092 ALOGE("%s: configRotator failed!", __FUNCTION__);
3093 return -1;
3094 }
Saurabh Shah8ec9b5e2014-06-30 14:37:17 -07003095 updateSource(orient, whf, crop, *rot);
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003096 rotFlags |= ovutils::ROT_PREROTATED;
Saurabh Shahab47c692014-02-12 18:45:57 -08003097 }
3098
3099 //If 2 pipes being used, divide layer into half, crop and dst
3100 hwc_rect_t cropL = crop;
3101 hwc_rect_t cropR = crop;
3102 hwc_rect_t dstL = dst;
3103 hwc_rect_t dstR = dst;
3104 if(lDest != OV_INVALID && rDest != OV_INVALID) {
3105 cropL.right = (crop.right + crop.left) / 2;
3106 cropR.left = cropL.right;
3107 sanitizeSourceCrop(cropL, cropR, hnd);
3108
Saurabh Shahb729b192014-08-15 18:04:24 -07003109 bool cropSwap = false;
Saurabh Shahab47c692014-02-12 18:45:57 -08003110 //Swap crops on H flip since 2 pipes are being used
3111 if((orient & OVERLAY_TRANSFORM_FLIP_H) && (*rot) == NULL) {
3112 hwc_rect_t tmp = cropL;
3113 cropL = cropR;
3114 cropR = tmp;
Saurabh Shahb729b192014-08-15 18:04:24 -07003115 cropSwap = true;
Saurabh Shahab47c692014-02-12 18:45:57 -08003116 }
3117
Saurabh Shahb729b192014-08-15 18:04:24 -07003118 //cropSwap trick: If the src and dst widths are both odd, let us say
3119 //2507, then splitting both into half would cause left width to be 1253
3120 //and right 1254. If crop is swapped because of H flip, this will cause
3121 //left crop width to be 1254, whereas left dst width remains 1253, thus
3122 //inducing a scaling that is unaccounted for. To overcome that we add 1
3123 //to the dst width if there is a cropSwap. So if the original width was
3124 //2507, the left dst width will be 1254. Even if the original width was
3125 //even for ex: 2508, the left dst width will still remain 1254.
3126 dstL.right = (dst.right + dst.left + cropSwap) / 2;
Saurabh Shahab47c692014-02-12 18:45:57 -08003127 dstR.left = dstL.right;
3128 }
3129
3130 //For the mdp, since either we are pre-rotating or MDP does flips
3131 orient = OVERLAY_TRANSFORM_0;
3132 transform = 0;
3133
3134 //configure left pipe
3135 if(lDest != OV_INVALID) {
Saurabh Shah2c8ad052014-08-15 13:27:46 -07003136 PipeArgs pargL(mdpFlags, whf, z,
Saurabh Shahab47c692014-02-12 18:45:57 -08003137 static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
3138 (ovutils::eBlending) getBlending(layer->blending));
3139
3140 if(configMdp(ctx->mOverlay, pargL, orient,
3141 cropL, dstL, metadata, lDest) < 0) {
3142 ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
3143 return -1;
3144 }
3145 }
3146
3147 //configure right pipe
3148 if(rDest != OV_INVALID) {
Saurabh Shah2c8ad052014-08-15 13:27:46 -07003149 PipeArgs pargR(mdpFlags, whf, z,
Saurabh Shahab47c692014-02-12 18:45:57 -08003150 static_cast<eRotFlags>(rotFlags),
3151 layer->planeAlpha,
3152 (ovutils::eBlending) getBlending(layer->blending));
3153 if(configMdp(ctx->mOverlay, pargR, orient,
3154 cropR, dstR, metadata, rDest) < 0) {
3155 ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
3156 return -1;
3157 }
3158 }
3159
3160 return 0;
3161}
3162
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -08003163bool MDPComp::getPartialUpdatePref(hwc_context_t *ctx) {
3164 Locker::Autolock _l(ctx->mDrawLock);
3165 const int fbNum = Overlay::getFbForDpy(Overlay::DPY_PRIMARY);
3166 char path[MAX_SYSFS_FILE_PATH];
3167 snprintf (path, sizeof(path), "sys/class/graphics/fb%d/dyn_pu", fbNum);
3168 int fd = open(path, O_RDONLY);
3169 if(fd < 0) {
3170 ALOGE("%s: Failed to open sysfd node: %s", __FUNCTION__, path);
3171 return -1;
3172 }
3173 char value[4];
3174 ssize_t size_read = read(fd, value, sizeof(value)-1);
3175 if(size_read <= 0) {
3176 ALOGE("%s: Failed to read sysfd node: %s", __FUNCTION__, path);
3177 close(fd);
3178 return -1;
3179 }
3180 close(fd);
3181 value[size_read] = '\0';
3182 return atoi(value);
3183}
3184
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003185int MDPComp::setPartialUpdatePref(hwc_context_t *ctx, bool enable) {
3186 Locker::Autolock _l(ctx->mDrawLock);
3187 const int fbNum = Overlay::getFbForDpy(Overlay::DPY_PRIMARY);
3188 char path[MAX_SYSFS_FILE_PATH];
3189 snprintf (path, sizeof(path), "sys/class/graphics/fb%d/dyn_pu", fbNum);
3190 int fd = open(path, O_WRONLY);
3191 if(fd < 0) {
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -08003192 ALOGE("%s: Failed to open sysfd node: %s", __FUNCTION__, path);
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003193 return -1;
3194 }
3195 char value[4];
3196 snprintf(value, sizeof(value), "%d", (int)enable);
3197 ssize_t ret = write(fd, value, strlen(value));
3198 if(ret <= 0) {
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -08003199 ALOGE("%s: Failed to write to sysfd nodes: %s", __FUNCTION__, path);
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003200 close(fd);
3201 return -1;
3202 }
3203 close(fd);
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003204 return 0;
3205}
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08003206
3207bool MDPComp::loadPerfLib() {
3208 char perfLibPath[PROPERTY_VALUE_MAX] = {0};
3209 bool success = false;
3210 if((property_get("ro.vendor.extension_library", perfLibPath, NULL) <= 0)) {
3211 ALOGE("vendor library not set in ro.vendor.extension_library");
3212 return false;
3213 }
3214
3215 sLibPerfHint = dlopen(perfLibPath, RTLD_NOW);
3216 if(sLibPerfHint) {
3217 *(void **)&sPerfLockAcquire = dlsym(sLibPerfHint, "perf_lock_acq");
3218 *(void **)&sPerfLockRelease = dlsym(sLibPerfHint, "perf_lock_rel");
3219 if (!sPerfLockAcquire || !sPerfLockRelease) {
3220 ALOGE("Failed to load symbols for perfLock");
3221 dlclose(sLibPerfHint);
3222 sLibPerfHint = NULL;
3223 return false;
3224 }
3225 success = true;
3226 ALOGI("Successfully Loaded perf hint API's");
3227 } else {
3228 ALOGE("Failed to open %s : %s", perfLibPath, dlerror());
3229 }
3230 return success;
3231}
3232
3233void MDPComp::setPerfHint(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
3234 if ((sPerfHintWindow < 0) || mDpy || !sLibPerfHint) {
3235 return;
3236 }
3237 static int count = sPerfHintWindow;
3238 static int perflockFlag = 0;
3239
3240 /* Send hint to mpctl when single layer is updated
3241 * for a successful number of windows. Hint release
3242 * happens immediately upon multiple layer update.
3243 */
3244 if (onlyVideosUpdating(ctx, list)) {
3245 if(count) {
3246 count--;
3247 }
3248 } else {
3249 if (perflockFlag) {
3250 perflockFlag = 0;
3251 sPerfLockRelease(sPerfLockHandle);
3252 }
3253 count = sPerfHintWindow;
3254 }
3255 if (count == 0 && !perflockFlag) {
3256 int perfHint = 0x4501; // 45-display layer hint, 01-Enable
3257 sPerfLockHandle = sPerfLockAcquire(0 /*handle*/, 0/*duration*/,
3258 &perfHint, sizeof(perfHint)/sizeof(int));
Arun Kumar K.R8b927022015-02-24 12:34:21 -08003259 if(sPerfLockHandle > 0) {
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08003260 perflockFlag = 1;
3261 }
3262 }
3263}
3264
Naseer Ahmed7c958d42012-07-31 18:57:03 -07003265}; //namespace
3266