blob: d21533c15f3ac30a162aa5c1b426ecf5b6bf6adf [file] [log] [blame]
Naseer Ahmed7c958d42012-07-31 18:57:03 -07001/*
Tatenda Chipeperekwa95675a72014-12-15 17:06:43 -08002 * Copyright (C) 2012-2015, The Linux Foundation. All rights reserved.
Naseer Ahmed7c958d42012-07-31 18:57:03 -07003 * Not a Contribution, Apache license notifications and license are retained
4 * for attribution purposes only.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
Saurabh Shah4fdde762013-04-30 18:47:33 -070019#include <math.h>
Naseer Ahmed7c958d42012-07-31 18:57:03 -070020#include "hwc_mdpcomp.h"
Arun Kumar K.R299bcda2014-12-18 19:36:40 -080021#include <dlfcn.h>
Tatenda Chipeperekwaaf2c0042014-09-17 12:55:01 -070022#include "hdmi.h"
Ramkumar Radhakrishnan47573e22012-11-07 11:36:41 -080023#include "qdMetaData.h"
Ramkumar Radhakrishnan288f8c72013-01-15 11:37:54 -080024#include "mdp_version.h"
Saurabh Shah2a4eb1b2013-07-22 16:33:23 -070025#include "hwc_fbupdate.h"
Saurabh Shaha9da08f2013-07-03 13:27:53 -070026#include "hwc_ad.h"
Saurabh Shahacf10202013-02-26 10:15:15 -080027#include <overlayRotator.h>
Arun Kumar K.R00b84792015-03-27 11:28:36 -070028#include <overlayCursor.h>
Sushil Chauhandefd3522014-05-13 18:17:12 -070029#include "hwc_copybit.h"
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -070030#include "qd_utils.h"
Saurabh Shahacf10202013-02-26 10:15:15 -080031
Saurabh Shah85234ec2013-04-12 17:09:00 -070032using namespace overlay;
Saurabh Shahbd2d0832013-04-04 14:33:08 -070033using namespace qdutils;
Saurabh Shahacf10202013-02-26 10:15:15 -080034using namespace overlay::utils;
35namespace ovutils = overlay::utils;
Naseer Ahmed7c958d42012-07-31 18:57:03 -070036
Naseer Ahmed7c958d42012-07-31 18:57:03 -070037namespace qhwc {
38
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -080039//==============MDPComp========================================================
40
Saurabh Shah59562ff2014-09-30 16:13:12 -070041IdleInvalidator *MDPComp::sIdleInvalidator = NULL;
Naseer Ahmed7c958d42012-07-31 18:57:03 -070042bool MDPComp::sIdleFallBack = false;
43bool MDPComp::sDebugLogs = false;
Naseer Ahmed54821fe2012-11-28 18:44:38 -050044bool MDPComp::sEnabled = false;
Jeykumar Sankaran24c199d2013-05-24 09:40:36 -070045bool MDPComp::sEnableMixedMode = true;
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -070046int MDPComp::sSimulationFlags = 0;
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -070047int MDPComp::sMaxPipesPerMixer = 0;
Raj Kamal389d6e32014-08-04 14:43:24 +053048bool MDPComp::sEnableYUVsplit = false;
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -070049bool MDPComp::sSrcSplitEnabled = false;
Saurabh Shahacec8e42014-11-25 11:07:04 -080050int MDPComp::sMaxSecLayers = 1;
Dileep Kumar Reddi4070e932014-09-30 09:00:57 +053051bool MDPComp::enablePartialUpdateForMDP3 = false;
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -070052bool MDPComp::sIsPartialUpdateActive = true;
Arun Kumar K.R299bcda2014-12-18 19:36:40 -080053void *MDPComp::sLibPerfHint = NULL;
54int MDPComp::sPerfLockHandle = 0;
55int (*MDPComp::sPerfLockAcquire)(int, int, int*, int) = NULL;
56int (*MDPComp::sPerfLockRelease)(int value) = NULL;
57int MDPComp::sPerfHintWindow = -1;
radhakrishna35e33072015-04-08 17:20:43 +053058float MDPComp::sDownscaleThreshold = 1.0;
Arun Kumar K.R299bcda2014-12-18 19:36:40 -080059
Saurabh Shah8cc77712015-03-31 10:48:51 -070060enum AllocOrder { FORMAT_YUV, FORMAT_RGB, FORMAT_MAX };
61
Saurabh Shah88e4d272013-09-03 13:31:29 -070062MDPComp* MDPComp::getObject(hwc_context_t *ctx, const int& dpy) {
Saurabh Shah60e8bde2014-04-30 14:46:03 -070063 if(qdutils::MDPVersion::getInstance().isSrcSplit()) {
64 sSrcSplitEnabled = true;
65 return new MDPCompSrcSplit(dpy);
66 } else if(isDisplaySplit(ctx, dpy)) {
Saurabh Shah88e4d272013-09-03 13:31:29 -070067 return new MDPCompSplit(dpy);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -080068 }
Saurabh Shah88e4d272013-09-03 13:31:29 -070069 return new MDPCompNonSplit(dpy);
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -080070}
71
Saurabh Shahac279de2015-05-21 18:56:58 -070072MDPComp::MDPComp(int dpy) : mDpy(dpy), mModeOn(false), mPrevModeOn(false) {
73};
Jeykumar Sankaran85977e32013-02-25 17:06:08 -080074
Jeykumar Sankaran6850ac62014-05-27 10:07:26 -070075void MDPComp::dump(android::String8& buf, hwc_context_t *ctx)
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -080076{
Jeykumar Sankaran3c6bb042013-08-15 14:01:04 -070077 if(mCurrentFrame.layerCount > MAX_NUM_APP_LAYERS)
78 return;
79
Jeykumar Sankaran85977e32013-02-25 17:06:08 -080080 dumpsys_log(buf,"HWC Map for Dpy: %s \n",
Jeykumar Sankaran27dee262013-08-01 17:09:54 -070081 (mDpy == 0) ? "\"PRIMARY\"" :
82 (mDpy == 1) ? "\"EXTERNAL\"" : "\"VIRTUAL\"");
Saurabh Shahe9bc60f2013-08-29 12:58:06 -070083 dumpsys_log(buf,"CURR_FRAME: layerCount:%2d mdpCount:%2d "
Arun Kumar K.R00b84792015-03-27 11:28:36 -070084 "fbCount:%2d dropCount:%2d\n", mCurrentFrame.layerCount,
85 mCurrentFrame.mdpCount, mCurrentFrame.fbCount, mCurrentFrame.dropCount);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -080086 dumpsys_log(buf,"needsFBRedraw:%3s pipesUsed:%2d MaxPipesPerMixer: %d \n",
87 (mCurrentFrame.needsRedraw? "YES" : "NO"),
88 mCurrentFrame.mdpCount, sMaxPipesPerMixer);
Jeykumar Sankaran6850ac62014-05-27 10:07:26 -070089 if(isDisplaySplit(ctx, mDpy)) {
90 dumpsys_log(buf, "Programmed ROI's: Left: [%d, %d, %d, %d] "
91 "Right: [%d, %d, %d, %d] \n",
92 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
93 ctx->listStats[mDpy].lRoi.right,
94 ctx->listStats[mDpy].lRoi.bottom,
95 ctx->listStats[mDpy].rRoi.left,ctx->listStats[mDpy].rRoi.top,
96 ctx->listStats[mDpy].rRoi.right,
97 ctx->listStats[mDpy].rRoi.bottom);
98 } else {
99 dumpsys_log(buf, "Programmed ROI: [%d, %d, %d, %d] \n",
100 ctx->listStats[mDpy].lRoi.left,ctx->listStats[mDpy].lRoi.top,
101 ctx->listStats[mDpy].lRoi.right,
102 ctx->listStats[mDpy].lRoi.bottom);
103 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800104 dumpsys_log(buf," --------------------------------------------- \n");
105 dumpsys_log(buf," listIdx | cached? | mdpIndex | comptype | Z \n");
106 dumpsys_log(buf," --------------------------------------------- \n");
107 for(int index = 0; index < mCurrentFrame.layerCount; index++ )
108 dumpsys_log(buf," %7d | %7s | %8d | %9s | %2d \n",
109 index,
110 (mCurrentFrame.isFBComposed[index] ? "YES" : "NO"),
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700111 mCurrentFrame.layerToMDP[index],
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800112 (mCurrentFrame.isFBComposed[index] ?
Arun Kumar K.R00b84792015-03-27 11:28:36 -0700113 (mCurrentFrame.drop[index] ?
114 ((mCurrentFrame.hwCursorIndex == index) ? "CURSOR": "DROP"):
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700115 (mCurrentFrame.needsRedraw ? "GLES" : "CACHE")) : "MDP"),
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800116 (mCurrentFrame.isFBComposed[index] ? mCurrentFrame.fbZ :
117 mCurrentFrame.mdpToLayer[mCurrentFrame.layerToMDP[index]].pipeInfo->zOrder));
118 dumpsys_log(buf,"\n");
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800119}
120
121bool MDPComp::init(hwc_context_t *ctx) {
122
123 if(!ctx) {
124 ALOGE("%s: Invalid hwc context!!",__FUNCTION__);
125 return false;
126 }
127
Saurabh Shah59562ff2014-09-30 16:13:12 -0700128 char property[PROPERTY_VALUE_MAX] = {0};
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800129
130 sEnabled = false;
Dileep Kumar Reddid8e601d2014-10-28 18:20:43 +0530131 if((ctx->mMDP.version >= qdutils::MDP_V4_0) &&
132 (property_get("persist.hwc.mdpcomp.enable", property, NULL) > 0) &&
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800133 (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
134 (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800135 sEnabled = true;
136 }
137
Jeykumar Sankaran24c199d2013-05-24 09:40:36 -0700138 sEnableMixedMode = true;
139 if((property_get("debug.mdpcomp.mixedmode.disable", property, NULL) > 0) &&
140 (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
141 (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
142 sEnableMixedMode = false;
143 }
144
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700145 qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
146
Saurabh Shah2fd8a252014-12-05 13:49:53 -0800147 sMaxPipesPerMixer = (int)mdpVersion.getBlendStages();
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700148 if(property_get("persist.hwc.mdpcomp.maxpermixer", property, "-1") > 0) {
Saurabh Shah85234ec2013-04-12 17:09:00 -0700149 int val = atoi(property);
150 if(val >= 0)
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700151 sMaxPipesPerMixer = min(val, sMaxPipesPerMixer);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800152 }
153
Saurabh Shahacec8e42014-11-25 11:07:04 -0800154 /* Maximum layers allowed to use MDP on secondary panels. If property
155 * doesn't exist, default to 1. Using the property it can be set to 0 or
156 * more.
157 */
158 if(property_get("persist.hwc.maxseclayers", property, "1") > 0) {
159 int val = atoi(property);
160 sMaxSecLayers = (val >= 0) ? val : 1;
161 sMaxSecLayers = min(sMaxSecLayers, sMaxPipesPerMixer);
162 }
163
Naseer Ahmedf40f2c82013-08-14 16:42:40 -0400164 if(ctx->mMDP.panel != MIPI_CMD_PANEL) {
Saurabh Shah59562ff2014-09-30 16:13:12 -0700165 sIdleInvalidator = IdleInvalidator::getInstance();
166 if(sIdleInvalidator->init(timeout_handler, ctx) < 0) {
167 delete sIdleInvalidator;
168 sIdleInvalidator = NULL;
Naseer Ahmedf40f2c82013-08-14 16:42:40 -0400169 }
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800170 }
radhakrishnac9a67412013-09-25 17:40:42 +0530171
Saurabh Shah7c727642014-06-02 15:47:14 -0700172 if(!qdutils::MDPVersion::getInstance().isSrcSplit() &&
Saurabh Shahc46cf9d2014-07-02 15:22:34 -0700173 !qdutils::MDPVersion::getInstance().isRotDownscaleEnabled() &&
Saurabh Shah7c727642014-06-02 15:47:14 -0700174 property_get("persist.mdpcomp.4k2kSplit", property, "0") > 0 &&
175 (!strncmp(property, "1", PROPERTY_VALUE_MAX) ||
176 !strncasecmp(property,"true", PROPERTY_VALUE_MAX))) {
Raj Kamal389d6e32014-08-04 14:43:24 +0530177 sEnableYUVsplit = true;
radhakrishnac9a67412013-09-25 17:40:42 +0530178 }
Sushil Chauhandefd3522014-05-13 18:17:12 -0700179
Dileep Kumar Reddic6ef3472014-09-24 19:07:08 +0530180 bool defaultPTOR = false;
181 //Enable PTOR when "persist.hwc.ptor.enable" is not defined for
Prabhanjan Kandulafc541b32015-03-30 20:56:16 +0530182 //Bear family targets by default
Dileep Kumar Reddic6ef3472014-09-24 19:07:08 +0530183 if((property_get("persist.hwc.ptor.enable", property, NULL) <= 0) &&
184 (qdutils::MDPVersion::getInstance().is8x16() ||
Prabhanjan Kandulafc541b32015-03-30 20:56:16 +0530185 qdutils::MDPVersion::getInstance().is8x39() ||
186 qdutils::MDPVersion::getInstance().is8x52())) {
Dileep Kumar Reddic6ef3472014-09-24 19:07:08 +0530187 defaultPTOR = true;
188 }
189
190 if (defaultPTOR || (!strncasecmp(property, "true", PROPERTY_VALUE_MAX)) ||
191 (!strncmp(property, "1", PROPERTY_VALUE_MAX ))) {
Sushil Chauhandefd3522014-05-13 18:17:12 -0700192 ctx->mCopyBit[HWC_DISPLAY_PRIMARY] = new CopyBit(ctx,
193 HWC_DISPLAY_PRIMARY);
194 }
195
Dileep Kumar Reddi4070e932014-09-30 09:00:57 +0530196 if((property_get("persist.mdp3.partialUpdate", property, NULL) <= 0) &&
197 (ctx->mMDP.version == qdutils::MDP_V3_0_5)) {
198 enablePartialUpdateForMDP3 = true;
199 }
200
201 if(!enablePartialUpdateForMDP3 &&
202 (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
203 (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
204 enablePartialUpdateForMDP3 = true;
205 }
206
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -0800207 sIsPartialUpdateActive = getPartialUpdatePref(ctx);
208
Arun Kumar K.R299bcda2014-12-18 19:36:40 -0800209 if(property_get("persist.mdpcomp_perfhint", property, "-1") > 0) {
210 int val = atoi(property);
211 if(val > 0 && loadPerfLib()) {
212 sPerfHintWindow = val;
213 ALOGI("PerfHintWindow = %d", sPerfHintWindow);
214 }
215 }
216
radhakrishna35e33072015-04-08 17:20:43 +0530217 if(property_get("persist.hwc.downscale_threshold", property, "1.0") > 0) {
218 sDownscaleThreshold = (float)atof(property);
219 }
220
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700221 return true;
222}
223
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800224void MDPComp::reset(hwc_context_t *ctx) {
225 const int numLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shah2a4eb1b2013-07-22 16:33:23 -0700226 mCurrentFrame.reset(numLayers);
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800227 ctx->mOverlay->clear(mDpy);
228 ctx->mLayerRotMap[mDpy]->clear();
Saurabh Shah2a4eb1b2013-07-22 16:33:23 -0700229}
230
Raj Kamal4393eaa2014-06-06 13:45:20 +0530231void MDPComp::reset() {
Raj Kamalfdfdddf2015-03-16 21:59:25 +0530232 mPrevModeOn = mModeOn;
Raj Kamal4393eaa2014-06-06 13:45:20 +0530233 mModeOn = false;
234}
235
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700236void MDPComp::timeout_handler(void *udata) {
237 struct hwc_context_t* ctx = (struct hwc_context_t*)(udata);
Raj Kamalfdfdddf2015-03-16 21:59:25 +0530238 bool handleTimeout = false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700239
240 if(!ctx) {
241 ALOGE("%s: received empty data in timer callback", __FUNCTION__);
242 return;
243 }
Raj Kamal58b31a02014-12-16 15:53:53 +0530244
245 ctx->mDrawLock.lock();
Raj Kamalfdfdddf2015-03-16 21:59:25 +0530246
247 /* Handle timeout event only if the previous composition
248 on any display is MDP or MIXED*/
249 for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
250 if(ctx->mMDPComp[i])
251 handleTimeout =
252 ctx->mMDPComp[i]->isMDPComp() || handleTimeout;
253 }
254
255 if(!handleTimeout) {
Ramkumar Radhakrishnan92abb4f2014-02-06 21:31:29 -0800256 ALOGD_IF(isDebug(), "%s:Do not handle this timeout", __FUNCTION__);
Raj Kamal58b31a02014-12-16 15:53:53 +0530257 ctx->mDrawLock.unlock();
Ramkumar Radhakrishnan92abb4f2014-02-06 21:31:29 -0800258 return;
259 }
Jesse Hall3be78d92012-08-21 15:12:23 -0700260 if(!ctx->proc) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700261 ALOGE("%s: HWC proc not registered", __FUNCTION__);
Raj Kamal58b31a02014-12-16 15:53:53 +0530262 ctx->mDrawLock.unlock();
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700263 return;
264 }
265 sIdleFallBack = true;
Raj Kamal58b31a02014-12-16 15:53:53 +0530266 ctx->mDrawLock.unlock();
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700267 /* Trigger SF to redraw the current frame */
Jesse Hall3be78d92012-08-21 15:12:23 -0700268 ctx->proc->invalidate(ctx->proc);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700269}
270
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700271void MDPComp::setMaxPipesPerMixer(const uint32_t value) {
272 qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
Saurabh Shah2fd8a252014-12-05 13:49:53 -0800273 uint32_t maxSupported = (int)mdpVersion.getBlendStages();
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700274 if(value > maxSupported) {
275 ALOGW("%s: Input exceeds max value supported. Setting to"
276 "max value: %d", __FUNCTION__, maxSupported);
277 }
278 sMaxPipesPerMixer = min(value, maxSupported);
279}
280
Saurabh Shah59562ff2014-09-30 16:13:12 -0700281void MDPComp::setIdleTimeout(const uint32_t& timeout) {
282 enum { ONE_REFRESH_PERIOD_MS = 17, ONE_BILLION_MS = 1000000000 };
283
284 if(sIdleInvalidator) {
285 if(timeout <= ONE_REFRESH_PERIOD_MS) {
286 //If the specified timeout is < 1 draw cycle worth, "virtually"
287 //disable idle timeout. The ideal way for clients to disable
288 //timeout is to set it to 0
289 sIdleInvalidator->setIdleTimeout(ONE_BILLION_MS);
290 ALOGI("Disabled idle timeout");
291 return;
292 }
293 sIdleInvalidator->setIdleTimeout(timeout);
294 ALOGI("Idle timeout set to %u", timeout);
295 } else {
296 ALOGW("Cannot set idle timeout, IdleInvalidator not enabled");
297 }
298}
299
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800300void MDPComp::setMDPCompLayerFlags(hwc_context_t *ctx,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800301 hwc_display_contents_1_t* list) {
302 LayerProp *layerProp = ctx->layerProp[mDpy];
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800303
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800304 for(int index = 0; index < ctx->listStats[mDpy].numAppLayers; index++) {
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800305 hwc_layer_1_t* layer = &(list->hwLayers[index]);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800306 if(!mCurrentFrame.isFBComposed[index]) {
307 layerProp[index].mFlags |= HWC_MDPCOMP;
308 layer->compositionType = HWC_OVERLAY;
309 layer->hints |= HWC_HINT_CLEAR_FB;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800310 } else {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700311 /* Drop the layer when its already present in FB OR when it lies
312 * outside frame's ROI */
313 if(!mCurrentFrame.needsRedraw || mCurrentFrame.drop[index]) {
Arun Kumar K.R00b84792015-03-27 11:28:36 -0700314 if(index == mCurrentFrame.hwCursorIndex) {
315 layer->compositionType = HWC_CURSOR_OVERLAY;
316 } else {
317 layer->compositionType = HWC_OVERLAY;
318 }
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700319 }
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800320 }
321 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700322}
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500323
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800324void MDPComp::setRedraw(hwc_context_t *ctx,
325 hwc_display_contents_1_t* list) {
326 mCurrentFrame.needsRedraw = false;
327 if(!mCachedFrame.isSameFrame(mCurrentFrame, list) ||
328 (list->flags & HWC_GEOMETRY_CHANGED) ||
329 isSkipPresent(ctx, mDpy)) {
330 mCurrentFrame.needsRedraw = true;
331 }
332}
333
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800334MDPComp::FrameInfo::FrameInfo() {
Saurabh Shahf7fad542014-08-14 10:11:36 -0700335 memset(&mdpToLayer, 0, sizeof(mdpToLayer));
Saurabh Shahaa236822013-04-24 18:07:26 -0700336 reset(0);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800337}
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800338
Saurabh Shahaa236822013-04-24 18:07:26 -0700339void MDPComp::FrameInfo::reset(const int& numLayers) {
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700340 for(int i = 0 ; i < MAX_NUM_BLEND_STAGES; i++ ) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800341 if(mdpToLayer[i].pipeInfo) {
342 delete mdpToLayer[i].pipeInfo;
343 mdpToLayer[i].pipeInfo = NULL;
344 //We dont own the rotator
345 mdpToLayer[i].rot = NULL;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800346 }
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800347 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800348
349 memset(&mdpToLayer, 0, sizeof(mdpToLayer));
350 memset(&layerToMDP, -1, sizeof(layerToMDP));
Saurabh Shahaa236822013-04-24 18:07:26 -0700351 memset(&isFBComposed, 1, sizeof(isFBComposed));
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800352
Saurabh Shahaa236822013-04-24 18:07:26 -0700353 layerCount = numLayers;
354 fbCount = numLayers;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800355 mdpCount = 0;
Saurabh Shah2f3895f2013-05-02 10:13:31 -0700356 needsRedraw = true;
Saurabh Shahd53bc5f2014-02-05 10:17:43 -0800357 fbZ = -1;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800358}
359
Saurabh Shahaa236822013-04-24 18:07:26 -0700360void MDPComp::FrameInfo::map() {
361 // populate layer and MDP maps
362 int mdpIdx = 0;
363 for(int idx = 0; idx < layerCount; idx++) {
364 if(!isFBComposed[idx]) {
365 mdpToLayer[mdpIdx].listIndex = idx;
366 layerToMDP[idx] = mdpIdx++;
367 }
368 }
369}
370
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800371MDPComp::LayerCache::LayerCache() {
372 reset();
373}
374
375void MDPComp::LayerCache::reset() {
Saurabh Shahaa236822013-04-24 18:07:26 -0700376 memset(&hnd, 0, sizeof(hnd));
Prabhanjan Kandula2243aa62013-10-24 12:58:55 +0530377 memset(&isFBComposed, true, sizeof(isFBComposed));
378 memset(&drop, false, sizeof(drop));
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800379 layerCount = 0;
Saurabh Shahaa236822013-04-24 18:07:26 -0700380}
381
382void MDPComp::LayerCache::cacheAll(hwc_display_contents_1_t* list) {
Praveena Pachipulusud9443c72014-02-17 10:42:28 +0530383 const int numAppLayers = (int)list->numHwLayers - 1;
Saurabh Shahaa236822013-04-24 18:07:26 -0700384 for(int i = 0; i < numAppLayers; i++) {
385 hnd[i] = list->hwLayers[i].handle;
386 }
387}
388
389void MDPComp::LayerCache::updateCounts(const FrameInfo& curFrame) {
Saurabh Shahaa236822013-04-24 18:07:26 -0700390 layerCount = curFrame.layerCount;
Prabhanjan Kandula2243aa62013-10-24 12:58:55 +0530391 memcpy(&isFBComposed, &curFrame.isFBComposed, sizeof(isFBComposed));
392 memcpy(&drop, &curFrame.drop, sizeof(drop));
393}
394
Jeykumar Sankaran988d3682013-11-15 11:57:16 -0800395bool MDPComp::LayerCache::isSameFrame(const FrameInfo& curFrame,
396 hwc_display_contents_1_t* list) {
Prabhanjan Kandula2243aa62013-10-24 12:58:55 +0530397 if(layerCount != curFrame.layerCount)
398 return false;
399 for(int i = 0; i < curFrame.layerCount; i++) {
400 if((curFrame.isFBComposed[i] != isFBComposed[i]) ||
401 (curFrame.drop[i] != drop[i])) {
402 return false;
403 }
Jeykumar Sankaran988d3682013-11-15 11:57:16 -0800404 if(curFrame.isFBComposed[i] &&
405 (hnd[i] != list->hwLayers[i].handle)){
406 return false;
407 }
Prabhanjan Kandula2243aa62013-10-24 12:58:55 +0530408 }
409 return true;
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800410}
411
Raj Kamalfdfdddf2015-03-16 21:59:25 +0530412bool MDPComp::LayerCache::isSameFrame(hwc_context_t *ctx, int dpy,
413 hwc_display_contents_1_t* list) {
414
415 if(layerCount != ctx->listStats[dpy].numAppLayers)
416 return false;
417
418 if((list->flags & HWC_GEOMETRY_CHANGED) ||
419 isSkipPresent(ctx, dpy)) {
420 return false;
421 }
422
423 for(int i = 0; i < layerCount; i++) {
424 if(hnd[i] != list->hwLayers[i].handle)
425 return false;
426 }
427
428 return true;
429}
430
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700431bool MDPComp::isSupportedForMDPComp(hwc_context_t *ctx, hwc_layer_1_t* layer) {
432 private_handle_t *hnd = (private_handle_t *)layer->handle;
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800433 if((has90Transform(layer) and (not isRotationDoable(ctx, hnd))) ||
Raj Kamal1179d9c2014-10-28 15:31:35 +0530434 (not isValidDimension(ctx,layer)) ||
435 isSkipLayer(layer)) {
436 //More conditions here, sRGB+Blend etc
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700437 return false;
438 }
radhakrishna35e33072015-04-08 17:20:43 +0530439
440 //In targets with fewer pipes, frequent composition switch between MDP/GPU
441 //can happen for a layer due to lack of pipes. When this switch happens
442 //continuously for RGB downscaled layer with downscale greater than
443 //threshold, it appears as flicker as output
444 //of MDP and GPU are different as they use different filters for downscale.
445 //To avoid this flicker, punt RGB downscaled layer with downscale greater
446 //than threshold value to GPU always.
447 if((sDownscaleThreshold > 1.0)) {
448 if(((not isYuvBuffer(hnd))
449 and (not isDownscaleWithinThreshold(layer,
450 sDownscaleThreshold)))) {
451 ALOGD_IF(isDebug(), "%s: required downscale is greater than \
452 threshold %f", __FUNCTION__, sDownscaleThreshold);
453 return false;
454 }
455 }
456
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700457 return true;
458}
459
Sravan Kumar D.V.Nad5d9292013-04-24 14:23:04 +0530460bool MDPComp::isValidDimension(hwc_context_t *ctx, hwc_layer_1_t *layer) {
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800461 private_handle_t *hnd = (private_handle_t *)layer->handle;
462
463 if(!hnd) {
Sushil Chauhan897a9c32013-07-18 11:09:55 -0700464 if (layer->flags & HWC_COLOR_FILL) {
465 // Color layer
466 return true;
467 }
Ramkumar Radhakrishnan0cabf212014-09-08 20:07:49 -0700468 ALOGD_IF(isDebug(), "%s: layer handle is NULL", __FUNCTION__);
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800469 return false;
470 }
471
Naseer Ahmede850a802013-09-06 13:12:52 -0400472 //XXX: Investigate doing this with pixel phase on MDSS
Arun Kumar K.R7b1f1522015-06-01 19:55:47 -0700473 if((!isSecureBuffer(hnd) || !isProtectedBuffer(hnd)) &&
474 isNonIntegralSourceCrop(layer->sourceCropf)) {
Naseer Ahmede850a802013-09-06 13:12:52 -0400475 return false;
Arun Kumar K.R7b1f1522015-06-01 19:55:47 -0700476 }
Naseer Ahmede850a802013-09-06 13:12:52 -0400477
Saurabh Shah62e1d732013-09-17 10:44:05 -0700478 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
Saurabh Shah4fdde762013-04-30 18:47:33 -0700479 hwc_rect_t dst = layer->displayFrame;
Saurabh Shahb6810df2014-06-17 16:00:22 -0700480 bool rotated90 = (bool)(layer->transform & HAL_TRANSFORM_ROT_90);
Saurabh Shahe28a4022014-06-13 11:41:13 -0700481 int crop_w = rotated90 ? crop.bottom - crop.top : crop.right - crop.left;
482 int crop_h = rotated90 ? crop.right - crop.left : crop.bottom - crop.top;
Saurabh Shah4fdde762013-04-30 18:47:33 -0700483 int dst_w = dst.right - dst.left;
484 int dst_h = dst.bottom - dst.top;
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800485 float w_scale = ((float)crop_w / (float)dst_w);
486 float h_scale = ((float)crop_h / (float)dst_h);
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530487 MDPVersion& mdpHw = MDPVersion::getInstance();
Saurabh Shah4fdde762013-04-30 18:47:33 -0700488
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800489 /* Workaround for MDP HW limitation in DSI command mode panels where
490 * FPS will not go beyond 30 if buffers on RGB pipes are of width or height
491 * less than 5 pixels
Sravan Kumar D.V.Nad5d9292013-04-24 14:23:04 +0530492 * There also is a HW limilation in MDP, minimum block size is 2x2
493 * Fallback to GPU if height is less than 2.
494 */
Saurabh Shah189f23d2014-09-26 17:21:00 -0700495 if(mdpHw.hasMinCropWidthLimitation() and (crop_w < 5 or crop_h < 5))
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800496 return false;
497
Ramkumar Radhakrishnan1a763e92015-03-19 16:46:46 -0700498 /* crop_w and crop_h should be even for yuv layer, so fallback to GPU for
499 * those cases
500 */
501 if(isYuvBuffer(hnd) && (crop_w < 2 || crop_h < 2)) {
502 return false;
503 }
504
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800505 if((w_scale > 1.0f) || (h_scale > 1.0f)) {
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530506 const uint32_t maxMDPDownscale = mdpHw.getMaxMDPDownscale();
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800507 const float w_dscale = w_scale;
508 const float h_dscale = h_scale;
509
Jeykumar Sankaran1706a772013-11-27 12:55:19 -0800510 if(ctx->mMDP.version >= qdutils::MDSS_V5) {
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700511
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530512 if(!mdpHw.supportsDecimation()) {
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700513 /* On targets that doesnt support Decimation (eg.,8x26)
514 * maximum downscale support is overlay pipe downscale.
515 */
Jeykumar Sankaran39305802014-12-12 17:55:57 -0800516 if(crop_w > (int) mdpHw.getMaxPipeWidth() ||
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530517 w_dscale > maxMDPDownscale ||
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700518 h_dscale > maxMDPDownscale)
Jeykumar Sankaran1706a772013-11-27 12:55:19 -0800519 return false;
520 } else {
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700521 // Decimation on macrotile format layers is not supported.
522 if(isTileRendered(hnd)) {
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530523 /* Bail out if
524 * 1. Src crop > Mixer limit on nonsplit MDPComp
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700525 * 2. exceeds maximum downscale limit
526 */
Jeykumar Sankaran39305802014-12-12 17:55:57 -0800527 if(((crop_w > (int) mdpHw.getMaxPipeWidth()) &&
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530528 !sSrcSplitEnabled) ||
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700529 w_dscale > maxMDPDownscale ||
530 h_dscale > maxMDPDownscale) {
531 return false;
532 }
533 } else if(w_dscale > 64 || h_dscale > 64)
Jeykumar Sankaran1706a772013-11-27 12:55:19 -0800534 return false;
535 }
536 } else { //A-family
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700537 if(w_dscale > maxMDPDownscale || h_dscale > maxMDPDownscale)
Saurabh Shah4fdde762013-04-30 18:47:33 -0700538 return false;
539 }
Saurabh Shah4fdde762013-04-30 18:47:33 -0700540 }
541
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800542 if((w_scale < 1.0f) || (h_scale < 1.0f)) {
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530543 const uint32_t upscale = mdpHw.getMaxMDPUpscale();
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800544 const float w_uscale = 1.0f / w_scale;
545 const float h_uscale = 1.0f / h_scale;
546
547 if(w_uscale > upscale || h_uscale > upscale)
548 return false;
549 }
550
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800551 return true;
552}
553
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800554bool MDPComp::isFrameDoable(hwc_context_t *ctx) {
Saurabh Shahaa236822013-04-24 18:07:26 -0700555 bool ret = true;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800556
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800557 if(!isEnabled()) {
558 ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
Saurabh Shahaa236822013-04-24 18:07:26 -0700559 ret = false;
Raj Kamal83605462015-05-27 11:30:16 +0530560 } else if (ctx->isDMAStateChanging) {
561 // Bail out if a padding round has been invoked in order to switch DMA
562 // state to block mode. We need this to cater for the case when a layer
563 // requires rotation in the current frame.
564 ALOGD_IF(isDebug(), "%s: padding round invoked to switch DMA state",
565 __FUNCTION__);
566 ret = false;
Saurabh Shah19740d02015-04-10 10:05:42 -0700567 } else if(ctx->mVideoTransFlag && isSecondaryConnected(ctx)) {
Saurabh Shahd4e65852013-06-17 11:33:53 -0700568 //1 Padding round to shift pipes across mixers
569 ALOGD_IF(isDebug(),"%s: MDP Comp. video transition padding round",
570 __FUNCTION__);
571 ret = false;
Raj Kamalc0d34242015-03-17 20:53:14 +0530572 } else if((qdutils::MDPVersion::getInstance().is8x26() ||
573 qdutils::MDPVersion::getInstance().is8x16() ||
Prabhanjan Kandulafc541b32015-03-30 20:56:16 +0530574 qdutils::MDPVersion::getInstance().is8x39() ||
575 qdutils::MDPVersion::getInstance().is8x52()) &&
Raj Kamalc0d34242015-03-17 20:53:14 +0530576 !mDpy && isSecondaryAnimating(ctx) &&
577 isYuvPresent(ctx,HWC_DISPLAY_VIRTUAL)) {
578 ALOGD_IF(isDebug(),"%s: Display animation in progress",
579 __FUNCTION__);
580 ret = false;
Ramkumar Radhakrishnanf26fe9e2014-09-09 13:47:54 -0700581 } else if(qdutils::MDPVersion::getInstance().getTotalPipes() < 8) {
582 /* TODO: freeing up all the resources only for the targets having total
583 number of pipes < 8. Need to analyze number of VIG pipes used
584 for primary in previous draw cycle and accordingly decide
585 whether to fall back to full GPU comp or video only comp
586 */
587 if(isSecondaryConfiguring(ctx)) {
588 ALOGD_IF( isDebug(),"%s: External Display connection is pending",
589 __FUNCTION__);
590 ret = false;
591 } else if(ctx->isPaddingRound) {
592 ALOGD_IF(isDebug(), "%s: padding round invoked for dpy %d",
593 __FUNCTION__,mDpy);
594 ret = false;
595 }
Saurabh Shah0ceeb6a2013-04-23 10:46:07 -0700596 }
Tatenda Chipeperekwadc8d7082014-11-04 16:41:50 -0800597
Saurabh Shahaa236822013-04-24 18:07:26 -0700598 return ret;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800599}
600
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800601void MDPCompNonSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect &crop,
602 hwc_rect &dst) {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800603 hwc_rect_t roi = ctx->listStats[mDpy].lRoi;
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800604 dst = getIntersection(dst, roi);
605 crop = dst;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800606}
607
608/* 1) Identify layers that are not visible or lying outside the updating ROI and
609 * drop them from composition.
610 * 2) If we have a scaling layer which needs cropping against generated
611 * ROI, reset ROI to full resolution. */
612bool MDPCompNonSplit::validateAndApplyROI(hwc_context_t *ctx,
613 hwc_display_contents_1_t* list) {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700614 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800615 hwc_rect_t visibleRect = ctx->listStats[mDpy].lRoi;
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800616
617 for(int i = numAppLayers - 1; i >= 0; i--){
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800618 if(!isValidRect(visibleRect)) {
619 mCurrentFrame.drop[i] = true;
620 mCurrentFrame.dropCount++;
Jeykumar Sankaran0b961452014-01-21 17:26:12 -0800621 continue;
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800622 }
623
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700624 const hwc_layer_1_t* layer = &list->hwLayers[i];
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700625 hwc_rect_t dstRect = layer->displayFrame;
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800626 hwc_rect_t res = getIntersection(visibleRect, dstRect);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700627
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700628 if(!isValidRect(res)) {
629 mCurrentFrame.drop[i] = true;
630 mCurrentFrame.dropCount++;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800631 } else {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700632 /* Reset frame ROI when any layer which needs scaling also needs ROI
633 * cropping */
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800634 if(!isSameRect(res, dstRect) && needsScaling (layer)) {
Arpita Banerjeed8965982013-11-08 17:27:33 -0800635 ALOGI("%s: Resetting ROI due to scaling", __FUNCTION__);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700636 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
637 mCurrentFrame.dropCount = 0;
638 return false;
639 }
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800640
Jeykumar Sankaran0b961452014-01-21 17:26:12 -0800641 /* deduct any opaque region from visibleRect */
radhakrishna4efbdd62014-11-03 13:19:27 +0530642 if (layer->blending == HWC_BLENDING_NONE &&
643 layer->planeAlpha == 0xFF)
Jeykumar Sankaran0b961452014-01-21 17:26:12 -0800644 visibleRect = deductRect(visibleRect, res);
645 }
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700646 }
647 return true;
648}
649
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800650/* Calculate ROI for the frame by accounting all the layer's dispalyFrame which
651 * are updating. If DirtyRegion is applicable, calculate it by accounting all
652 * the changing layer's dirtyRegion. */
653void MDPCompNonSplit::generateROI(hwc_context_t *ctx,
654 hwc_display_contents_1_t* list) {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700655 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800656 if(!canPartialUpdate(ctx, list))
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700657 return;
658
659 struct hwc_rect roi = (struct hwc_rect){0, 0, 0, 0};
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800660 hwc_rect fullFrame = (struct hwc_rect) {0, 0,(int)ctx->dpyAttr[mDpy].xres,
661 (int)ctx->dpyAttr[mDpy].yres};
662
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700663 for(int index = 0; index < numAppLayers; index++ ) {
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800664 hwc_layer_1_t* layer = &list->hwLayers[index];
665 if ((mCachedFrame.hnd[index] != layer->handle) ||
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800666 isYuvBuffer((private_handle_t *)layer->handle)) {
Jeykumar Sankaran455678c2014-05-30 10:22:38 -0700667 hwc_rect_t dst = layer->displayFrame;
668 hwc_rect_t updatingRect = dst;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800669
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800670#ifdef QCOM_BSP
Dileep Kumar Reddi7399d5c2014-12-31 18:01:19 +0530671 if(!needsScaling(layer) && !layer->transform &&
672 (!isYuvBuffer((private_handle_t *)layer->handle)))
Jeykumar Sankaran455678c2014-05-30 10:22:38 -0700673 {
674 hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
675 int x_off = dst.left - src.left;
676 int y_off = dst.top - src.top;
677 updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
678 }
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800679#endif
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800680
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800681 roi = getUnion(roi, updatingRect);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700682 }
683 }
684
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800685 /* No layer is updating. Still SF wants a refresh.*/
686 if(!isValidRect(roi))
687 return;
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800688
689 // Align ROI coordinates to panel restrictions
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800690 roi = getSanitizeROI(roi, fullFrame);
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800691
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800692 ctx->listStats[mDpy].lRoi = roi;
693 if(!validateAndApplyROI(ctx, list))
694 resetROI(ctx, mDpy);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700695
696 ALOGD_IF(isDebug(),"%s: generated ROI: [%d, %d, %d, %d]", __FUNCTION__,
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800697 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
698 ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom);
699}
700
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800701void MDPCompSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect &crop,
702 hwc_rect &dst) {
703 hwc_rect roi = getUnion(ctx->listStats[mDpy].lRoi,
704 ctx->listStats[mDpy].rRoi);
705 hwc_rect tmpDst = getIntersection(dst, roi);
706 if(!isSameRect(dst, tmpDst)) {
707 crop.left = crop.left + (tmpDst.left - dst.left);
708 crop.top = crop.top + (tmpDst.top - dst.top);
709 crop.right = crop.left + (tmpDst.right - tmpDst.left);
710 crop.bottom = crop.top + (tmpDst.bottom - tmpDst.top);
711 dst = tmpDst;
712 }
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800713}
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800714
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800715/* 1) Identify layers that are not visible or lying outside BOTH the updating
716 * ROI's and drop them from composition. If a layer is spanning across both
717 * the halves of the screen but needed by only ROI, the non-contributing
718 * half will not be programmed for MDP.
719 * 2) If we have a scaling layer which needs cropping against generated
720 * ROI, reset ROI to full resolution. */
721bool MDPCompSplit::validateAndApplyROI(hwc_context_t *ctx,
722 hwc_display_contents_1_t* list) {
723
724 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
725
726 hwc_rect_t visibleRectL = ctx->listStats[mDpy].lRoi;
727 hwc_rect_t visibleRectR = ctx->listStats[mDpy].rRoi;
728
729 for(int i = numAppLayers - 1; i >= 0; i--){
730 if(!isValidRect(visibleRectL) && !isValidRect(visibleRectR))
731 {
732 mCurrentFrame.drop[i] = true;
733 mCurrentFrame.dropCount++;
734 continue;
735 }
736
737 const hwc_layer_1_t* layer = &list->hwLayers[i];
738 hwc_rect_t dstRect = layer->displayFrame;
739
740 hwc_rect_t l_res = getIntersection(visibleRectL, dstRect);
741 hwc_rect_t r_res = getIntersection(visibleRectR, dstRect);
742 hwc_rect_t res = getUnion(l_res, r_res);
743
744 if(!isValidRect(l_res) && !isValidRect(r_res)) {
745 mCurrentFrame.drop[i] = true;
746 mCurrentFrame.dropCount++;
747 } else {
748 /* Reset frame ROI when any layer which needs scaling also needs ROI
749 * cropping */
750 if(!isSameRect(res, dstRect) && needsScaling (layer)) {
751 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
752 mCurrentFrame.dropCount = 0;
753 return false;
754 }
755
radhakrishna4efbdd62014-11-03 13:19:27 +0530756 if (layer->blending == HWC_BLENDING_NONE &&
757 layer->planeAlpha == 0xFF) {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800758 visibleRectL = deductRect(visibleRectL, l_res);
759 visibleRectR = deductRect(visibleRectR, r_res);
760 }
761 }
762 }
763 return true;
764}
765/* Calculate ROI for the frame by accounting all the layer's dispalyFrame which
766 * are updating. If DirtyRegion is applicable, calculate it by accounting all
767 * the changing layer's dirtyRegion. */
768void MDPCompSplit::generateROI(hwc_context_t *ctx,
769 hwc_display_contents_1_t* list) {
770 if(!canPartialUpdate(ctx, list))
771 return;
772
773 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
774 int lSplit = getLeftSplit(ctx, mDpy);
775
776 int hw_h = (int)ctx->dpyAttr[mDpy].yres;
777 int hw_w = (int)ctx->dpyAttr[mDpy].xres;
778
779 struct hwc_rect l_frame = (struct hwc_rect){0, 0, lSplit, hw_h};
780 struct hwc_rect r_frame = (struct hwc_rect){lSplit, 0, hw_w, hw_h};
781
782 struct hwc_rect l_roi = (struct hwc_rect){0, 0, 0, 0};
783 struct hwc_rect r_roi = (struct hwc_rect){0, 0, 0, 0};
784
785 for(int index = 0; index < numAppLayers; index++ ) {
786 hwc_layer_1_t* layer = &list->hwLayers[index];
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800787 private_handle_t *hnd = (private_handle_t *)layer->handle;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800788 if ((mCachedFrame.hnd[index] != layer->handle) ||
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800789 isYuvBuffer(hnd)) {
Jeykumar Sankaran71e597c2014-05-07 16:23:14 -0700790 hwc_rect_t dst = layer->displayFrame;
791 hwc_rect_t updatingRect = dst;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800792
793#ifdef QCOM_BSP
794 if(!needsScaling(layer) && !layer->transform)
Jeykumar Sankaran71e597c2014-05-07 16:23:14 -0700795 {
796 hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
797 int x_off = dst.left - src.left;
798 int y_off = dst.top - src.top;
799 updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
800 }
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800801#endif
802
803 hwc_rect_t l_dst = getIntersection(l_frame, updatingRect);
804 if(isValidRect(l_dst))
805 l_roi = getUnion(l_roi, l_dst);
806
807 hwc_rect_t r_dst = getIntersection(r_frame, updatingRect);
808 if(isValidRect(r_dst))
809 r_roi = getUnion(r_roi, r_dst);
810 }
811 }
812
Jeykumar Sankarana40a9342014-04-25 09:37:10 -0700813 /* For panels that cannot accept commands in both the interfaces, we cannot
814 * send two ROI's (for each half). We merge them into single ROI and split
815 * them across lSplit for MDP mixer use. The ROI's will be merged again
816 * finally before udpating the panel in the driver. */
817 if(qdutils::MDPVersion::getInstance().needsROIMerge()) {
818 hwc_rect_t temp_roi = getUnion(l_roi, r_roi);
819 l_roi = getIntersection(temp_roi, l_frame);
820 r_roi = getIntersection(temp_roi, r_frame);
821 }
822
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800823 /* No layer is updating. Still SF wants a refresh. */
824 if(!isValidRect(l_roi) && !isValidRect(r_roi))
825 return;
826
827 l_roi = getSanitizeROI(l_roi, l_frame);
828 r_roi = getSanitizeROI(r_roi, r_frame);
829
830 ctx->listStats[mDpy].lRoi = l_roi;
831 ctx->listStats[mDpy].rRoi = r_roi;
832
833 if(!validateAndApplyROI(ctx, list))
834 resetROI(ctx, mDpy);
835
836 ALOGD_IF(isDebug(),"%s: generated L_ROI: [%d, %d, %d, %d]"
837 "R_ROI: [%d, %d, %d, %d]", __FUNCTION__,
838 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
839 ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom,
840 ctx->listStats[mDpy].rRoi.left, ctx->listStats[mDpy].rRoi.top,
841 ctx->listStats[mDpy].rRoi.right, ctx->listStats[mDpy].rRoi.bottom);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700842}
843
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800844/* Checks for conditions where all the layers marked for MDP comp cannot be
845 * bypassed. On such conditions we try to bypass atleast YUV layers */
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800846bool MDPComp::tryFullFrame(hwc_context_t *ctx,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800847 hwc_display_contents_1_t* list){
848
Saurabh Shahaa236822013-04-24 18:07:26 -0700849 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800850
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -0700851 // Fall back to video only composition, if AIV video mode is enabled
852 if(ctx->listStats[mDpy].mAIVVideoMode) {
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -0700853 ALOGD_IF(isDebug(), "%s: AIV Video Mode enabled dpy %d",
854 __FUNCTION__, mDpy);
855 return false;
856 }
857
Praveena Pachipulusu47346c22014-12-04 11:06:41 +0530858 /* No Idle fall back if secure display or secure RGB layers are present
859 * or if there is only a single layer being composed */
860 if(sIdleFallBack && !ctx->listStats[mDpy].secureUI &&
861 !ctx->listStats[mDpy].secureRGBCount &&
862 (ctx->listStats[mDpy].numAppLayers > 1)) {
Saurabh Shah2d998a92013-05-14 17:55:58 -0700863 ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
864 return false;
865 }
866
Raj Kamalc0d34242015-03-17 20:53:14 +0530867 if(!mDpy && isSecondaryAnimating(ctx) &&
868 (isYuvPresent(ctx,HWC_DISPLAY_EXTERNAL) ||
869 isYuvPresent(ctx,HWC_DISPLAY_VIRTUAL)) ) {
870 ALOGD_IF(isDebug(),"%s: Display animation in progress",
871 __FUNCTION__);
872 return false;
873 }
874
Ramkumar Radhakrishnanf26fe9e2014-09-09 13:47:54 -0700875 // if secondary is configuring or Padding round, fall back to video only
876 // composition and release all assigned non VIG pipes from primary.
877 if(isSecondaryConfiguring(ctx)) {
878 ALOGD_IF( isDebug(),"%s: External Display connection is pending",
879 __FUNCTION__);
880 return false;
881 } else if(ctx->isPaddingRound) {
882 ALOGD_IF(isDebug(), "%s: padding round invoked for dpy %d",
883 __FUNCTION__,mDpy);
884 return false;
885 }
886
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -0500887 // No MDP composition for 3D
888 if(needs3DComposition(ctx, mDpy))
889 return false;
890
Tatenda Chipeperekwacb2a2432014-08-06 17:45:58 -0700891 // check for action safe flag and MDP scaling mode which requires scaling.
Ramkumar Radhakrishnan4af1ef02013-12-12 11:53:08 -0800892 if(ctx->dpyAttr[mDpy].mActionSafePresent
Tatenda Chipeperekwacb2a2432014-08-06 17:45:58 -0700893 || ctx->dpyAttr[mDpy].mMDPScalingMode) {
Ramkumar Radhakrishnan4af1ef02013-12-12 11:53:08 -0800894 ALOGD_IF(isDebug(), "%s: Scaling needed for this frame",__FUNCTION__);
895 return false;
896 }
897
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800898 for(int i = 0; i < numAppLayers; ++i) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800899 hwc_layer_1_t* layer = &list->hwLayers[i];
900 private_handle_t *hnd = (private_handle_t *)layer->handle;
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -0800901
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800902 if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700903 if(!canUseRotator(ctx, mDpy)) {
904 ALOGD_IF(isDebug(), "%s: Can't use rotator for dpy %d",
905 __FUNCTION__, mDpy);
Amara Venkata Mastan Manoj Kumar9d373c02013-08-20 14:30:09 -0700906 return false;
907 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800908 }
Prabhanjan Kandula9fb032a2013-06-18 17:37:22 +0530909
910 //For 8x26 with panel width>1k, if RGB layer needs HFLIP fail mdp comp
911 // may not need it if Gfx pre-rotation can handle all flips & rotations
Saurabh Shahcad57772014-12-01 14:19:51 -0800912 MDPVersion& mdpHw = MDPVersion::getInstance();
Sushil Chauhanfda00fc2014-03-20 11:08:41 -0700913 int transform = (layer->flags & HWC_COLOR_FILL) ? 0 : layer->transform;
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530914 if( mdpHw.is8x26() && (ctx->dpyAttr[mDpy].xres > 1024) &&
915 (transform & HWC_TRANSFORM_FLIP_H) && (!isYuvBuffer(hnd)))
916 return false;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800917 }
Saurabh Shahaa236822013-04-24 18:07:26 -0700918
Saurabh Shaha9da08f2013-07-03 13:27:53 -0700919 if(ctx->mAD->isDoable()) {
920 return false;
921 }
922
Saurabh Shahaa236822013-04-24 18:07:26 -0700923 //If all above hard conditions are met we can do full or partial MDP comp.
924 bool ret = false;
925 if(fullMDPComp(ctx, list)) {
926 ret = true;
Sushil Chauhandefd3522014-05-13 18:17:12 -0700927 } else if(fullMDPCompWithPTOR(ctx, list)) {
928 ret = true;
Jeykumar Sankaran24c199d2013-05-24 09:40:36 -0700929 } else if(partialMDPComp(ctx, list)) {
Saurabh Shahaa236822013-04-24 18:07:26 -0700930 ret = true;
931 }
Prabhanjan Kandula21918db2013-11-26 15:51:58 +0530932
Saurabh Shahaa236822013-04-24 18:07:26 -0700933 return ret;
934}
935
936bool MDPComp::fullMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -0700937
938 if(sSimulationFlags & MDPCOMP_AVOID_FULL_MDP)
939 return false;
940
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700941 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
942 for(int i = 0; i < numAppLayers; i++) {
943 hwc_layer_1_t* layer = &list->hwLayers[i];
Jeykumar Sankaran880da832014-04-18 10:22:35 -0700944 if(not mCurrentFrame.drop[i] and
945 not isSupportedForMDPComp(ctx, layer)) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700946 ALOGD_IF(isDebug(), "%s: Unsupported layer in list",__FUNCTION__);
947 return false;
948 }
949 }
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800950
Raj Kamalb5f0b4a2015-04-08 15:10:37 +0530951 if(!mDpy && isSecondaryConnected(ctx) &&
952 (qdutils::MDPVersion::getInstance().is8x16() ||
953 qdutils::MDPVersion::getInstance().is8x26() ||
954 qdutils::MDPVersion::getInstance().is8x39()) &&
955 isYuvPresent(ctx, HWC_DISPLAY_VIRTUAL)) {
956 ALOGD_IF(isDebug(), "%s: YUV layer present on secondary", __FUNCTION__);
957 return false;
958 }
959
Saurabh Shahaa236822013-04-24 18:07:26 -0700960 mCurrentFrame.fbCount = 0;
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700961 memcpy(&mCurrentFrame.isFBComposed, &mCurrentFrame.drop,
962 sizeof(mCurrentFrame.isFBComposed));
963 mCurrentFrame.mdpCount = mCurrentFrame.layerCount - mCurrentFrame.fbCount -
964 mCurrentFrame.dropCount;
Saurabh Shahaa236822013-04-24 18:07:26 -0700965
Raj Kamal389d6e32014-08-04 14:43:24 +0530966 if(sEnableYUVsplit){
Saurabh Shah3d4b8042013-12-10 15:19:17 -0800967 adjustForSourceSplit(ctx, list);
radhakrishnac9a67412013-09-25 17:40:42 +0530968 }
969
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800970 if(!postHeuristicsHandling(ctx, list)) {
971 ALOGD_IF(isDebug(), "post heuristic handling failed");
972 reset(ctx);
Saurabh Shah8c5c8522013-08-29 17:32:49 -0700973 return false;
974 }
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -0700975 ALOGD_IF(sSimulationFlags,"%s: FULL_MDP_COMP SUCCEEDED",
976 __FUNCTION__);
Saurabh Shahaa236822013-04-24 18:07:26 -0700977 return true;
978}
979
Sushil Chauhandefd3522014-05-13 18:17:12 -0700980/* Full MDP Composition with Peripheral Tiny Overlap Removal.
981 * MDP bandwidth limitations can be avoided, if the overlap region
982 * covered by the smallest layer at a higher z-order, gets composed
983 * by Copybit on a render buffer, which can be queued to MDP.
984 */
985bool MDPComp::fullMDPCompWithPTOR(hwc_context_t *ctx,
986 hwc_display_contents_1_t* list) {
987
988 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Arun Kumar K.R00b84792015-03-27 11:28:36 -0700989 // PTOR does not qualify when there are layers dropped, but if
990 // dropped layer is only a cursor, PTOR could qualify
991 const int numNonCursorLayers = numAppLayers - mCurrentFrame.dropCount;
Sushil Chauhandefd3522014-05-13 18:17:12 -0700992 const int stagesForMDP = min(sMaxPipesPerMixer,
993 ctx->mOverlay->availablePipes(mDpy, Overlay::MIXER_DEFAULT));
994
995 // Hard checks where we cannot use this mode
Sushil Chauhanbfc2de02014-07-24 11:52:58 -0700996 if (mDpy || !ctx->mCopyBit[mDpy]) {
Sushil Chauhandefd3522014-05-13 18:17:12 -0700997 ALOGD_IF(isDebug(), "%s: Feature not supported!", __FUNCTION__);
998 return false;
999 }
1000
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001001 // Frame level checks - consider PTOR in case of dropCount only if the cursor
1002 // layer is dropped, otherwise bail out of PTOR
Sushil Chauhandefd3522014-05-13 18:17:12 -07001003 if ((numAppLayers > stagesForMDP) || isSkipPresent(ctx, mDpy) ||
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001004 isYuvPresent(ctx, mDpy) || isSecurePresent(ctx, mDpy) ||
1005 (mCurrentFrame.dropCount - (int)isCursorPresent(ctx, mDpy))) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001006 ALOGD_IF(isDebug(), "%s: Frame not supported!", __FUNCTION__);
1007 return false;
1008 }
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001009 // MDP comp checks
1010 for(int i = 0; i < numAppLayers; i++) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001011 hwc_layer_1_t* layer = &list->hwLayers[i];
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001012 if(not isSupportedForMDPComp(ctx, layer)) {
1013 ALOGD_IF(isDebug(), "%s: Unsupported layer in list",__FUNCTION__);
1014 return false;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001015 }
1016 }
1017
Raj Kamalb5f0b4a2015-04-08 15:10:37 +05301018 if(!mDpy && isSecondaryConnected(ctx) &&
1019 (qdutils::MDPVersion::getInstance().is8x16() ||
1020 qdutils::MDPVersion::getInstance().is8x26() ||
1021 qdutils::MDPVersion::getInstance().is8x39()) &&
1022 isYuvPresent(ctx, HWC_DISPLAY_VIRTUAL)) {
1023 ALOGD_IF(isDebug(), "%s: YUV layer present on secondary", __FUNCTION__);
1024 return false;
1025 }
1026
Sushil Chauhandefd3522014-05-13 18:17:12 -07001027 /* We cannot use this composition mode, if:
1028 1. A below layer needs scaling.
1029 2. Overlap is not peripheral to display.
1030 3. Overlap or a below layer has 90 degree transform.
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001031 4. Overlap area > (1/3 * FrameBuffer) area, based on Perf inputs.
Sushil Chauhandefd3522014-05-13 18:17:12 -07001032 */
1033
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001034 int minLayerIndex[MAX_PTOR_LAYERS] = { -1, -1};
1035 hwc_rect_t overlapRect[MAX_PTOR_LAYERS];
1036 memset(overlapRect, 0, sizeof(overlapRect));
1037 int layerPixelCount, minPixelCount = 0;
1038 int numPTORLayersFound = 0;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001039 for (int i = numNonCursorLayers - 1; (i >= 0 &&
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001040 numPTORLayersFound < MAX_PTOR_LAYERS); i--) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001041 hwc_layer_1_t* layer = &list->hwLayers[i];
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001042 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
Sushil Chauhandefd3522014-05-13 18:17:12 -07001043 hwc_rect_t dispFrame = layer->displayFrame;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001044 layerPixelCount = (crop.right - crop.left) * (crop.bottom - crop.top);
1045 // PTOR layer should be peripheral and cannot have transform
1046 if (!isPeripheral(dispFrame, ctx->mViewFrame[mDpy]) ||
1047 has90Transform(layer)) {
1048 continue;
1049 }
1050 if((3 * (layerPixelCount + minPixelCount)) >
1051 ((int)ctx->dpyAttr[mDpy].xres * (int)ctx->dpyAttr[mDpy].yres)) {
1052 // Overlap area > (1/3 * FrameBuffer) area, based on Perf inputs.
1053 continue;
1054 }
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001055 bool found = false;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001056 for (int j = i-1; j >= 0; j--) {
1057 // Check if the layers below this layer qualifies for PTOR comp
1058 hwc_layer_1_t* layer = &list->hwLayers[j];
1059 hwc_rect_t disFrame = layer->displayFrame;
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001060 // Layer below PTOR is intersecting and has 90 degree transform or
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001061 // needs scaling cannot be supported.
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001062 if (isValidRect(getIntersection(dispFrame, disFrame))) {
1063 if (has90Transform(layer) || needsScaling(layer)) {
1064 found = false;
1065 break;
1066 }
1067 found = true;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001068 }
1069 }
1070 // Store the minLayer Index
1071 if(found) {
1072 minLayerIndex[numPTORLayersFound] = i;
1073 overlapRect[numPTORLayersFound] = list->hwLayers[i].displayFrame;
1074 minPixelCount += layerPixelCount;
1075 numPTORLayersFound++;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001076 }
1077 }
1078
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001079 // No overlap layers
1080 if (!numPTORLayersFound)
1081 return false;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001082
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001083 // Store the displayFrame and the sourceCrops of the layers
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001084 hwc_rect_t displayFrame[numNonCursorLayers];
1085 hwc_rect_t sourceCrop[numNonCursorLayers];
1086 for(int i = 0; i < numNonCursorLayers; i++) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001087 hwc_layer_1_t* layer = &list->hwLayers[i];
1088 displayFrame[i] = layer->displayFrame;
1089 sourceCrop[i] = integerizeSourceCrop(layer->sourceCropf);
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001090 }
Sushil Chauhandefd3522014-05-13 18:17:12 -07001091
Prabhanjan Kandula9889a202014-09-04 21:50:35 +05301092 /**
1093 * It's possible that 2 PTOR layers might have overlapping.
1094 * In such case, remove the intersection(again if peripheral)
1095 * from the lower PTOR layer to avoid overlapping.
1096 * If intersection is not on peripheral then compromise
1097 * by reducing number of PTOR layers.
1098 **/
1099 hwc_rect_t commonRect = getIntersection(overlapRect[0], overlapRect[1]);
1100 if(isValidRect(commonRect)) {
1101 overlapRect[1] = deductRect(overlapRect[1], commonRect);
1102 list->hwLayers[minLayerIndex[1]].displayFrame = overlapRect[1];
1103 }
1104
1105 ctx->mPtorInfo.count = numPTORLayersFound;
1106 for(int i = 0; i < MAX_PTOR_LAYERS; i++) {
1107 ctx->mPtorInfo.layerIndex[i] = minLayerIndex[i];
1108 }
1109
1110 if (!ctx->mCopyBit[mDpy]->prepareOverlap(ctx, list)) {
1111 // reset PTOR
1112 ctx->mPtorInfo.count = 0;
1113 if(isValidRect(commonRect)) {
1114 // If PTORs are intersecting restore displayframe of PTOR[1]
1115 // before returning, as we have modified it above.
1116 list->hwLayers[minLayerIndex[1]].displayFrame =
1117 displayFrame[minLayerIndex[1]];
1118 }
1119 return false;
1120 }
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001121 private_handle_t *renderBuf = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
1122 Whf layerWhf[numPTORLayersFound]; // To store w,h,f of PTOR layers
1123
Xu Yangcda012c2014-07-30 21:57:21 +08001124 // Store the blending mode, planeAlpha, and transform of PTOR layers
1125 int32_t blending[numPTORLayersFound];
1126 uint8_t planeAlpha[numPTORLayersFound];
1127 uint32_t transform[numPTORLayersFound];
1128
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001129 for(int j = 0; j < numPTORLayersFound; j++) {
1130 int index = ctx->mPtorInfo.layerIndex[j];
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001131
1132 // Update src crop of PTOR layer
1133 hwc_layer_1_t* layer = &list->hwLayers[index];
1134 layer->sourceCropf.left = (float)ctx->mPtorInfo.displayFrame[j].left;
1135 layer->sourceCropf.top = (float)ctx->mPtorInfo.displayFrame[j].top;
1136 layer->sourceCropf.right = (float)ctx->mPtorInfo.displayFrame[j].right;
1137 layer->sourceCropf.bottom =(float)ctx->mPtorInfo.displayFrame[j].bottom;
1138
1139 // Store & update w, h, format of PTOR layer
1140 private_handle_t *hnd = (private_handle_t *)layer->handle;
1141 Whf whf(hnd->width, hnd->height, hnd->format, hnd->size);
1142 layerWhf[j] = whf;
1143 hnd->width = renderBuf->width;
1144 hnd->height = renderBuf->height;
1145 hnd->format = renderBuf->format;
1146
Xu Yangcda012c2014-07-30 21:57:21 +08001147 // Store & update blending mode, planeAlpha and transform of PTOR layer
1148 blending[j] = layer->blending;
1149 planeAlpha[j] = layer->planeAlpha;
1150 transform[j] = layer->transform;
1151 layer->blending = HWC_BLENDING_NONE;
1152 layer->planeAlpha = 0xFF;
1153 layer->transform = 0;
1154
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001155 // Remove overlap from crop & displayFrame of below layers
1156 for (int i = 0; i < index && index !=-1; i++) {
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001157 layer = &list->hwLayers[i];
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001158 if(!isValidRect(getIntersection(layer->displayFrame,
1159 overlapRect[j]))) {
1160 continue;
1161 }
1162 // Update layer attributes
1163 hwc_rect_t srcCrop = integerizeSourceCrop(layer->sourceCropf);
1164 hwc_rect_t destRect = deductRect(layer->displayFrame,
Dileep Kumar Reddi72058b82014-11-11 16:03:03 +05301165 getIntersection(layer->displayFrame, overlapRect[j]));
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001166 qhwc::calculate_crop_rects(srcCrop, layer->displayFrame, destRect,
1167 layer->transform);
1168 layer->sourceCropf.left = (float)srcCrop.left;
1169 layer->sourceCropf.top = (float)srcCrop.top;
1170 layer->sourceCropf.right = (float)srcCrop.right;
1171 layer->sourceCropf.bottom = (float)srcCrop.bottom;
1172 }
Sushil Chauhandefd3522014-05-13 18:17:12 -07001173 }
1174
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001175 mCurrentFrame.mdpCount = numNonCursorLayers;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001176 mCurrentFrame.fbCount = 0;
1177 mCurrentFrame.fbZ = -1;
1178
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001179 for (int j = 0; j < numNonCursorLayers; j++) {
Dileep Kumar Reddi72058b82014-11-11 16:03:03 +05301180 if(isValidRect(list->hwLayers[j].displayFrame)) {
1181 mCurrentFrame.isFBComposed[j] = false;
1182 } else {
1183 mCurrentFrame.mdpCount--;
1184 mCurrentFrame.drop[j] = true;
1185 }
1186 }
Sushil Chauhandefd3522014-05-13 18:17:12 -07001187
1188 bool result = postHeuristicsHandling(ctx, list);
1189
1190 // Restore layer attributes
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001191 for(int i = 0; i < numNonCursorLayers; i++) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001192 hwc_layer_1_t* layer = &list->hwLayers[i];
1193 layer->displayFrame = displayFrame[i];
1194 layer->sourceCropf.left = (float)sourceCrop[i].left;
1195 layer->sourceCropf.top = (float)sourceCrop[i].top;
1196 layer->sourceCropf.right = (float)sourceCrop[i].right;
1197 layer->sourceCropf.bottom = (float)sourceCrop[i].bottom;
1198 }
1199
Xu Yangcda012c2014-07-30 21:57:21 +08001200 // Restore w,h,f, blending attributes, and transform of PTOR layers
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001201 for (int i = 0; i < numPTORLayersFound; i++) {
1202 int idx = ctx->mPtorInfo.layerIndex[i];
Xu Yangcda012c2014-07-30 21:57:21 +08001203 hwc_layer_1_t* layer = &list->hwLayers[idx];
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001204 private_handle_t *hnd = (private_handle_t *)list->hwLayers[idx].handle;
1205 hnd->width = layerWhf[i].w;
1206 hnd->height = layerWhf[i].h;
1207 hnd->format = layerWhf[i].format;
Xu Yangcda012c2014-07-30 21:57:21 +08001208 layer->blending = blending[i];
1209 layer->planeAlpha = planeAlpha[i];
1210 layer->transform = transform[i];
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001211 }
1212
Sushil Chauhandefd3522014-05-13 18:17:12 -07001213 if (!result) {
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001214 // reset PTOR
1215 ctx->mPtorInfo.count = 0;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001216 reset(ctx);
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001217 } else {
1218 ALOGD_IF(isDebug(), "%s: PTOR Indexes: %d and %d", __FUNCTION__,
1219 ctx->mPtorInfo.layerIndex[0], ctx->mPtorInfo.layerIndex[1]);
Sushil Chauhandefd3522014-05-13 18:17:12 -07001220 }
1221
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001222 ALOGD_IF(isDebug(), "%s: Postheuristics %s!", __FUNCTION__,
1223 (result ? "successful" : "failed"));
Sushil Chauhandefd3522014-05-13 18:17:12 -07001224 return result;
1225}
1226
Saurabh Shahaa236822013-04-24 18:07:26 -07001227bool MDPComp::partialMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list)
1228{
radhakrishnac3198ff2015-03-10 17:10:02 +05301229 if(!sEnableMixedMode || !isAlphaPresentinFB(ctx, mDpy)) {
1230 //Mixed mode is disabled/can't be used. No need to even try caching.
Jeykumar Sankaran24c199d2013-05-24 09:40:36 -07001231 return false;
1232 }
1233
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001234 bool ret = false;
Raj Kamal1179d9c2014-10-28 15:31:35 +05301235 if(isSkipPresent(ctx, mDpy) or list->flags & HWC_GEOMETRY_CHANGED) {
1236 //Try load based first
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001237 ret = loadBasedComp(ctx, list) or
Saurabh Shahf2de00f2013-12-11 17:52:53 -08001238 cacheBasedComp(ctx, list);
1239 } else {
1240 ret = cacheBasedComp(ctx, list) or
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001241 loadBasedComp(ctx, list);
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001242 }
1243
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001244 return ret;
1245}
1246
1247bool MDPComp::cacheBasedComp(hwc_context_t *ctx,
1248 hwc_display_contents_1_t* list) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001249 if(sSimulationFlags & MDPCOMP_AVOID_CACHE_MDP)
1250 return false;
1251
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001252 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shahaa236822013-04-24 18:07:26 -07001253 mCurrentFrame.reset(numAppLayers);
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001254 updateLayerCache(ctx, list, mCurrentFrame);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001255
1256 //If an MDP marked layer is unsupported cannot do partial MDP Comp
1257 for(int i = 0; i < numAppLayers; i++) {
1258 if(!mCurrentFrame.isFBComposed[i]) {
1259 hwc_layer_1_t* layer = &list->hwLayers[i];
1260 if(not isSupportedForMDPComp(ctx, layer)) {
1261 ALOGD_IF(isDebug(), "%s: Unsupported layer in list",
1262 __FUNCTION__);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001263 reset(ctx);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001264 return false;
1265 }
1266 }
1267 }
1268
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001269 updateYUV(ctx, list, false /*secure only*/, mCurrentFrame);
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001270 /* mark secure RGB layers for MDP comp */
1271 updateSecureRGB(ctx, list);
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301272 bool ret = markLayersForCaching(ctx, list); //sets up fbZ also
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001273 if(!ret) {
1274 ALOGD_IF(isDebug(),"%s: batching failed, dpy %d",__FUNCTION__, mDpy);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001275 reset(ctx);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001276 return false;
1277 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001278
1279 int mdpCount = mCurrentFrame.mdpCount;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001280
Raj Kamal389d6e32014-08-04 14:43:24 +05301281 if(sEnableYUVsplit){
Saurabh Shah3d4b8042013-12-10 15:19:17 -08001282 adjustForSourceSplit(ctx, list);
radhakrishnac9a67412013-09-25 17:40:42 +05301283 }
1284
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001285 if(!postHeuristicsHandling(ctx, list)) {
1286 ALOGD_IF(isDebug(), "post heuristic handling failed");
1287 reset(ctx);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07001288 return false;
1289 }
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001290 ALOGD_IF(sSimulationFlags,"%s: CACHE_MDP_COMP SUCCEEDED",
1291 __FUNCTION__);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07001292
Saurabh Shahaa236822013-04-24 18:07:26 -07001293 return true;
1294}
1295
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001296bool MDPComp::loadBasedComp(hwc_context_t *ctx,
Saurabh Shahb772ae32013-11-18 15:40:02 -08001297 hwc_display_contents_1_t* list) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001298 if(sSimulationFlags & MDPCOMP_AVOID_LOAD_MDP)
1299 return false;
1300
Arun Kumar K.R2aa44c62014-01-21 23:08:28 -08001301 if(not isLoadBasedCompDoable(ctx)) {
Saurabh Shahf2de00f2013-12-11 17:52:53 -08001302 return false;
1303 }
1304
Saurabh Shahb772ae32013-11-18 15:40:02 -08001305 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001306 const int numNonDroppedLayers = numAppLayers - mCurrentFrame.dropCount;
1307 const int stagesForMDP = min(sMaxPipesPerMixer,
1308 ctx->mOverlay->availablePipes(mDpy, Overlay::MIXER_DEFAULT));
Saurabh Shahf2de00f2013-12-11 17:52:53 -08001309
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001310 int mdpBatchSize = stagesForMDP - 1; //1 stage for FB
1311 int fbBatchSize = numNonDroppedLayers - mdpBatchSize;
1312 int lastMDPSupportedIndex = numAppLayers;
1313 int dropCount = 0;
Saurabh Shahb772ae32013-11-18 15:40:02 -08001314
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001315 //Find the minimum MDP batch size
1316 for(int i = 0; i < numAppLayers;i++) {
1317 if(mCurrentFrame.drop[i]) {
1318 dropCount++;
Jeykumar Sankaran846e2792014-01-23 21:59:58 -08001319 continue;
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001320 }
1321 hwc_layer_1_t* layer = &list->hwLayers[i];
1322 if(not isSupportedForMDPComp(ctx, layer)) {
1323 lastMDPSupportedIndex = i;
1324 mdpBatchSize = min(i - dropCount, stagesForMDP - 1);
1325 fbBatchSize = numNonDroppedLayers - mdpBatchSize;
Jeykumar Sankaran846e2792014-01-23 21:59:58 -08001326 break;
Saurabh Shahb772ae32013-11-18 15:40:02 -08001327 }
Saurabh Shahb772ae32013-11-18 15:40:02 -08001328 }
1329
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001330 ALOGD_IF(isDebug(), "%s:Before optimizing fbBatch, mdpbatch %d, fbbatch %d "
1331 "dropped %d", __FUNCTION__, mdpBatchSize, fbBatchSize,
1332 mCurrentFrame.dropCount);
1333
1334 //Start at a point where the fb batch should at least have 2 layers, for
1335 //this mode to be justified.
1336 while(fbBatchSize < 2) {
1337 ++fbBatchSize;
1338 --mdpBatchSize;
Jeykumar Sankaran846e2792014-01-23 21:59:58 -08001339 }
Saurabh Shahb772ae32013-11-18 15:40:02 -08001340
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001341 //If there are no layers for MDP, this mode doesnt make sense.
1342 if(mdpBatchSize < 1) {
1343 ALOGD_IF(isDebug(), "%s: No MDP layers after optimizing for fbBatch",
1344 __FUNCTION__);
Saurabh Shahb772ae32013-11-18 15:40:02 -08001345 return false;
1346 }
1347
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001348 mCurrentFrame.reset(numAppLayers);
1349
1350 //Try with successively smaller mdp batch sizes until we succeed or reach 1
1351 while(mdpBatchSize > 0) {
1352 //Mark layers for MDP comp
1353 int mdpBatchLeft = mdpBatchSize;
1354 for(int i = 0; i < lastMDPSupportedIndex and mdpBatchLeft; i++) {
1355 if(mCurrentFrame.drop[i]) {
1356 continue;
1357 }
1358 mCurrentFrame.isFBComposed[i] = false;
1359 --mdpBatchLeft;
1360 }
1361
1362 mCurrentFrame.fbZ = mdpBatchSize;
1363 mCurrentFrame.fbCount = fbBatchSize;
1364 mCurrentFrame.mdpCount = mdpBatchSize;
1365
1366 ALOGD_IF(isDebug(), "%s:Trying with: mdpbatch %d fbbatch %d dropped %d",
1367 __FUNCTION__, mdpBatchSize, fbBatchSize,
1368 mCurrentFrame.dropCount);
1369
1370 if(postHeuristicsHandling(ctx, list)) {
1371 ALOGD_IF(isDebug(), "%s: Postheuristics handling succeeded",
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001372 __FUNCTION__);
1373 ALOGD_IF(sSimulationFlags,"%s: LOAD_MDP_COMP SUCCEEDED",
1374 __FUNCTION__);
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001375 return true;
1376 }
1377
1378 reset(ctx);
1379 --mdpBatchSize;
1380 ++fbBatchSize;
1381 }
1382
1383 return false;
Saurabh Shahb772ae32013-11-18 15:40:02 -08001384}
1385
Arun Kumar K.R2aa44c62014-01-21 23:08:28 -08001386bool MDPComp::isLoadBasedCompDoable(hwc_context_t *ctx) {
Prabhanjan Kandula3dbbd882013-12-11 14:43:46 +05301387 if(mDpy or isSecurePresent(ctx, mDpy) or
1388 isYuvPresent(ctx, mDpy)) {
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001389 return false;
1390 }
1391 return true;
1392}
1393
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001394bool MDPComp::canPartialUpdate(hwc_context_t *ctx,
1395 hwc_display_contents_1_t* list){
1396 if(!qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() ||
1397 isSkipPresent(ctx, mDpy) || (list->flags & HWC_GEOMETRY_CHANGED) ||
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001398 isCursorPresent(ctx, mDpy) || !sIsPartialUpdateActive || mDpy) {
1399 // On Async position update, the ROI becomes invalid, hence disable PU
1400 // when cursor is present
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001401 return false;
1402 }
Jeykumar Sankaran4dd10ab2014-07-02 12:23:09 -07001403 if(ctx->listStats[mDpy].secureUI)
1404 return false;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001405 return true;
1406}
1407
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001408bool MDPComp::tryVideoOnly(hwc_context_t *ctx,
1409 hwc_display_contents_1_t* list) {
1410 const bool secureOnly = true;
1411 return videoOnlyComp(ctx, list, not secureOnly) or
1412 videoOnlyComp(ctx, list, secureOnly);
1413}
1414
1415bool MDPComp::videoOnlyComp(hwc_context_t *ctx,
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001416 hwc_display_contents_1_t* list, bool secureOnly) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001417 if(sSimulationFlags & MDPCOMP_AVOID_VIDEO_ONLY)
1418 return false;
Praveena Pachipulusu47346c22014-12-04 11:06:41 +05301419
Saurabh Shahaa236822013-04-24 18:07:26 -07001420 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Praveena Pachipulusu47346c22014-12-04 11:06:41 +05301421 if(!isSecurePresent(ctx, mDpy)) {
1422 /* Bail out if we are processing only secured video layers
1423 * and we dont have any */
1424 if(secureOnly) {
1425 ALOGD_IF(isDebug(),"%s: No Secure Video Layers", __FUNCTION__);
1426 return false;
1427 }
1428 /* No Idle fall back for secure video layers and if there is only
1429 * single layer being composed. */
1430 if(sIdleFallBack && (ctx->listStats[mDpy].numAppLayers > 1)) {
1431 ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
1432 return false;
1433 }
1434 }
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001435
Saurabh Shahaa236822013-04-24 18:07:26 -07001436 mCurrentFrame.reset(numAppLayers);
Jeykumar Sankaraneb3a5e22014-04-08 16:07:55 -07001437 mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001438 updateYUV(ctx, list, secureOnly, mCurrentFrame);
Saurabh Shah4fdde762013-04-30 18:47:33 -07001439 int mdpCount = mCurrentFrame.mdpCount;
Saurabh Shahaa236822013-04-24 18:07:26 -07001440
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001441 if(!isYuvPresent(ctx, mDpy) or (mdpCount == 0)) {
1442 reset(ctx);
Saurabh Shahaa236822013-04-24 18:07:26 -07001443 return false;
1444 }
1445
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001446 if(mCurrentFrame.fbCount)
1447 mCurrentFrame.fbZ = mCurrentFrame.mdpCount;
Saurabh Shah4fdde762013-04-30 18:47:33 -07001448
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05001449 if(sEnableYUVsplit || needs3DComposition(ctx, mDpy)){
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001450 adjustForSourceSplit(ctx, list);
1451 }
1452
1453 if(!postHeuristicsHandling(ctx, list)) {
1454 ALOGD_IF(isDebug(), "post heuristic handling failed");
Justin Philip37ab9a82015-01-06 11:55:12 +05301455 if(errno == ENOBUFS) {
1456 ALOGD_IF(isDebug(), "SMP Allocation failed");
1457 //On SMP allocation failure in video only comp add padding round
1458 ctx->isPaddingRound = true;
1459 }
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001460 reset(ctx);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07001461 return false;
1462 }
1463
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001464 ALOGD_IF(sSimulationFlags,"%s: VIDEO_ONLY_COMP SUCCEEDED",
1465 __FUNCTION__);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001466 return true;
1467}
1468
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001469/* if tryFullFrame fails, try to push all video and secure RGB layers to MDP */
1470bool MDPComp::tryMDPOnlyLayers(hwc_context_t *ctx,
1471 hwc_display_contents_1_t* list) {
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001472 // Fall back to video only composition, if AIV video mode is enabled
1473 if(ctx->listStats[mDpy].mAIVVideoMode) {
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07001474 ALOGD_IF(isDebug(), "%s: AIV Video Mode enabled dpy %d",
1475 __FUNCTION__, mDpy);
1476 return false;
1477 }
1478
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05001479 // No MDP composition for 3D
1480 if(needs3DComposition(ctx,mDpy))
1481 return false;
1482
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001483 const bool secureOnly = true;
1484 return mdpOnlyLayersComp(ctx, list, not secureOnly) or
1485 mdpOnlyLayersComp(ctx, list, secureOnly);
1486
1487}
1488
1489bool MDPComp::mdpOnlyLayersComp(hwc_context_t *ctx,
1490 hwc_display_contents_1_t* list, bool secureOnly) {
1491
1492 if(sSimulationFlags & MDPCOMP_AVOID_MDP_ONLY_LAYERS)
1493 return false;
1494
Praveena Pachipulusu47346c22014-12-04 11:06:41 +05301495 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
1496 if(!isSecurePresent(ctx, mDpy) && !ctx->listStats[mDpy].secureUI) {
1497 /* Bail out if we are processing only secured video/ui layers
1498 * and we dont have any */
1499 if(secureOnly) {
1500 ALOGD_IF(isDebug(), "%s: No secure video/ui layers");
1501 return false;
1502 }
1503 /* No Idle fall back for secure video/ui layers and if there is only
1504 * single layer being composed. */
1505 if(sIdleFallBack && (ctx->listStats[mDpy].numAppLayers > 1)) {
1506 ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
1507 return false;
1508 }
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001509 }
1510
Tatenda Chipeperekwa95675a72014-12-15 17:06:43 -08001511 /* Bail out if we dont have any secure RGB layers */
1512 if (!ctx->listStats[mDpy].secureRGBCount) {
1513 reset(ctx);
1514 return false;
1515 }
1516
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001517 mCurrentFrame.reset(numAppLayers);
1518 mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
1519
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001520 updateYUV(ctx, list, secureOnly, mCurrentFrame);
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001521 /* mark secure RGB layers for MDP comp */
1522 updateSecureRGB(ctx, list);
1523
1524 if(mCurrentFrame.mdpCount == 0) {
1525 reset(ctx);
1526 return false;
1527 }
1528
1529 /* find the maximum batch of layers to be marked for framebuffer */
1530 bool ret = markLayersForCaching(ctx, list); //sets up fbZ also
1531 if(!ret) {
1532 ALOGD_IF(isDebug(),"%s: batching failed, dpy %d",__FUNCTION__, mDpy);
1533 reset(ctx);
1534 return false;
1535 }
1536
1537 if(sEnableYUVsplit){
1538 adjustForSourceSplit(ctx, list);
1539 }
1540
1541 if(!postHeuristicsHandling(ctx, list)) {
1542 ALOGD_IF(isDebug(), "post heuristic handling failed");
1543 reset(ctx);
1544 return false;
1545 }
1546
1547 ALOGD_IF(sSimulationFlags,"%s: MDP_ONLY_LAYERS_COMP SUCCEEDED",
1548 __FUNCTION__);
1549 return true;
1550}
1551
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001552/* Checks for conditions where YUV layers cannot be bypassed */
1553bool MDPComp::isYUVDoable(hwc_context_t* ctx, hwc_layer_1_t* layer) {
Ramkumar Radhakrishnana70981a2013-08-28 11:33:53 -07001554 if(isSkipLayer(layer)) {
Saurabh Shahe2474082013-05-15 16:32:13 -07001555 ALOGD_IF(isDebug(), "%s: Video marked SKIP dpy %d", __FUNCTION__, mDpy);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001556 return false;
1557 }
1558
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08001559 if(has90Transform(layer) && !canUseRotator(ctx, mDpy)) {
Amara Venkata Mastan Manoj Kumar9d373c02013-08-20 14:30:09 -07001560 ALOGD_IF(isDebug(), "%s: no free DMA pipe",__FUNCTION__);
1561 return false;
1562 }
1563
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001564 if(isSecuring(ctx, layer)) {
1565 ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
1566 return false;
1567 }
1568
Saurabh Shah4fdde762013-04-30 18:47:33 -07001569 if(!isValidDimension(ctx, layer)) {
1570 ALOGD_IF(isDebug(), "%s: Buffer is of invalid width",
1571 __FUNCTION__);
1572 return false;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001573 }
Saurabh Shah4fdde762013-04-30 18:47:33 -07001574
Naseer Ahmeddc61a972013-07-10 17:50:54 -04001575 if(layer->planeAlpha < 0xFF) {
1576 ALOGD_IF(isDebug(), "%s: Cannot handle YUV layer with plane alpha\
1577 in video only mode",
1578 __FUNCTION__);
1579 return false;
1580 }
1581
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001582 return true;
1583}
1584
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001585/* Checks for conditions where Secure RGB layers cannot be bypassed */
1586bool MDPComp::isSecureRGBDoable(hwc_context_t* ctx, hwc_layer_1_t* layer) {
1587 if(isSkipLayer(layer)) {
1588 ALOGD_IF(isDebug(), "%s: Secure RGB layer marked SKIP dpy %d",
1589 __FUNCTION__, mDpy);
1590 return false;
1591 }
1592
1593 if(isSecuring(ctx, layer)) {
1594 ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
1595 return false;
1596 }
1597
1598 if(not isSupportedForMDPComp(ctx, layer)) {
1599 ALOGD_IF(isDebug(), "%s: Unsupported secure RGB layer",
1600 __FUNCTION__);
1601 return false;
1602 }
1603 return true;
1604}
1605
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301606/* starts at fromIndex and check for each layer to find
1607 * if it it has overlapping with any Updating layer above it in zorder
1608 * till the end of the batch. returns true if it finds any intersection */
1609bool MDPComp::canPushBatchToTop(const hwc_display_contents_1_t* list,
1610 int fromIndex, int toIndex) {
1611 for(int i = fromIndex; i < toIndex; i++) {
1612 if(mCurrentFrame.isFBComposed[i] && !mCurrentFrame.drop[i]) {
1613 if(intersectingUpdatingLayers(list, i+1, toIndex, i)) {
1614 return false;
1615 }
1616 }
1617 }
1618 return true;
1619}
1620
1621/* Checks if given layer at targetLayerIndex has any
1622 * intersection with all the updating layers in beween
1623 * fromIndex and toIndex. Returns true if it finds intersectiion */
1624bool MDPComp::intersectingUpdatingLayers(const hwc_display_contents_1_t* list,
1625 int fromIndex, int toIndex, int targetLayerIndex) {
1626 for(int i = fromIndex; i <= toIndex; i++) {
1627 if(!mCurrentFrame.isFBComposed[i]) {
1628 if(areLayersIntersecting(&list->hwLayers[i],
1629 &list->hwLayers[targetLayerIndex])) {
1630 return true;
1631 }
1632 }
1633 }
1634 return false;
1635}
1636
1637int MDPComp::getBatch(hwc_display_contents_1_t* list,
1638 int& maxBatchStart, int& maxBatchEnd,
1639 int& maxBatchCount) {
1640 int i = 0;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301641 int fbZOrder =-1;
Jeykumar Sankaran9502f352014-01-20 12:25:32 -08001642 int droppedLayerCt = 0;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301643 while (i < mCurrentFrame.layerCount) {
1644 int batchCount = 0;
1645 int batchStart = i;
1646 int batchEnd = i;
Jeykumar Sankaran9502f352014-01-20 12:25:32 -08001647 /* Adjust batch Z order with the dropped layers so far */
1648 int fbZ = batchStart - droppedLayerCt;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301649 int firstZReverseIndex = -1;
Prabhanjan Kandula0ed2cc92013-12-06 12:39:04 +05301650 int updatingLayersAbove = 0;//Updating layer count in middle of batch
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301651 while(i < mCurrentFrame.layerCount) {
1652 if(!mCurrentFrame.isFBComposed[i]) {
1653 if(!batchCount) {
1654 i++;
1655 break;
1656 }
1657 updatingLayersAbove++;
1658 i++;
1659 continue;
1660 } else {
1661 if(mCurrentFrame.drop[i]) {
1662 i++;
Jeykumar Sankaran9502f352014-01-20 12:25:32 -08001663 droppedLayerCt++;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301664 continue;
1665 } else if(updatingLayersAbove <= 0) {
1666 batchCount++;
1667 batchEnd = i;
1668 i++;
1669 continue;
1670 } else { //Layer is FBComposed, not a drop & updatingLayer > 0
1671
1672 // We have a valid updating layer already. If layer-i not
1673 // have overlapping with all updating layers in between
1674 // batch-start and i, then we can add layer i to batch.
1675 if(!intersectingUpdatingLayers(list, batchStart, i-1, i)) {
1676 batchCount++;
1677 batchEnd = i;
1678 i++;
1679 continue;
1680 } else if(canPushBatchToTop(list, batchStart, i)) {
1681 //If All the non-updating layers with in this batch
1682 //does not have intersection with the updating layers
1683 //above in z-order, then we can safely move the batch to
1684 //higher z-order. Increment fbZ as it is moving up.
1685 if( firstZReverseIndex < 0) {
1686 firstZReverseIndex = i;
1687 }
1688 batchCount++;
1689 batchEnd = i;
1690 fbZ += updatingLayersAbove;
1691 i++;
1692 updatingLayersAbove = 0;
1693 continue;
1694 } else {
1695 //both failed.start the loop again from here.
1696 if(firstZReverseIndex >= 0) {
1697 i = firstZReverseIndex;
1698 }
1699 break;
1700 }
1701 }
1702 }
1703 }
1704 if(batchCount > maxBatchCount) {
1705 maxBatchCount = batchCount;
1706 maxBatchStart = batchStart;
1707 maxBatchEnd = batchEnd;
1708 fbZOrder = fbZ;
1709 }
1710 }
1711 return fbZOrder;
1712}
1713
1714bool MDPComp::markLayersForCaching(hwc_context_t* ctx,
1715 hwc_display_contents_1_t* list) {
1716 /* Idea is to keep as many non-updating(cached) layers in FB and
1717 * send rest of them through MDP. This is done in 2 steps.
1718 * 1. Find the maximum contiguous batch of non-updating layers.
1719 * 2. See if we can improve this batch size for caching by adding
1720 * opaque layers around the batch, if they don't have
1721 * any overlapping with the updating layers in between.
1722 * NEVER mark an updating layer for caching.
1723 * But cached ones can be marked for MDP */
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001724
1725 int maxBatchStart = -1;
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001726 int maxBatchEnd = -1;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001727 int maxBatchCount = 0;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301728 int fbZ = -1;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001729
Saurabh Shahd53bc5f2014-02-05 10:17:43 -08001730 /* Nothing is cached. No batching needed */
1731 if(mCurrentFrame.fbCount == 0) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001732 return true;
Saurabh Shahaa236822013-04-24 18:07:26 -07001733 }
Saurabh Shahd53bc5f2014-02-05 10:17:43 -08001734
1735 /* No MDP comp layers, try to use other comp modes */
1736 if(mCurrentFrame.mdpCount == 0) {
1737 return false;
Saurabh Shahaa236822013-04-24 18:07:26 -07001738 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001739
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301740 fbZ = getBatch(list, maxBatchStart, maxBatchEnd, maxBatchCount);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001741
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301742 /* reset rest of the layers lying inside ROI for MDP comp */
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001743 for(int i = 0; i < mCurrentFrame.layerCount; i++) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001744 hwc_layer_1_t* layer = &list->hwLayers[i];
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001745 if((i < maxBatchStart || i > maxBatchEnd) &&
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301746 mCurrentFrame.isFBComposed[i]){
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001747 if(!mCurrentFrame.drop[i]){
1748 //If an unsupported layer is being attempted to
1749 //be pulled out we should fail
1750 if(not isSupportedForMDPComp(ctx, layer)) {
1751 return false;
1752 }
1753 mCurrentFrame.isFBComposed[i] = false;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001754 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001755 }
1756 }
1757
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301758 // update the frame data
1759 mCurrentFrame.fbZ = fbZ;
1760 mCurrentFrame.fbCount = maxBatchCount;
Saurabh Shahaa236822013-04-24 18:07:26 -07001761 mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001762 mCurrentFrame.fbCount - mCurrentFrame.dropCount;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001763
1764 ALOGD_IF(isDebug(),"%s: cached count: %d",__FUNCTION__,
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301765 mCurrentFrame.fbCount);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001766
1767 return true;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001768}
Saurabh Shah85234ec2013-04-12 17:09:00 -07001769
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001770void MDPComp::updateLayerCache(hwc_context_t* ctx,
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001771 hwc_display_contents_1_t* list, FrameInfo& frame) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001772 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001773 int fbCount = 0;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001774
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001775 for(int i = 0; i < numAppLayers; i++) {
1776 if (mCachedFrame.hnd[i] == list->hwLayers[i].handle) {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001777 if(!frame.drop[i])
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001778 fbCount++;
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001779 frame.isFBComposed[i] = true;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001780 } else {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001781 frame.isFBComposed[i] = false;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001782 }
1783 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001784
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001785 frame.fbCount = fbCount;
1786 frame.mdpCount = frame.layerCount - frame.fbCount
1787 - frame.dropCount;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001788
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001789 ALOGD_IF(isDebug(),"%s: MDP count: %d FB count %d drop count: %d",
1790 __FUNCTION__, frame.mdpCount, frame.fbCount, frame.dropCount);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001791}
1792
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001793// drop other non-AIV layers from external display list.
1794void MDPComp::dropNonAIVLayers(hwc_context_t* ctx,
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07001795 hwc_display_contents_1_t* list) {
1796 for (size_t i = 0; i < (size_t)ctx->listStats[mDpy].numAppLayers; i++) {
1797 hwc_layer_1_t * layer = &list->hwLayers[i];
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001798 if(!(isAIVVideoLayer(layer) || isAIVCCLayer(layer))) {
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07001799 mCurrentFrame.dropCount++;
1800 mCurrentFrame.drop[i] = true;
1801 }
1802 }
1803 mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
1804 mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
1805 mCurrentFrame.fbCount - mCurrentFrame.dropCount;
1806 ALOGD_IF(isDebug(),"%s: fb count: %d mdp count %d drop count %d",
1807 __FUNCTION__, mCurrentFrame.fbCount, mCurrentFrame.mdpCount,
1808 mCurrentFrame.dropCount);
1809}
1810
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001811void MDPComp::updateYUV(hwc_context_t* ctx, hwc_display_contents_1_t* list,
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001812 bool secureOnly, FrameInfo& frame) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001813 int nYuvCount = ctx->listStats[mDpy].yuvCount;
radhakrishna03640472015-05-25 17:34:13 +05301814 int nVGpipes = qdutils::MDPVersion::getInstance().getVGPipes();
1815
1816 /* If number of YUV layers in the layer list is more than the number of
1817 VG pipes available in the target (non-split), try to program maximum
1818 possible number of YUV layers to MDP, instead of falling back to GPU
1819 completely.*/
1820 nYuvCount = (nYuvCount > nVGpipes) ? nVGpipes : nYuvCount;
1821
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001822 for(int index = 0;index < nYuvCount; index++){
1823 int nYuvIndex = ctx->listStats[mDpy].yuvIndices[index];
1824 hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
1825
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001826 if(mCurrentFrame.drop[nYuvIndex]) {
1827 continue;
1828 }
1829
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001830 if(!isYUVDoable(ctx, layer)) {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001831 if(!frame.isFBComposed[nYuvIndex]) {
1832 frame.isFBComposed[nYuvIndex] = true;
1833 frame.fbCount++;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001834 }
1835 } else {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001836 if(frame.isFBComposed[nYuvIndex]) {
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001837 private_handle_t *hnd = (private_handle_t *)layer->handle;
Arun Kumar K.R7b1f1522015-06-01 19:55:47 -07001838 if(!secureOnly || isSecureBuffer(hnd) ||
1839 isProtectedBuffer(hnd)) {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001840 frame.isFBComposed[nYuvIndex] = false;
1841 frame.fbCount--;
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001842 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001843 }
1844 }
1845 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001846
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001847 frame.mdpCount = frame.layerCount - frame.fbCount - frame.dropCount;
1848 ALOGD_IF(isDebug(),"%s: fb count: %d",__FUNCTION__, frame.fbCount);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001849}
1850
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001851void MDPComp::updateSecureRGB(hwc_context_t* ctx,
1852 hwc_display_contents_1_t* list) {
1853 int nSecureRGBCount = ctx->listStats[mDpy].secureRGBCount;
1854 for(int index = 0;index < nSecureRGBCount; index++){
1855 int nSecureRGBIndex = ctx->listStats[mDpy].secureRGBIndices[index];
1856 hwc_layer_1_t* layer = &list->hwLayers[nSecureRGBIndex];
1857
1858 if(!isSecureRGBDoable(ctx, layer)) {
1859 if(!mCurrentFrame.isFBComposed[nSecureRGBIndex]) {
1860 mCurrentFrame.isFBComposed[nSecureRGBIndex] = true;
1861 mCurrentFrame.fbCount++;
1862 }
1863 } else {
1864 if(mCurrentFrame.isFBComposed[nSecureRGBIndex]) {
1865 mCurrentFrame.isFBComposed[nSecureRGBIndex] = false;
1866 mCurrentFrame.fbCount--;
1867 }
1868 }
1869 }
1870
1871 mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
1872 mCurrentFrame.fbCount - mCurrentFrame.dropCount;
1873 ALOGD_IF(isDebug(),"%s: fb count: %d",__FUNCTION__,
1874 mCurrentFrame.fbCount);
1875}
1876
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001877hwc_rect_t MDPComp::getUpdatingFBRect(hwc_context_t *ctx,
1878 hwc_display_contents_1_t* list){
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001879 hwc_rect_t fbRect = (struct hwc_rect){0, 0, 0, 0};
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001880
1881 /* Update only the region of FB needed for composition */
1882 for(int i = 0; i < mCurrentFrame.layerCount; i++ ) {
1883 if(mCurrentFrame.isFBComposed[i] && !mCurrentFrame.drop[i]) {
1884 hwc_layer_1_t* layer = &list->hwLayers[i];
1885 hwc_rect_t dst = layer->displayFrame;
1886 fbRect = getUnion(fbRect, dst);
1887 }
1888 }
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08001889 trimAgainstROI(ctx, fbRect, fbRect);
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001890 return fbRect;
1891}
1892
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001893bool MDPComp::postHeuristicsHandling(hwc_context_t *ctx,
1894 hwc_display_contents_1_t* list) {
1895
1896 //Capability checks
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08001897 if(!resourceCheck(ctx, list)) {
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001898 ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
1899 return false;
1900 }
1901
1902 //Limitations checks
1903 if(!hwLimitationsCheck(ctx, list)) {
1904 ALOGD_IF(isDebug(), "%s: HW limitations",__FUNCTION__);
1905 return false;
1906 }
1907
Saurabh Shah3d4b8042013-12-10 15:19:17 -08001908 //Configure framebuffer first if applicable
1909 if(mCurrentFrame.fbZ >= 0) {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001910 hwc_rect_t fbRect = getUpdatingFBRect(ctx, list);
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001911 if(!ctx->mFBUpdate[mDpy]->prepare(ctx, list, fbRect, mCurrentFrame.fbZ))
1912 {
Saurabh Shah3d4b8042013-12-10 15:19:17 -08001913 ALOGD_IF(isDebug(), "%s configure framebuffer failed",
1914 __FUNCTION__);
1915 return false;
1916 }
1917 }
1918
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001919 mCurrentFrame.map();
1920
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001921 if(!allocLayerPipes(ctx, list)) {
1922 ALOGD_IF(isDebug(), "%s: Unable to allocate MDP pipes", __FUNCTION__);
Saurabh Shahaa236822013-04-24 18:07:26 -07001923 return false;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001924 }
1925
1926 for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
Saurabh Shahaa236822013-04-24 18:07:26 -07001927 index++) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001928 if(!mCurrentFrame.isFBComposed[index]) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001929 int mdpIndex = mCurrentFrame.layerToMDP[index];
1930 hwc_layer_1_t* layer = &list->hwLayers[index];
1931
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301932 //Leave fbZ for framebuffer. CACHE/GLES layers go here.
1933 if(mdpNextZOrder == mCurrentFrame.fbZ) {
1934 mdpNextZOrder++;
1935 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001936 MdpPipeInfo* cur_pipe = mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
1937 cur_pipe->zOrder = mdpNextZOrder++;
1938
radhakrishnac9a67412013-09-25 17:40:42 +05301939 private_handle_t *hnd = (private_handle_t *)layer->handle;
Raj Kamal389d6e32014-08-04 14:43:24 +05301940 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
radhakrishnac9a67412013-09-25 17:40:42 +05301941 if(configure4k2kYuv(ctx, layer,
1942 mCurrentFrame.mdpToLayer[mdpIndex])
1943 != 0 ){
1944 ALOGD_IF(isDebug(), "%s: Failed to configure split pipes \
1945 for layer %d",__FUNCTION__, index);
1946 return false;
1947 }
1948 else{
1949 mdpNextZOrder++;
1950 }
1951 continue;
1952 }
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05001953 if(needs3DComposition(ctx,mDpy) && get3DFormat(hnd) != HAL_NO_3D) {
1954 mdpNextZOrder++;
1955 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001956 if(configure(ctx, layer, mCurrentFrame.mdpToLayer[mdpIndex]) != 0 ){
1957 ALOGD_IF(isDebug(), "%s: Failed to configure overlay for \
radhakrishnac9a67412013-09-25 17:40:42 +05301958 layer %d",__FUNCTION__, index);
Saurabh Shahaa236822013-04-24 18:07:26 -07001959 return false;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001960 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001961 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001962 }
1963
Saurabh Shaha36be922013-12-16 18:18:39 -08001964 if(!ctx->mOverlay->validateAndSet(mDpy, ctx->dpyAttr[mDpy].fd)) {
1965 ALOGD_IF(isDebug(), "%s: Failed to validate and set overlay for dpy %d"
1966 ,__FUNCTION__, mDpy);
1967 return false;
1968 }
1969
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001970 setRedraw(ctx, list);
Saurabh Shahaa236822013-04-24 18:07:26 -07001971 return true;
1972}
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001973
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08001974bool MDPComp::resourceCheck(hwc_context_t* ctx,
1975 hwc_display_contents_1_t* list) {
Saurabh Shah173f4242013-11-20 09:50:12 -08001976 const bool fbUsed = mCurrentFrame.fbCount;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001977 int cursorInUse = 0;
1978 if(mDpy == HWC_DISPLAY_PRIMARY) {
1979 // check if cursor is in use for primary
1980 cursorInUse = HWCursor::getInstance()->isCursorSet();
1981 }
1982 int maxStages = qdutils::MDPVersion::getInstance().getBlendStages();
1983 // HW Cursor needs one blending stage, account for that in the check below
1984 // On high end targets(8994) has 8 blending stages, HAL is configured to use < 8.
1985 // Make use of the remaining stages for HW Cursor so that the composition
1986 // strategy would not fail due to this limitation.
1987 if (maxStages > sMaxPipesPerMixer) {
1988 cursorInUse = 0;
1989 }
1990 if(mCurrentFrame.mdpCount > (sMaxPipesPerMixer - fbUsed - cursorInUse)) {
Saurabh Shah173f4242013-11-20 09:50:12 -08001991 ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
1992 return false;
1993 }
Saurabh Shahacec8e42014-11-25 11:07:04 -08001994
1995 //Will benefit cases where a video has non-updating background.
1996 if((mDpy > HWC_DISPLAY_PRIMARY) and
1997 (mCurrentFrame.mdpCount > sMaxSecLayers)) {
1998 ALOGD_IF(isDebug(), "%s: Exceeds max secondary pipes",__FUNCTION__);
1999 return false;
2000 }
2001
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08002002 // Init rotCount to number of rotate sessions used by other displays
2003 int rotCount = ctx->mRotMgr->getNumActiveSessions();
2004 // Count the number of rotator sessions required for current display
2005 for (int index = 0; index < mCurrentFrame.layerCount; index++) {
2006 if(!mCurrentFrame.isFBComposed[index]) {
2007 hwc_layer_1_t* layer = &list->hwLayers[index];
2008 private_handle_t *hnd = (private_handle_t *)layer->handle;
2009 if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
2010 rotCount++;
2011 }
2012 }
2013 }
2014 // if number of layers to rotate exceeds max rotator sessions, bail out.
2015 if(rotCount > RotMgr::MAX_ROT_SESS) {
2016 ALOGD_IF(isDebug(), "%s: Exceeds max rotator sessions %d",
2017 __FUNCTION__, mDpy);
2018 return false;
2019 }
Saurabh Shah173f4242013-11-20 09:50:12 -08002020 return true;
2021}
2022
Prabhanjan Kandula21918db2013-11-26 15:51:58 +05302023bool MDPComp::hwLimitationsCheck(hwc_context_t* ctx,
2024 hwc_display_contents_1_t* list) {
2025
2026 //A-family hw limitation:
2027 //If a layer need alpha scaling, MDP can not support.
2028 if(ctx->mMDP.version < qdutils::MDSS_V5) {
2029 for(int i = 0; i < mCurrentFrame.layerCount; ++i) {
2030 if(!mCurrentFrame.isFBComposed[i] &&
2031 isAlphaScaled( &list->hwLayers[i])) {
2032 ALOGD_IF(isDebug(), "%s:frame needs alphaScaling",__FUNCTION__);
2033 return false;
2034 }
2035 }
2036 }
2037
2038 // On 8x26 & 8974 hw, we have a limitation of downscaling+blending.
2039 //If multiple layers requires downscaling and also they are overlapping
2040 //fall back to GPU since MDSS can not handle it.
2041 if(qdutils::MDPVersion::getInstance().is8x74v2() ||
2042 qdutils::MDPVersion::getInstance().is8x26()) {
2043 for(int i = 0; i < mCurrentFrame.layerCount-1; ++i) {
2044 hwc_layer_1_t* botLayer = &list->hwLayers[i];
2045 if(!mCurrentFrame.isFBComposed[i] &&
2046 isDownscaleRequired(botLayer)) {
2047 //if layer-i is marked for MDP and needs downscaling
2048 //check if any MDP layer on top of i & overlaps with layer-i
2049 for(int j = i+1; j < mCurrentFrame.layerCount; ++j) {
2050 hwc_layer_1_t* topLayer = &list->hwLayers[j];
2051 if(!mCurrentFrame.isFBComposed[j] &&
2052 isDownscaleRequired(topLayer)) {
2053 hwc_rect_t r = getIntersection(botLayer->displayFrame,
2054 topLayer->displayFrame);
2055 if(isValidRect(r))
2056 return false;
2057 }
2058 }
2059 }
2060 }
2061 }
2062 return true;
2063}
2064
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002065static bool validForCursor(hwc_context_t* ctx, int dpy, hwc_layer_1_t* layer) {
2066 private_handle_t *hnd = (private_handle_t *)layer->handle;
2067 hwc_rect dst = layer->displayFrame;
2068 hwc_rect src = integerizeSourceCrop(layer->sourceCropf);
2069 int srcW = src.right - src.left;
2070 int srcH = src.bottom - src.top;
2071 int dstW = dst.right - dst.left;
2072 int dstH = dst.bottom - dst.top;
2073 qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
2074 uint32_t maxCursorSize = mdpVersion.getMaxCursorSize();
2075 uint32_t numHwCursors = mdpVersion.getCursorPipes();
2076 bool primarySplit = isDisplaySplit(ctx, HWC_DISPLAY_PRIMARY);
2077 uint32_t cursorPipesNeeded = 1; // One cursor pipe needed(default)
2078 bool ret = false;
2079
2080 if(dpy > HWC_DISPLAY_PRIMARY) {
2081 // Cursor not supported on secondary displays, as it involves scaling
2082 // in most of the cases
2083 return false;
2084 } else if (isSkipLayer(layer)) {
2085 return false;
2086 // Checks for HW limitation
2087 } else if (numHwCursors == 0 || maxCursorSize <= 0) {
2088 return false;
2089 } else if (needsScaling(layer)) {
2090 return false;
2091 } else if (layer->transform != 0) {
2092 return false;
2093 } else if (hnd->format != HAL_PIXEL_FORMAT_RGBA_8888) {
2094 return false;
2095 } else if (srcW > (int)maxCursorSize || srcH > (int)maxCursorSize) {
2096 return false;
2097 }
2098
2099 if (isDisplaySplit(ctx, dpy) && !mdpVersion.isSrcSplit()) {
2100 // In case of split display with no srcSplit, the driver allocates two
2101 // pipes to support async position update across mixers, hence
2102 // need to account for that here.
2103 cursorPipesNeeded = 2;
2104 }
2105 if (cursorPipesNeeded <= numHwCursors) {
2106 ret = true;
2107 }
2108 return ret;
2109}
2110
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08002111// Checks only if videos or single layer(RGB) is updating
2112// which is used for setting dynamic fps or perf hint for single
2113// layer video playback
2114bool MDPComp::onlyVideosUpdating(hwc_context_t *ctx,
2115 hwc_display_contents_1_t* list) {
2116 bool support = false;
2117 FrameInfo frame;
2118 frame.reset(mCurrentFrame.layerCount);
2119 memset(&frame.drop, 0, sizeof(frame.drop));
2120 frame.dropCount = 0;
2121 ALOGD_IF(isDebug(), "%s: Update Cache and YUVInfo", __FUNCTION__);
2122 updateLayerCache(ctx, list, frame);
2123 updateYUV(ctx, list, false /*secure only*/, frame);
2124 // There are only updating YUV layers or there is single RGB
2125 // Layer(Youtube)
2126 if((ctx->listStats[mDpy].yuvCount == frame.mdpCount) ||
2127 (frame.layerCount == 1)) {
2128 support = true;
2129 }
2130 return support;
2131}
2132
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302133void MDPComp::setDynRefreshRate(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
2134 //For primary display, set the dynamic refreshrate
2135 if(!mDpy && qdutils::MDPVersion::getInstance().isDynFpsSupported() &&
2136 ctx->mUseMetaDataRefreshRate) {
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302137 uint32_t refreshRate = ctx->dpyAttr[mDpy].refreshRate;
2138 MDPVersion& mdpHw = MDPVersion::getInstance();
2139 if(sIdleFallBack) {
2140 //Set minimum panel refresh rate during idle timeout
2141 refreshRate = mdpHw.getMinFpsSupported();
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08002142 } else if(onlyVideosUpdating(ctx, list)) {
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302143 //Set the new fresh rate, if there is only one updating YUV layer
2144 //or there is one single RGB layer with this request
2145 refreshRate = ctx->listStats[mDpy].refreshRateRequest;
2146 }
2147 setRefreshRate(ctx, mDpy, refreshRate);
2148 }
2149}
2150
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002151int MDPComp::prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002152 int ret = 0;
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07002153 char property[PROPERTY_VALUE_MAX];
2154
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002155 if(!list) {
2156 ALOGE("%s: Invalid list", __FUNCTION__);
Raj Kamal4393eaa2014-06-06 13:45:20 +05302157 mCachedFrame.reset();
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002158 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Raj Kamal4393eaa2014-06-06 13:45:20 +05302159 return -1;
2160 }
2161
2162 const int numLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shah286cf122014-09-08 14:13:08 -07002163 if(mDpy == HWC_DISPLAY_PRIMARY) {
2164 sSimulationFlags = 0;
2165 if(property_get("debug.hwc.simulate", property, NULL) > 0) {
2166 int currentFlags = atoi(property);
2167 if(currentFlags != sSimulationFlags) {
2168 sSimulationFlags = currentFlags;
2169 ALOGI("%s: Simulation Flag read: 0x%x (%d)", __FUNCTION__,
2170 sSimulationFlags, sSimulationFlags);
2171 }
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07002172 }
2173 }
Ramkumar Radhakrishnanc5893f12013-06-06 19:43:53 -07002174
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302175 //reset old data
2176 mCurrentFrame.reset(numLayers);
2177 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
2178 mCurrentFrame.dropCount = 0;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002179 mCurrentFrame.hwCursorIndex = -1;
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302180
Raj Kamal9ed3d6b2014-02-07 16:15:17 +05302181 //Do not cache the information for next draw cycle.
2182 if(numLayers > MAX_NUM_APP_LAYERS or (!numLayers)) {
2183 ALOGI("%s: Unsupported layer count for mdp composition",
2184 __FUNCTION__);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002185 mCachedFrame.reset();
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302186#ifdef DYNAMIC_FPS
2187 setDynRefreshRate(ctx, list);
2188#endif
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002189 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002190 return -1;
2191 }
2192
Ramkumar Radhakrishnana70981a2013-08-28 11:33:53 -07002193 // Detect the start of animation and fall back to GPU only once to cache
2194 // all the layers in FB and display FB content untill animation completes.
2195 if(ctx->listStats[mDpy].isDisplayAnimating) {
2196 mCurrentFrame.needsRedraw = false;
2197 if(ctx->mAnimationState[mDpy] == ANIMATION_STOPPED) {
2198 mCurrentFrame.needsRedraw = true;
2199 ctx->mAnimationState[mDpy] = ANIMATION_STARTED;
2200 }
2201 setMDPCompLayerFlags(ctx, list);
2202 mCachedFrame.updateCounts(mCurrentFrame);
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302203#ifdef DYNAMIC_FPS
2204 setDynRefreshRate(ctx, list);
2205#endif
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002206 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Ramkumar Radhakrishnana70981a2013-08-28 11:33:53 -07002207 ret = -1;
2208 return ret;
2209 } else {
2210 ctx->mAnimationState[mDpy] = ANIMATION_STOPPED;
2211 }
2212
Raj Kamalfdfdddf2015-03-16 21:59:25 +05302213 if(!mDpy and !isSecondaryConnected(ctx) and !mPrevModeOn and
2214 mCachedFrame.isSameFrame(ctx,mDpy,list)) {
2215
2216 ALOGD_IF(isDebug(),"%s: Avoid new composition",__FUNCTION__);
2217 mCurrentFrame.needsRedraw = false;
2218 setMDPCompLayerFlags(ctx, list);
2219 mCachedFrame.updateCounts(mCurrentFrame);
2220#ifdef DYNAMIC_FPS
2221 setDynRefreshRate(ctx, list);
2222#endif
2223 return -1;
2224
2225 }
2226
Saurabh Shahb39f8152013-08-22 10:21:44 -07002227 //Hard conditions, if not met, cannot do MDP comp
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002228 if(isFrameDoable(ctx)) {
2229 generateROI(ctx, list);
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07002230 // if AIV Video mode is enabled, drop all non AIV layers from the
2231 // external display list.
2232 if(ctx->listStats[mDpy].mAIVVideoMode) {
2233 dropNonAIVLayers(ctx, list);
2234 }
Saurabh Shahb39f8152013-08-22 10:21:44 -07002235
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002236 // Configure the cursor if present
2237 int topIndex = ctx->listStats[mDpy].numAppLayers - 1;
2238 if(ctx->listStats[mDpy].cursorLayerPresent &&
2239 validForCursor(ctx, mDpy, &(list->hwLayers[topIndex]))) {
2240 if(configHwCursor(ctx->dpyAttr[mDpy].fd, mDpy,
2241 &(list->hwLayers[topIndex]))) {
2242 // As cursor is configured, mark that layer as dropped, so that
2243 // it wont be considered for composition by other strategies.
2244 mCurrentFrame.hwCursorIndex = topIndex;
2245 mCurrentFrame.drop[topIndex] = true;
2246 mCurrentFrame.dropCount++;
2247 }
2248 } else {
2249 // Release the hw cursor
2250 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
2251 }
2252
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07002253 // if tryFullFrame fails, try to push all video and secure RGB layers
2254 // to MDP for composition.
2255 mModeOn = tryFullFrame(ctx, list) || tryMDPOnlyLayers(ctx, list) ||
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07002256 tryVideoOnly(ctx, list);
Raj Kamal4393eaa2014-06-06 13:45:20 +05302257 if(mModeOn) {
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002258 setMDPCompLayerFlags(ctx, list);
2259 } else {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08002260 resetROI(ctx, mDpy);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002261 reset(ctx);
2262 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
2263 mCurrentFrame.dropCount = 0;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002264 // Check if cursor is in use for primary and mark accordingly
2265 if(!mDpy && HWCursor::getInstance()->isCursorSet()) {
2266 int topIndex = ctx->listStats[mDpy].numAppLayers - 1;
2267 hwc_layer_1_t *layer = &(list->hwLayers[topIndex]);
2268 layer->compositionType = HWC_CURSOR_OVERLAY;
2269 }
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002270 ret = -1;
Saurabh Shah286cf122014-09-08 14:13:08 -07002271 ALOGE_IF(sSimulationFlags && (mDpy == HWC_DISPLAY_PRIMARY),
2272 "MDP Composition Strategies Failed");
Saurabh Shahb39f8152013-08-22 10:21:44 -07002273 }
2274 } else {
Dileep Kumar Reddi4070e932014-09-30 09:00:57 +05302275 if ((ctx->mMDP.version == qdutils::MDP_V3_0_5) && ctx->mCopyBit[mDpy] &&
2276 enablePartialUpdateForMDP3) {
2277 generateROI(ctx, list);
2278 for(int i = 0; i < ctx->listStats[mDpy].numAppLayers; i++) {
2279 ctx->copybitDrop[i] = mCurrentFrame.drop[i];
2280 }
2281 }
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002282 ALOGD_IF( isDebug(),"%s: MDP Comp not possible for this frame",
2283 __FUNCTION__);
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002284 // Release the hw cursor
2285 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002286 ret = -1;
Saurabh Shahb39f8152013-08-22 10:21:44 -07002287 }
Saurabh Shahb39f8152013-08-22 10:21:44 -07002288
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002289 if(isDebug()) {
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002290 ALOGD("GEOMETRY change: %d",
2291 (list->flags & HWC_GEOMETRY_CHANGED));
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002292 android::String8 sDump("");
Jeykumar Sankaran6850ac62014-05-27 10:07:26 -07002293 dump(sDump, ctx);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002294 ALOGD("%s",sDump.string());
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002295 }
2296
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07002297#ifdef DYNAMIC_FPS
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302298 setDynRefreshRate(ctx, list);
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07002299#endif
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08002300 setPerfHint(ctx, list);
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07002301
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002302 mCachedFrame.cacheAll(list);
2303 mCachedFrame.updateCounts(mCurrentFrame);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002304 return ret;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002305}
2306
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002307bool MDPComp::allocSplitVGPipes(hwc_context_t *ctx, int index) {
radhakrishnac9a67412013-09-25 17:40:42 +05302308
2309 bool bRet = true;
radhakrishnac9a67412013-09-25 17:40:42 +05302310 int mdpIndex = mCurrentFrame.layerToMDP[index];
2311 PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
2312 info.pipeInfo = new MdpYUVPipeInfo;
2313 info.rot = NULL;
2314 MdpYUVPipeInfo& pipe_info = *(MdpYUVPipeInfo*)info.pipeInfo;
radhakrishnac9a67412013-09-25 17:40:42 +05302315
2316 pipe_info.lIndex = ovutils::OV_INVALID;
2317 pipe_info.rIndex = ovutils::OV_INVALID;
2318
Saurabh Shahc62f3982014-03-05 14:28:26 -08002319 Overlay::PipeSpecs pipeSpecs;
2320 pipeSpecs.formatClass = Overlay::FORMAT_YUV;
2321 pipeSpecs.needsScaling = true;
2322 pipeSpecs.dpy = mDpy;
2323 pipeSpecs.fb = false;
2324
2325 pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
radhakrishnac9a67412013-09-25 17:40:42 +05302326 if(pipe_info.lIndex == ovutils::OV_INVALID){
2327 bRet = false;
2328 ALOGD_IF(isDebug(),"%s: allocating first VG pipe failed",
2329 __FUNCTION__);
2330 }
Saurabh Shahc62f3982014-03-05 14:28:26 -08002331 pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
radhakrishnac9a67412013-09-25 17:40:42 +05302332 if(pipe_info.rIndex == ovutils::OV_INVALID){
2333 bRet = false;
2334 ALOGD_IF(isDebug(),"%s: allocating second VG pipe failed",
2335 __FUNCTION__);
2336 }
2337 return bRet;
2338}
Sushil Chauhandefd3522014-05-13 18:17:12 -07002339
2340int MDPComp::drawOverlap(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
2341 int fd = -1;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002342 if (ctx->mPtorInfo.isActive()) {
2343 fd = ctx->mCopyBit[mDpy]->drawOverlap(ctx, list);
Sushil Chauhandefd3522014-05-13 18:17:12 -07002344 if (fd < 0) {
2345 ALOGD_IF(isDebug(),"%s: failed", __FUNCTION__);
Sushil Chauhandefd3522014-05-13 18:17:12 -07002346 }
2347 }
2348 return fd;
2349}
Arun Kumar K.R2aa44c62014-01-21 23:08:28 -08002350//=============MDPCompNonSplit==================================================
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002351
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002352void MDPCompNonSplit::adjustForSourceSplit(hwc_context_t *ctx,
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302353 hwc_display_contents_1_t* list) {
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002354 //If 4k2k Yuv layer split is possible, and if
2355 //fbz is above 4k2k layer, increment fb zorder by 1
2356 //as we split 4k2k layer and increment zorder for right half
2357 //of the layer
Shalaj Jaina70b4352014-06-15 13:47:47 -07002358 if(!ctx)
2359 return;
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002360 if(mCurrentFrame.fbZ >= 0) {
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302361 for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
2362 index++) {
2363 if(!mCurrentFrame.isFBComposed[index]) {
2364 if(mdpNextZOrder == mCurrentFrame.fbZ) {
2365 mdpNextZOrder++;
2366 }
2367 mdpNextZOrder++;
2368 hwc_layer_1_t* layer = &list->hwLayers[index];
2369 private_handle_t *hnd = (private_handle_t *)layer->handle;
Raj Kamal389d6e32014-08-04 14:43:24 +05302370 if(isYUVSplitNeeded(hnd)) {
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302371 if(mdpNextZOrder <= mCurrentFrame.fbZ)
2372 mCurrentFrame.fbZ += 1;
2373 mdpNextZOrder++;
2374 //As we split 4kx2k yuv layer and program to 2 VG pipes
2375 //(if available) increase mdpcount by 1.
2376 mCurrentFrame.mdpCount++;
2377 }
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002378 }
2379 }
2380 }
radhakrishnac9a67412013-09-25 17:40:42 +05302381}
2382
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002383/*
2384 * Configures pipe(s) for MDP composition
2385 */
Saurabh Shah88e4d272013-09-03 13:31:29 -07002386int MDPCompNonSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002387 PipeLayerPair& PipeLayerPair) {
Saurabh Shah88e4d272013-09-03 13:31:29 -07002388 MdpPipeInfoNonSplit& mdp_info =
2389 *(static_cast<MdpPipeInfoNonSplit*>(PipeLayerPair.pipeInfo));
Justin Philipd6166602014-08-12 13:42:21 +05302390 eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shahacf10202013-02-26 10:15:15 -08002391 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Saurabh Shahacf10202013-02-26 10:15:15 -08002392 eDest dest = mdp_info.index;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002393
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002394 ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipe: %d",
2395 __FUNCTION__, layer, zOrder, dest);
2396
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002397 return configureNonSplit(ctx, layer, mDpy, mdpFlags, zOrder, dest,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002398 &PipeLayerPair.rot);
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002399}
2400
Saurabh Shah88e4d272013-09-03 13:31:29 -07002401bool MDPCompNonSplit::allocLayerPipes(hwc_context_t *ctx,
Saurabh Shahe51f8ca2013-05-06 17:26:16 -07002402 hwc_display_contents_1_t* list) {
Saurabh Shah8cc77712015-03-31 10:48:51 -07002403 for(uint32_t formatType = FORMAT_YUV; formatType < FORMAT_MAX;
2404 formatType++) {
2405 for(int index = 0; index < mCurrentFrame.layerCount; index++) {
2406 if(mCurrentFrame.isFBComposed[index]) continue;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002407
Saurabh Shah8cc77712015-03-31 10:48:51 -07002408 hwc_layer_1_t* layer = &list->hwLayers[index];
2409 private_handle_t *hnd = (private_handle_t *)layer->handle;
2410 if(formatType == FORMAT_YUV && !isYuvBuffer(hnd))
radhakrishnac9a67412013-09-25 17:40:42 +05302411 continue;
Saurabh Shah8cc77712015-03-31 10:48:51 -07002412 if(formatType == FORMAT_RGB && isYuvBuffer(hnd))
2413 continue;
2414
2415 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
2416 if(allocSplitVGPipes(ctx, index)){
2417 continue;
2418 }
radhakrishnac9a67412013-09-25 17:40:42 +05302419 }
radhakrishnac9a67412013-09-25 17:40:42 +05302420
Saurabh Shah8cc77712015-03-31 10:48:51 -07002421 int mdpIndex = mCurrentFrame.layerToMDP[index];
2422 PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
2423 info.pipeInfo = new MdpPipeInfoNonSplit;
2424 info.rot = NULL;
2425 MdpPipeInfoNonSplit& pipe_info =
2426 *(MdpPipeInfoNonSplit*)info.pipeInfo;
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -08002427
Saurabh Shah8cc77712015-03-31 10:48:51 -07002428 Overlay::PipeSpecs pipeSpecs;
2429 pipeSpecs.formatClass = isYuvBuffer(hnd) ?
2430 Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
2431 pipeSpecs.needsScaling = qhwc::needsScaling(layer) or
2432 (qdutils::MDPVersion::getInstance().is8x26() and
2433 ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres > 1024);
2434 pipeSpecs.dpy = mDpy;
2435 pipeSpecs.fb = false;
2436 pipeSpecs.numActiveDisplays = ctx->numActiveDisplays;
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -08002437
Saurabh Shah8cc77712015-03-31 10:48:51 -07002438 pipe_info.index = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahc62f3982014-03-05 14:28:26 -08002439
Saurabh Shah8cc77712015-03-31 10:48:51 -07002440 if(pipe_info.index == ovutils::OV_INVALID) {
2441 ALOGD_IF(isDebug(), "%s: Unable to get pipe for layer %d of "\
2442 "format type %d", __FUNCTION__, index, formatType);
2443 return false;
2444 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002445 }
2446 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002447 return true;
2448}
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002449
radhakrishnac9a67412013-09-25 17:40:42 +05302450int MDPCompNonSplit::configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
2451 PipeLayerPair& PipeLayerPair) {
2452 MdpYUVPipeInfo& mdp_info =
2453 *(static_cast<MdpYUVPipeInfo*>(PipeLayerPair.pipeInfo));
2454 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Justin Philipd6166602014-08-12 13:42:21 +05302455 eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
radhakrishnac9a67412013-09-25 17:40:42 +05302456 eDest lDest = mdp_info.lIndex;
2457 eDest rDest = mdp_info.rIndex;
2458
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002459 return configureSourceSplit(ctx, layer, mDpy, mdpFlagsL, zOrder,
radhakrishnac9a67412013-09-25 17:40:42 +05302460 lDest, rDest, &PipeLayerPair.rot);
2461}
2462
Saurabh Shah88e4d272013-09-03 13:31:29 -07002463bool MDPCompNonSplit::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002464
Raj Kamal4393eaa2014-06-06 13:45:20 +05302465 if(!isEnabled() or !mModeOn) {
2466 ALOGD_IF(isDebug(),"%s: MDP Comp not enabled/configured", __FUNCTION__);
Prabhanjan Kandula08222fc2013-07-10 17:20:59 +05302467 return true;
2468 }
2469
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002470 overlay::Overlay& ov = *ctx->mOverlay;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002471 LayerProp *layerProp = ctx->layerProp[mDpy];
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002472
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002473 int numHwLayers = ctx->listStats[mDpy].numAppLayers;
2474 for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ )
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002475 {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002476 if(mCurrentFrame.isFBComposed[i]) continue;
2477
Naseer Ahmed5b6708a2012-08-02 13:46:08 -07002478 hwc_layer_1_t *layer = &list->hwLayers[i];
Saurabh Shahacf10202013-02-26 10:15:15 -08002479 private_handle_t *hnd = (private_handle_t *)layer->handle;
2480 if(!hnd) {
Sushil Chauhan897a9c32013-07-18 11:09:55 -07002481 if (!(layer->flags & HWC_COLOR_FILL)) {
2482 ALOGE("%s handle null", __FUNCTION__);
2483 return false;
2484 }
2485 // No PLAY for Color layer
2486 layerProp[i].mFlags &= ~HWC_MDPCOMP;
2487 continue;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002488 }
2489
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002490 int mdpIndex = mCurrentFrame.layerToMDP[i];
2491
Raj Kamal389d6e32014-08-04 14:43:24 +05302492 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit)
radhakrishnac9a67412013-09-25 17:40:42 +05302493 {
2494 MdpYUVPipeInfo& pipe_info =
2495 *(MdpYUVPipeInfo*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
2496 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
2497 ovutils::eDest indexL = pipe_info.lIndex;
2498 ovutils::eDest indexR = pipe_info.rIndex;
2499 int fd = hnd->fd;
Praveena Pachipulusud9443c72014-02-17 10:42:28 +05302500 uint32_t offset = (uint32_t)hnd->offset;
radhakrishnac9a67412013-09-25 17:40:42 +05302501 if(rot) {
2502 rot->queueBuffer(fd, offset);
2503 fd = rot->getDstMemId();
2504 offset = rot->getDstOffset();
2505 }
2506 if(indexL != ovutils::OV_INVALID) {
2507 ovutils::eDest destL = (ovutils::eDest)indexL;
2508 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2509 using pipe: %d", __FUNCTION__, layer, hnd, indexL );
2510 if (!ov.queueBuffer(fd, offset, destL)) {
2511 ALOGE("%s: queueBuffer failed for display:%d",
2512 __FUNCTION__, mDpy);
2513 return false;
2514 }
2515 }
2516
2517 if(indexR != ovutils::OV_INVALID) {
2518 ovutils::eDest destR = (ovutils::eDest)indexR;
2519 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2520 using pipe: %d", __FUNCTION__, layer, hnd, indexR );
2521 if (!ov.queueBuffer(fd, offset, destR)) {
2522 ALOGE("%s: queueBuffer failed for display:%d",
2523 __FUNCTION__, mDpy);
2524 return false;
2525 }
2526 }
2527 }
2528 else{
2529 MdpPipeInfoNonSplit& pipe_info =
Saurabh Shah88e4d272013-09-03 13:31:29 -07002530 *(MdpPipeInfoNonSplit*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
radhakrishnac9a67412013-09-25 17:40:42 +05302531 ovutils::eDest dest = pipe_info.index;
2532 if(dest == ovutils::OV_INVALID) {
2533 ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, dest);
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002534 return false;
radhakrishnac9a67412013-09-25 17:40:42 +05302535 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002536
radhakrishnac9a67412013-09-25 17:40:42 +05302537 if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
2538 continue;
2539 }
2540
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002541 int fd = hnd->fd;
2542 uint32_t offset = (uint32_t)hnd->offset;
2543 int index = ctx->mPtorInfo.getPTORArrayIndex(i);
2544 if (!mDpy && (index != -1)) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07002545 hnd = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002546 fd = hnd->fd;
Sushil Chauhan875a92e2014-07-25 12:20:23 -07002547 offset = 0;
Sushil Chauhandefd3522014-05-13 18:17:12 -07002548 }
2549
radhakrishnac9a67412013-09-25 17:40:42 +05302550 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2551 using pipe: %d", __FUNCTION__, layer,
2552 hnd, dest );
2553
radhakrishnac9a67412013-09-25 17:40:42 +05302554 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
2555 if(rot) {
2556 if(!rot->queueBuffer(fd, offset))
2557 return false;
2558 fd = rot->getDstMemId();
2559 offset = rot->getDstOffset();
2560 }
2561
2562 if (!ov.queueBuffer(fd, offset, dest)) {
2563 ALOGE("%s: queueBuffer failed for display:%d ",
2564 __FUNCTION__, mDpy);
2565 return false;
2566 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002567 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002568
2569 layerProp[i].mFlags &= ~HWC_MDPCOMP;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002570 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002571 return true;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002572}
2573
Saurabh Shah88e4d272013-09-03 13:31:29 -07002574//=============MDPCompSplit===================================================
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002575
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002576void MDPCompSplit::adjustForSourceSplit(hwc_context_t *ctx,
radhakrishnac9a67412013-09-25 17:40:42 +05302577 hwc_display_contents_1_t* list){
2578 //if 4kx2k yuv layer is totally present in either in left half
2579 //or right half then try splitting the yuv layer to avoid decimation
radhakrishnac9a67412013-09-25 17:40:42 +05302580 const int lSplit = getLeftSplit(ctx, mDpy);
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302581 if(mCurrentFrame.fbZ >= 0) {
2582 for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
2583 index++) {
2584 if(!mCurrentFrame.isFBComposed[index]) {
2585 if(mdpNextZOrder == mCurrentFrame.fbZ) {
2586 mdpNextZOrder++;
2587 }
2588 mdpNextZOrder++;
2589 hwc_layer_1_t* layer = &list->hwLayers[index];
2590 private_handle_t *hnd = (private_handle_t *)layer->handle;
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002591 if(isYUVSplitNeeded(hnd) ||
2592 (needs3DComposition(ctx,mDpy) &&
2593 get3DFormat(hnd) != HAL_NO_3D)) {
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302594 hwc_rect_t dst = layer->displayFrame;
2595 if((dst.left > lSplit) || (dst.right < lSplit)) {
2596 mCurrentFrame.mdpCount += 1;
2597 }
2598 if(mdpNextZOrder <= mCurrentFrame.fbZ)
2599 mCurrentFrame.fbZ += 1;
2600 mdpNextZOrder++;
2601 }
2602 }
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002603 }
radhakrishnac9a67412013-09-25 17:40:42 +05302604 }
2605}
2606
Saurabh Shah88e4d272013-09-03 13:31:29 -07002607bool MDPCompSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
Saurabh Shahc62f3982014-03-05 14:28:26 -08002608 MdpPipeInfoSplit& pipe_info) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002609
Saurabh Shahc62f3982014-03-05 14:28:26 -08002610 const int lSplit = getLeftSplit(ctx, mDpy);
2611 private_handle_t *hnd = (private_handle_t *)layer->handle;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002612 hwc_rect_t dst = layer->displayFrame;
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002613 pipe_info.lIndex = ovutils::OV_INVALID;
2614 pipe_info.rIndex = ovutils::OV_INVALID;
2615
Saurabh Shahc62f3982014-03-05 14:28:26 -08002616 Overlay::PipeSpecs pipeSpecs;
2617 pipeSpecs.formatClass = isYuvBuffer(hnd) ?
2618 Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
2619 pipeSpecs.needsScaling = qhwc::needsScalingWithSplit(ctx, layer, mDpy);
2620 pipeSpecs.dpy = mDpy;
2621 pipeSpecs.mixer = Overlay::MIXER_LEFT;
2622 pipeSpecs.fb = false;
2623
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08002624 // Acquire pipe only for the updating half
2625 hwc_rect_t l_roi = ctx->listStats[mDpy].lRoi;
2626 hwc_rect_t r_roi = ctx->listStats[mDpy].rRoi;
2627
2628 if (dst.left < lSplit && isValidRect(getIntersection(dst, l_roi))) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002629 pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002630 if(pipe_info.lIndex == ovutils::OV_INVALID)
2631 return false;
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002632 }
2633
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08002634 if(dst.right > lSplit && isValidRect(getIntersection(dst, r_roi))) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002635 pipeSpecs.mixer = Overlay::MIXER_RIGHT;
2636 pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002637 if(pipe_info.rIndex == ovutils::OV_INVALID)
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002638 return false;
2639 }
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002640
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002641 return true;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002642}
2643
Saurabh Shah88e4d272013-09-03 13:31:29 -07002644bool MDPCompSplit::allocLayerPipes(hwc_context_t *ctx,
Saurabh Shahe51f8ca2013-05-06 17:26:16 -07002645 hwc_display_contents_1_t* list) {
Saurabh Shah8cc77712015-03-31 10:48:51 -07002646 for(uint32_t formatType = FORMAT_YUV; formatType < FORMAT_MAX;
2647 formatType++) {
2648 for(int index = 0 ; index < mCurrentFrame.layerCount; index++) {
2649 if(mCurrentFrame.isFBComposed[index]) continue;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002650
Saurabh Shah8cc77712015-03-31 10:48:51 -07002651 hwc_layer_1_t* layer = &list->hwLayers[index];
2652 private_handle_t *hnd = (private_handle_t *)layer->handle;
2653 if(formatType == FORMAT_YUV && !isYuvBuffer(hnd))
2654 continue;
2655 if(formatType == FORMAT_RGB && isYuvBuffer(hnd))
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002656 continue;
2657
Saurabh Shah8cc77712015-03-31 10:48:51 -07002658 hwc_rect_t dst = layer->displayFrame;
2659 const int lSplit = getLeftSplit(ctx, mDpy);
2660 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
2661 if((dst.left > lSplit)||(dst.right < lSplit)){
2662 if(allocSplitVGPipes(ctx, index)){
2663 continue;
2664 }
2665 }
2666 }
2667 //XXX: Check for forced 2D composition
2668 if(needs3DComposition(ctx, mDpy) && get3DFormat(hnd) != HAL_NO_3D)
2669 if(allocSplitVGPipes(ctx,index))
2670 continue;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002671
Saurabh Shah8cc77712015-03-31 10:48:51 -07002672 int mdpIndex = mCurrentFrame.layerToMDP[index];
2673 PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
2674 info.pipeInfo = new MdpPipeInfoSplit;
2675 info.rot = NULL;
2676 MdpPipeInfoSplit& pipe_info = *(MdpPipeInfoSplit*)info.pipeInfo;
2677
2678 if(!acquireMDPPipes(ctx, layer, pipe_info)) {
2679 ALOGD_IF(isDebug(), "%s: Unable to get pipe for layer %d of "\
2680 "format type %d", __FUNCTION__, index, formatType);
2681 return false;
2682 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002683 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002684 }
2685 return true;
2686}
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002687
radhakrishnac9a67412013-09-25 17:40:42 +05302688int MDPCompSplit::configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
2689 PipeLayerPair& PipeLayerPair) {
2690 const int lSplit = getLeftSplit(ctx, mDpy);
2691 hwc_rect_t dst = layer->displayFrame;
2692 if((dst.left > lSplit)||(dst.right < lSplit)){
2693 MdpYUVPipeInfo& mdp_info =
2694 *(static_cast<MdpYUVPipeInfo*>(PipeLayerPair.pipeInfo));
2695 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Justin Philipd6166602014-08-12 13:42:21 +05302696 eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
radhakrishnac9a67412013-09-25 17:40:42 +05302697 eDest lDest = mdp_info.lIndex;
2698 eDest rDest = mdp_info.rIndex;
2699
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002700 return configureSourceSplit(ctx, layer, mDpy, mdpFlagsL, zOrder,
radhakrishnac9a67412013-09-25 17:40:42 +05302701 lDest, rDest, &PipeLayerPair.rot);
2702 }
2703 else{
2704 return configure(ctx, layer, PipeLayerPair);
2705 }
2706}
2707
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002708/*
2709 * Configures pipe(s) for MDP composition
2710 */
Saurabh Shah88e4d272013-09-03 13:31:29 -07002711int MDPCompSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
Saurabh Shah67a38c32013-06-10 16:23:15 -07002712 PipeLayerPair& PipeLayerPair) {
Saurabh Shah88e4d272013-09-03 13:31:29 -07002713 MdpPipeInfoSplit& mdp_info =
2714 *(static_cast<MdpPipeInfoSplit*>(PipeLayerPair.pipeInfo));
Saurabh Shahacf10202013-02-26 10:15:15 -08002715 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Justin Philipd6166602014-08-12 13:42:21 +05302716 eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shahacf10202013-02-26 10:15:15 -08002717 eDest lDest = mdp_info.lIndex;
2718 eDest rDest = mdp_info.rIndex;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002719
2720 ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
Jeykumar Sankaran39305802014-12-12 17:55:57 -08002721 "dest_pipeR: %d",__FUNCTION__, layer, zOrder, lDest, rDest);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002722
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002723 return configureSplit(ctx, layer, mDpy, mdpFlagsL, zOrder, lDest,
Jeykumar Sankaran39305802014-12-12 17:55:57 -08002724 rDest, &PipeLayerPair.rot);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002725}
2726
Saurabh Shah88e4d272013-09-03 13:31:29 -07002727bool MDPCompSplit::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002728
Raj Kamal4393eaa2014-06-06 13:45:20 +05302729 if(!isEnabled() or !mModeOn) {
2730 ALOGD_IF(isDebug(),"%s: MDP Comp not enabled/configured", __FUNCTION__);
Prabhanjan Kandula08222fc2013-07-10 17:20:59 +05302731 return true;
2732 }
2733
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002734 overlay::Overlay& ov = *ctx->mOverlay;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002735 LayerProp *layerProp = ctx->layerProp[mDpy];
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002736
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002737 int numHwLayers = ctx->listStats[mDpy].numAppLayers;
2738 for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ )
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002739 {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002740 if(mCurrentFrame.isFBComposed[i]) continue;
2741
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002742 hwc_layer_1_t *layer = &list->hwLayers[i];
Saurabh Shahacf10202013-02-26 10:15:15 -08002743 private_handle_t *hnd = (private_handle_t *)layer->handle;
2744 if(!hnd) {
2745 ALOGE("%s handle null", __FUNCTION__);
2746 return false;
2747 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002748
2749 if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
2750 continue;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002751 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002752
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002753 int mdpIndex = mCurrentFrame.layerToMDP[i];
2754
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002755 if((isYUVSplitNeeded(hnd) && sEnableYUVsplit) ||
2756 (needs3DComposition(ctx, mDpy) && get3DFormat(hnd) != HAL_NO_3D))
radhakrishnac9a67412013-09-25 17:40:42 +05302757 {
2758 MdpYUVPipeInfo& pipe_info =
2759 *(MdpYUVPipeInfo*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
2760 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
2761 ovutils::eDest indexL = pipe_info.lIndex;
2762 ovutils::eDest indexR = pipe_info.rIndex;
2763 int fd = hnd->fd;
Praveena Pachipulusud9443c72014-02-17 10:42:28 +05302764 uint32_t offset = (uint32_t)hnd->offset;
radhakrishnac9a67412013-09-25 17:40:42 +05302765 if(rot) {
2766 rot->queueBuffer(fd, offset);
2767 fd = rot->getDstMemId();
2768 offset = rot->getDstOffset();
2769 }
2770 if(indexL != ovutils::OV_INVALID) {
2771 ovutils::eDest destL = (ovutils::eDest)indexL;
2772 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2773 using pipe: %d", __FUNCTION__, layer, hnd, indexL );
2774 if (!ov.queueBuffer(fd, offset, destL)) {
2775 ALOGE("%s: queueBuffer failed for display:%d",
2776 __FUNCTION__, mDpy);
2777 return false;
2778 }
2779 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002780
radhakrishnac9a67412013-09-25 17:40:42 +05302781 if(indexR != ovutils::OV_INVALID) {
2782 ovutils::eDest destR = (ovutils::eDest)indexR;
2783 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2784 using pipe: %d", __FUNCTION__, layer, hnd, indexR );
2785 if (!ov.queueBuffer(fd, offset, destR)) {
2786 ALOGE("%s: queueBuffer failed for display:%d",
2787 __FUNCTION__, mDpy);
2788 return false;
2789 }
Saurabh Shaha9da08f2013-07-03 13:27:53 -07002790 }
2791 }
radhakrishnac9a67412013-09-25 17:40:42 +05302792 else{
2793 MdpPipeInfoSplit& pipe_info =
2794 *(MdpPipeInfoSplit*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
2795 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
Saurabh Shaha9da08f2013-07-03 13:27:53 -07002796
radhakrishnac9a67412013-09-25 17:40:42 +05302797 ovutils::eDest indexL = pipe_info.lIndex;
2798 ovutils::eDest indexR = pipe_info.rIndex;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002799
radhakrishnac9a67412013-09-25 17:40:42 +05302800 int fd = hnd->fd;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002801 uint32_t offset = (uint32_t)hnd->offset;
2802 int index = ctx->mPtorInfo.getPTORArrayIndex(i);
2803 if (!mDpy && (index != -1)) {
2804 hnd = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
2805 fd = hnd->fd;
Sushil Chauhan875a92e2014-07-25 12:20:23 -07002806 offset = 0;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002807 }
radhakrishnac9a67412013-09-25 17:40:42 +05302808
Tatenda Chipeperekwa88fe6352014-04-14 10:36:06 -07002809 if(ctx->mAD->draw(ctx, fd, offset)) {
2810 fd = ctx->mAD->getDstFd();
2811 offset = ctx->mAD->getDstOffset();
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002812 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002813
radhakrishnac9a67412013-09-25 17:40:42 +05302814 if(rot) {
2815 rot->queueBuffer(fd, offset);
2816 fd = rot->getDstMemId();
2817 offset = rot->getDstOffset();
2818 }
2819
2820 //************* play left mixer **********
2821 if(indexL != ovutils::OV_INVALID) {
2822 ovutils::eDest destL = (ovutils::eDest)indexL;
2823 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2824 using pipe: %d", __FUNCTION__, layer, hnd, indexL );
2825 if (!ov.queueBuffer(fd, offset, destL)) {
2826 ALOGE("%s: queueBuffer failed for left mixer",
2827 __FUNCTION__);
2828 return false;
2829 }
2830 }
2831
2832 //************* play right mixer **********
2833 if(indexR != ovutils::OV_INVALID) {
2834 ovutils::eDest destR = (ovutils::eDest)indexR;
2835 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2836 using pipe: %d", __FUNCTION__, layer, hnd, indexR );
2837 if (!ov.queueBuffer(fd, offset, destR)) {
2838 ALOGE("%s: queueBuffer failed for right mixer",
2839 __FUNCTION__);
2840 return false;
2841 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002842 }
2843 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002844
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002845 layerProp[i].mFlags &= ~HWC_MDPCOMP;
2846 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002847
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002848 return true;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002849}
Saurabh Shahab47c692014-02-12 18:45:57 -08002850
2851//================MDPCompSrcSplit==============================================
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08002852
2853bool MDPCompSrcSplit::validateAndApplyROI(hwc_context_t *ctx,
2854 hwc_display_contents_1_t* list) {
2855 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
2856 hwc_rect_t visibleRect = ctx->listStats[mDpy].lRoi;
2857
2858 for(int i = numAppLayers - 1; i >= 0; i--) {
2859 if(!isValidRect(visibleRect)) {
2860 mCurrentFrame.drop[i] = true;
2861 mCurrentFrame.dropCount++;
2862 continue;
2863 }
2864
2865 const hwc_layer_1_t* layer = &list->hwLayers[i];
2866 hwc_rect_t dstRect = layer->displayFrame;
2867 hwc_rect_t res = getIntersection(visibleRect, dstRect);
2868
2869 if(!isValidRect(res)) {
2870 mCurrentFrame.drop[i] = true;
2871 mCurrentFrame.dropCount++;
2872 } else {
2873 /* Reset frame ROI when any layer which needs scaling also needs ROI
2874 * cropping */
2875 if(!isSameRect(res, dstRect) && needsScaling (layer)) {
2876 ALOGI("%s: Resetting ROI due to scaling", __FUNCTION__);
2877 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
2878 mCurrentFrame.dropCount = 0;
2879 return false;
2880 }
2881
2882 /* deduct any opaque region from visibleRect */
2883 if (layer->blending == HWC_BLENDING_NONE &&
2884 layer->planeAlpha == 0xFF)
2885 visibleRect = deductRect(visibleRect, res);
2886 }
2887 }
2888 return true;
2889}
2890
2891/*
2892 * HW Limitation: ping pong split can always split the ping pong output
2893 * equally across two DSI's. So the ROI programmed should be of equal width
2894 * for both the halves
2895 */
2896void MDPCompSrcSplit::generateROI(hwc_context_t *ctx,
2897 hwc_display_contents_1_t* list) {
2898 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
2899
2900
2901 if(!canPartialUpdate(ctx, list))
2902 return;
2903
2904 struct hwc_rect roi = (struct hwc_rect){0, 0, 0, 0};
2905 hwc_rect fullFrame = (struct hwc_rect) {0, 0,(int)ctx->dpyAttr[mDpy].xres,
2906 (int)ctx->dpyAttr[mDpy].yres};
2907
2908 for(int index = 0; index < numAppLayers; index++ ) {
2909 hwc_layer_1_t* layer = &list->hwLayers[index];
2910
2911 // If we have a RGB layer which needs rotation, no partial update
2912 if(!isYuvBuffer((private_handle_t *)layer->handle) && layer->transform)
2913 return;
2914
2915 if ((mCachedFrame.hnd[index] != layer->handle) ||
2916 isYuvBuffer((private_handle_t *)layer->handle)) {
2917 hwc_rect_t dst = layer->displayFrame;
2918 hwc_rect_t updatingRect = dst;
2919
2920#ifdef QCOM_BSP
2921 if(!needsScaling(layer) && !layer->transform)
2922 {
2923 hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
2924 int x_off = dst.left - src.left;
2925 int y_off = dst.top - src.top;
2926 updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
2927 }
2928#endif
2929
2930 roi = getUnion(roi, updatingRect);
2931 }
2932 }
2933
2934 /* No layer is updating. Still SF wants a refresh.*/
2935 if(!isValidRect(roi))
2936 return;
2937
2938 roi = expandROIFromMidPoint(roi, fullFrame);
2939
2940 hwc_rect lFrame = fullFrame;
2941 lFrame.right /= 2;
2942 hwc_rect lRoi = getIntersection(roi, lFrame);
2943
2944 // Align ROI coordinates to panel restrictions
2945 lRoi = getSanitizeROI(lRoi, lFrame);
2946
2947 hwc_rect rFrame = fullFrame;
2948 rFrame.left = lFrame.right;
2949 hwc_rect rRoi = getIntersection(roi, rFrame);
2950
2951 // Align ROI coordinates to panel restrictions
2952 rRoi = getSanitizeROI(rRoi, rFrame);
2953
2954 roi = getUnion(lRoi, rRoi);
2955
2956 ctx->listStats[mDpy].lRoi = roi;
2957 if(!validateAndApplyROI(ctx, list))
2958 resetROI(ctx, mDpy);
2959
2960 ALOGD_IF(isDebug(),"%s: generated ROI: [%d, %d, %d, %d] [%d, %d, %d, %d]",
2961 __FUNCTION__,
2962 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
2963 ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom,
2964 ctx->listStats[mDpy].rRoi.left, ctx->listStats[mDpy].rRoi.top,
2965 ctx->listStats[mDpy].rRoi.right, ctx->listStats[mDpy].rRoi.bottom);
2966}
2967
Saurabh Shahab47c692014-02-12 18:45:57 -08002968bool MDPCompSrcSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
Saurabh Shahc62f3982014-03-05 14:28:26 -08002969 MdpPipeInfoSplit& pipe_info) {
Saurabh Shahab47c692014-02-12 18:45:57 -08002970 private_handle_t *hnd = (private_handle_t *)layer->handle;
2971 hwc_rect_t dst = layer->displayFrame;
2972 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
2973 pipe_info.lIndex = ovutils::OV_INVALID;
2974 pipe_info.rIndex = ovutils::OV_INVALID;
2975
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08002976 if(qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() && !mDpy)
2977 trimAgainstROI(ctx,crop, dst);
2978
Saurabh Shahab47c692014-02-12 18:45:57 -08002979 //If 2 pipes are staged on a single stage of a mixer, then the left pipe
2980 //should have a higher priority than the right one. Pipe priorities are
2981 //starting with VG0, VG1 ... , RGB0 ..., DMA1
Saurabh Shahab47c692014-02-12 18:45:57 -08002982
Saurabh Shahc62f3982014-03-05 14:28:26 -08002983 Overlay::PipeSpecs pipeSpecs;
2984 pipeSpecs.formatClass = isYuvBuffer(hnd) ?
2985 Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
2986 pipeSpecs.needsScaling = qhwc::needsScaling(layer);
2987 pipeSpecs.dpy = mDpy;
2988 pipeSpecs.fb = false;
2989
Saurabh Shahab47c692014-02-12 18:45:57 -08002990 //1 pipe by default for a layer
Saurabh Shahc62f3982014-03-05 14:28:26 -08002991 pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahab47c692014-02-12 18:45:57 -08002992 if(pipe_info.lIndex == ovutils::OV_INVALID) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002993 return false;
Saurabh Shahab47c692014-02-12 18:45:57 -08002994 }
2995
Saurabh Shahea7a01d2014-05-22 17:45:36 -07002996 /* Use 2 pipes IF
2997 a) Layer's crop width is > 2048 or
2998 b) Layer's dest width > 2048 or
2999 c) On primary, driver has indicated with caps to split always. This is
3000 based on an empirically derived value of panel height. Applied only
3001 if the layer's width is > mixer's width
3002 */
3003
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +05303004 MDPVersion& mdpHw = MDPVersion::getInstance();
Saurabh Shahea7a01d2014-05-22 17:45:36 -07003005 bool primarySplitAlways = (mDpy == HWC_DISPLAY_PRIMARY) and
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +05303006 mdpHw.isSrcSplitAlways();
Saurabh Shah514759d2014-11-11 18:02:24 -08003007 const uint32_t lSplit = getLeftSplit(ctx, mDpy);
3008 const uint32_t dstWidth = dst.right - dst.left;
3009 const uint32_t dstHeight = dst.bottom - dst.top;
Saurabh Shah05f4e222015-02-05 14:36:22 -08003010 uint32_t cropWidth = has90Transform(layer) ? crop.bottom - crop.top :
Saurabh Shah189f23d2014-09-26 17:21:00 -07003011 crop.right - crop.left;
Saurabh Shah05f4e222015-02-05 14:36:22 -08003012 uint32_t cropHeight = has90Transform(layer) ? crop.right - crop.left :
Saurabh Shah514759d2014-11-11 18:02:24 -08003013 crop.bottom - crop.top;
3014 //Approximation to actual clock, ignoring the common factors in pipe and
3015 //mixer cases like line_time
3016 const uint32_t layerClock = getLayerClock(dstWidth, dstHeight, cropHeight);
3017 const uint32_t mixerClock = lSplit;
Saurabh Shahea7a01d2014-05-22 17:45:36 -07003018
Saurabh Shah05f4e222015-02-05 14:36:22 -08003019 const uint32_t downscale = getRotDownscale(ctx, layer);
3020 if(downscale) {
3021 cropWidth /= downscale;
3022 cropHeight /= downscale;
3023 }
3024
Jeykumar Sankaran39305802014-12-12 17:55:57 -08003025 if(dstWidth > mdpHw.getMaxPipeWidth() or
3026 cropWidth > mdpHw.getMaxPipeWidth() or
Saurabh Shah514759d2014-11-11 18:02:24 -08003027 (primarySplitAlways and
3028 (cropWidth > lSplit or layerClock > mixerClock))) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08003029 pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahab47c692014-02-12 18:45:57 -08003030 if(pipe_info.rIndex == ovutils::OV_INVALID) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08003031 return false;
Saurabh Shahdd8237a2014-02-28 14:29:09 -08003032 }
3033
Jeykumar Sankaran89e23ab2015-01-28 15:57:46 -08003034 if(ctx->mOverlay->needsPrioritySwap(pipe_info.lIndex,
3035 pipe_info.rIndex)) {
Saurabh Shahdd8237a2014-02-28 14:29:09 -08003036 qhwc::swap(pipe_info.lIndex, pipe_info.rIndex);
Saurabh Shahab47c692014-02-12 18:45:57 -08003037 }
3038 }
3039
3040 return true;
3041}
3042
Saurabh Shahab47c692014-02-12 18:45:57 -08003043int MDPCompSrcSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
3044 PipeLayerPair& PipeLayerPair) {
3045 private_handle_t *hnd = (private_handle_t *)layer->handle;
3046 if(!hnd) {
3047 ALOGE("%s: layer handle is NULL", __FUNCTION__);
3048 return -1;
3049 }
3050 MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
3051 MdpPipeInfoSplit& mdp_info =
3052 *(static_cast<MdpPipeInfoSplit*>(PipeLayerPair.pipeInfo));
3053 Rotator **rot = &PipeLayerPair.rot;
3054 eZorder z = static_cast<eZorder>(mdp_info.zOrder);
Saurabh Shahab47c692014-02-12 18:45:57 -08003055 eDest lDest = mdp_info.lIndex;
3056 eDest rDest = mdp_info.rIndex;
3057 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
3058 hwc_rect_t dst = layer->displayFrame;
3059 int transform = layer->transform;
3060 eTransform orient = static_cast<eTransform>(transform);
Saurabh Shahab47c692014-02-12 18:45:57 -08003061 int rotFlags = ROT_FLAGS_NONE;
Sushil Chauhan65e26302015-01-14 10:48:57 -08003062 uint32_t format = ovutils::getMdpFormat(hnd->format, hnd->flags);
Saurabh Shahab47c692014-02-12 18:45:57 -08003063 Whf whf(getWidth(hnd), getHeight(hnd), format, hnd->size);
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05003064 eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shahab47c692014-02-12 18:45:57 -08003065
3066 ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
3067 "dest_pipeR: %d",__FUNCTION__, layer, z, lDest, rDest);
3068
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08003069 if(qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() && !mDpy) {
3070 /* MDP driver crops layer coordinates against ROI in Non-Split
3071 * and Split MDP comp. But HWC needs to crop them for source split.
3072 * Reason: 1) Source split is efficient only when the final effective
3073 * load is distributed evenly across mixers.
3074 * 2) We have to know the effective width of the layer that
3075 * the ROI needs to find the no. of pipes the layer needs.
3076 */
3077 trimAgainstROI(ctx, crop, dst);
3078 }
3079
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05003080 if(needs3DComposition(ctx, mDpy) &&
3081 get3DFormat(hnd) != HAL_NO_3D){
3082 return configure3DVideo(ctx, layer, mDpy, mdpFlags, z, lDest,
3083 rDest, &PipeLayerPair.rot);
3084 }
3085
Saurabh Shahab47c692014-02-12 18:45:57 -08003086 // Handle R/B swap
3087 if (layer->flags & HWC_FORMAT_RB_SWAP) {
3088 if (hnd->format == HAL_PIXEL_FORMAT_RGBA_8888)
3089 whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRA_8888);
3090 else if (hnd->format == HAL_PIXEL_FORMAT_RGBX_8888)
3091 whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
3092 }
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07003093 // update source crop and destination position of AIV video layer.
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07003094 if(ctx->listStats[mDpy].mAIVVideoMode && isYuvBuffer(hnd)) {
3095 updateCoordinates(ctx, crop, dst, mDpy);
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07003096 }
Ramkumar Radhakrishnana5c72872014-08-28 19:04:18 -07003097 /* Calculate the external display position based on MDP downscale,
3098 ActionSafe, and extorientation features. */
3099 calcExtDisplayPosition(ctx, hnd, mDpy, crop, dst, transform, orient);
Saurabh Shahab47c692014-02-12 18:45:57 -08003100
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003101 int downscale = getRotDownscale(ctx, layer);
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003102 setMdpFlags(ctx, layer, mdpFlags, downscale, transform);
Saurabh Shahab47c692014-02-12 18:45:57 -08003103
3104 if(lDest != OV_INVALID && rDest != OV_INVALID) {
3105 //Enable overfetch
Saurabh Shah97e2d802014-04-14 18:03:54 -07003106 setMdpFlags(mdpFlags, OV_MDSS_MDP_DUAL_PIPE);
Saurabh Shahab47c692014-02-12 18:45:57 -08003107 }
3108
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003109 if((has90Transform(layer) or downscale) and isRotationDoable(ctx, hnd)) {
Saurabh Shahab47c692014-02-12 18:45:57 -08003110 (*rot) = ctx->mRotMgr->getNext();
3111 if((*rot) == NULL) return -1;
Saurabh Shah39240c92014-03-31 10:31:42 -07003112 ctx->mLayerRotMap[mDpy]->add(layer, *rot);
Saurabh Shah1bd5b6f2014-05-19 12:23:13 -07003113 //If the video is using a single pipe, enable BWC
3114 if(rDest == OV_INVALID) {
Saurabh Shahcd018352014-11-11 13:54:19 -08003115 BwcPM::setBwc(ctx, mDpy, hnd, crop, dst, transform, downscale,
3116 mdpFlags);
Saurabh Shah1bd5b6f2014-05-19 12:23:13 -07003117 }
Saurabh Shahab47c692014-02-12 18:45:57 -08003118 //Configure rotator for pre-rotation
Saurabh Shah97e2d802014-04-14 18:03:54 -07003119 if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale) < 0) {
Saurabh Shahab47c692014-02-12 18:45:57 -08003120 ALOGE("%s: configRotator failed!", __FUNCTION__);
3121 return -1;
3122 }
Saurabh Shah8ec9b5e2014-06-30 14:37:17 -07003123 updateSource(orient, whf, crop, *rot);
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003124 rotFlags |= ovutils::ROT_PREROTATED;
Saurabh Shahab47c692014-02-12 18:45:57 -08003125 }
3126
3127 //If 2 pipes being used, divide layer into half, crop and dst
3128 hwc_rect_t cropL = crop;
3129 hwc_rect_t cropR = crop;
3130 hwc_rect_t dstL = dst;
3131 hwc_rect_t dstR = dst;
3132 if(lDest != OV_INVALID && rDest != OV_INVALID) {
3133 cropL.right = (crop.right + crop.left) / 2;
3134 cropR.left = cropL.right;
3135 sanitizeSourceCrop(cropL, cropR, hnd);
3136
Saurabh Shahb729b192014-08-15 18:04:24 -07003137 bool cropSwap = false;
Saurabh Shahab47c692014-02-12 18:45:57 -08003138 //Swap crops on H flip since 2 pipes are being used
3139 if((orient & OVERLAY_TRANSFORM_FLIP_H) && (*rot) == NULL) {
3140 hwc_rect_t tmp = cropL;
3141 cropL = cropR;
3142 cropR = tmp;
Saurabh Shahb729b192014-08-15 18:04:24 -07003143 cropSwap = true;
Saurabh Shahab47c692014-02-12 18:45:57 -08003144 }
3145
Saurabh Shahb729b192014-08-15 18:04:24 -07003146 //cropSwap trick: If the src and dst widths are both odd, let us say
3147 //2507, then splitting both into half would cause left width to be 1253
3148 //and right 1254. If crop is swapped because of H flip, this will cause
3149 //left crop width to be 1254, whereas left dst width remains 1253, thus
3150 //inducing a scaling that is unaccounted for. To overcome that we add 1
3151 //to the dst width if there is a cropSwap. So if the original width was
3152 //2507, the left dst width will be 1254. Even if the original width was
3153 //even for ex: 2508, the left dst width will still remain 1254.
3154 dstL.right = (dst.right + dst.left + cropSwap) / 2;
Saurabh Shahab47c692014-02-12 18:45:57 -08003155 dstR.left = dstL.right;
3156 }
3157
3158 //For the mdp, since either we are pre-rotating or MDP does flips
3159 orient = OVERLAY_TRANSFORM_0;
3160 transform = 0;
3161
3162 //configure left pipe
3163 if(lDest != OV_INVALID) {
Saurabh Shah2c8ad052014-08-15 13:27:46 -07003164 PipeArgs pargL(mdpFlags, whf, z,
Saurabh Shahab47c692014-02-12 18:45:57 -08003165 static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
3166 (ovutils::eBlending) getBlending(layer->blending));
3167
3168 if(configMdp(ctx->mOverlay, pargL, orient,
3169 cropL, dstL, metadata, lDest) < 0) {
3170 ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
3171 return -1;
3172 }
3173 }
3174
3175 //configure right pipe
3176 if(rDest != OV_INVALID) {
Saurabh Shah2c8ad052014-08-15 13:27:46 -07003177 PipeArgs pargR(mdpFlags, whf, z,
Saurabh Shahab47c692014-02-12 18:45:57 -08003178 static_cast<eRotFlags>(rotFlags),
3179 layer->planeAlpha,
3180 (ovutils::eBlending) getBlending(layer->blending));
3181 if(configMdp(ctx->mOverlay, pargR, orient,
3182 cropR, dstR, metadata, rDest) < 0) {
3183 ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
3184 return -1;
3185 }
3186 }
3187
3188 return 0;
3189}
3190
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -08003191bool MDPComp::getPartialUpdatePref(hwc_context_t *ctx) {
3192 Locker::Autolock _l(ctx->mDrawLock);
3193 const int fbNum = Overlay::getFbForDpy(Overlay::DPY_PRIMARY);
3194 char path[MAX_SYSFS_FILE_PATH];
3195 snprintf (path, sizeof(path), "sys/class/graphics/fb%d/dyn_pu", fbNum);
3196 int fd = open(path, O_RDONLY);
3197 if(fd < 0) {
3198 ALOGE("%s: Failed to open sysfd node: %s", __FUNCTION__, path);
3199 return -1;
3200 }
3201 char value[4];
3202 ssize_t size_read = read(fd, value, sizeof(value)-1);
3203 if(size_read <= 0) {
3204 ALOGE("%s: Failed to read sysfd node: %s", __FUNCTION__, path);
3205 close(fd);
3206 return -1;
3207 }
3208 close(fd);
3209 value[size_read] = '\0';
3210 return atoi(value);
3211}
3212
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003213int MDPComp::setPartialUpdatePref(hwc_context_t *ctx, bool enable) {
3214 Locker::Autolock _l(ctx->mDrawLock);
3215 const int fbNum = Overlay::getFbForDpy(Overlay::DPY_PRIMARY);
3216 char path[MAX_SYSFS_FILE_PATH];
3217 snprintf (path, sizeof(path), "sys/class/graphics/fb%d/dyn_pu", fbNum);
3218 int fd = open(path, O_WRONLY);
3219 if(fd < 0) {
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -08003220 ALOGE("%s: Failed to open sysfd node: %s", __FUNCTION__, path);
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003221 return -1;
3222 }
3223 char value[4];
3224 snprintf(value, sizeof(value), "%d", (int)enable);
3225 ssize_t ret = write(fd, value, strlen(value));
3226 if(ret <= 0) {
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -08003227 ALOGE("%s: Failed to write to sysfd nodes: %s", __FUNCTION__, path);
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003228 close(fd);
3229 return -1;
3230 }
3231 close(fd);
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003232 return 0;
3233}
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08003234
3235bool MDPComp::loadPerfLib() {
3236 char perfLibPath[PROPERTY_VALUE_MAX] = {0};
3237 bool success = false;
3238 if((property_get("ro.vendor.extension_library", perfLibPath, NULL) <= 0)) {
3239 ALOGE("vendor library not set in ro.vendor.extension_library");
3240 return false;
3241 }
3242
3243 sLibPerfHint = dlopen(perfLibPath, RTLD_NOW);
3244 if(sLibPerfHint) {
3245 *(void **)&sPerfLockAcquire = dlsym(sLibPerfHint, "perf_lock_acq");
3246 *(void **)&sPerfLockRelease = dlsym(sLibPerfHint, "perf_lock_rel");
3247 if (!sPerfLockAcquire || !sPerfLockRelease) {
3248 ALOGE("Failed to load symbols for perfLock");
3249 dlclose(sLibPerfHint);
3250 sLibPerfHint = NULL;
3251 return false;
3252 }
3253 success = true;
3254 ALOGI("Successfully Loaded perf hint API's");
3255 } else {
3256 ALOGE("Failed to open %s : %s", perfLibPath, dlerror());
3257 }
3258 return success;
3259}
3260
3261void MDPComp::setPerfHint(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
3262 if ((sPerfHintWindow < 0) || mDpy || !sLibPerfHint) {
3263 return;
3264 }
3265 static int count = sPerfHintWindow;
3266 static int perflockFlag = 0;
3267
3268 /* Send hint to mpctl when single layer is updated
3269 * for a successful number of windows. Hint release
3270 * happens immediately upon multiple layer update.
3271 */
3272 if (onlyVideosUpdating(ctx, list)) {
3273 if(count) {
3274 count--;
3275 }
3276 } else {
3277 if (perflockFlag) {
3278 perflockFlag = 0;
3279 sPerfLockRelease(sPerfLockHandle);
3280 }
3281 count = sPerfHintWindow;
3282 }
3283 if (count == 0 && !perflockFlag) {
3284 int perfHint = 0x4501; // 45-display layer hint, 01-Enable
3285 sPerfLockHandle = sPerfLockAcquire(0 /*handle*/, 0/*duration*/,
3286 &perfHint, sizeof(perfHint)/sizeof(int));
Arun Kumar K.R8b927022015-02-24 12:34:21 -08003287 if(sPerfLockHandle > 0) {
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08003288 perflockFlag = 1;
3289 }
3290 }
3291}
3292
Naseer Ahmed7c958d42012-07-31 18:57:03 -07003293}; //namespace
3294