blob: 3e3638ce26aceeb7e0a452649ef1465d61be2e09 [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
Naseer Ahmede77f8082013-10-10 13:42:48 -0400473 if(!isSecureBuffer(hnd) && isNonIntegralSourceCrop(layer->sourceCropf))
Naseer Ahmede850a802013-09-06 13:12:52 -0400474 return false;
475
Saurabh Shah62e1d732013-09-17 10:44:05 -0700476 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
Saurabh Shah4fdde762013-04-30 18:47:33 -0700477 hwc_rect_t dst = layer->displayFrame;
Saurabh Shahb6810df2014-06-17 16:00:22 -0700478 bool rotated90 = (bool)(layer->transform & HAL_TRANSFORM_ROT_90);
Saurabh Shahe28a4022014-06-13 11:41:13 -0700479 int crop_w = rotated90 ? crop.bottom - crop.top : crop.right - crop.left;
480 int crop_h = rotated90 ? crop.right - crop.left : crop.bottom - crop.top;
Saurabh Shah4fdde762013-04-30 18:47:33 -0700481 int dst_w = dst.right - dst.left;
482 int dst_h = dst.bottom - dst.top;
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800483 float w_scale = ((float)crop_w / (float)dst_w);
484 float h_scale = ((float)crop_h / (float)dst_h);
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530485 MDPVersion& mdpHw = MDPVersion::getInstance();
Saurabh Shah4fdde762013-04-30 18:47:33 -0700486
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800487 /* Workaround for MDP HW limitation in DSI command mode panels where
488 * FPS will not go beyond 30 if buffers on RGB pipes are of width or height
489 * less than 5 pixels
Sravan Kumar D.V.Nad5d9292013-04-24 14:23:04 +0530490 * There also is a HW limilation in MDP, minimum block size is 2x2
491 * Fallback to GPU if height is less than 2.
492 */
Saurabh Shah189f23d2014-09-26 17:21:00 -0700493 if(mdpHw.hasMinCropWidthLimitation() and (crop_w < 5 or crop_h < 5))
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800494 return false;
495
Ramkumar Radhakrishnan1a763e92015-03-19 16:46:46 -0700496 /* crop_w and crop_h should be even for yuv layer, so fallback to GPU for
497 * those cases
498 */
499 if(isYuvBuffer(hnd) && (crop_w < 2 || crop_h < 2)) {
500 return false;
501 }
502
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800503 if((w_scale > 1.0f) || (h_scale > 1.0f)) {
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530504 const uint32_t maxMDPDownscale = mdpHw.getMaxMDPDownscale();
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800505 const float w_dscale = w_scale;
506 const float h_dscale = h_scale;
507
Jeykumar Sankaran1706a772013-11-27 12:55:19 -0800508 if(ctx->mMDP.version >= qdutils::MDSS_V5) {
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700509
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530510 if(!mdpHw.supportsDecimation()) {
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700511 /* On targets that doesnt support Decimation (eg.,8x26)
512 * maximum downscale support is overlay pipe downscale.
513 */
Jeykumar Sankaran39305802014-12-12 17:55:57 -0800514 if(crop_w > (int) mdpHw.getMaxPipeWidth() ||
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530515 w_dscale > maxMDPDownscale ||
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700516 h_dscale > maxMDPDownscale)
Jeykumar Sankaran1706a772013-11-27 12:55:19 -0800517 return false;
518 } else {
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700519 // Decimation on macrotile format layers is not supported.
520 if(isTileRendered(hnd)) {
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530521 /* Bail out if
522 * 1. Src crop > Mixer limit on nonsplit MDPComp
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700523 * 2. exceeds maximum downscale limit
524 */
Jeykumar Sankaran39305802014-12-12 17:55:57 -0800525 if(((crop_w > (int) mdpHw.getMaxPipeWidth()) &&
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530526 !sSrcSplitEnabled) ||
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700527 w_dscale > maxMDPDownscale ||
528 h_dscale > maxMDPDownscale) {
529 return false;
530 }
531 } else if(w_dscale > 64 || h_dscale > 64)
Jeykumar Sankaran1706a772013-11-27 12:55:19 -0800532 return false;
533 }
534 } else { //A-family
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700535 if(w_dscale > maxMDPDownscale || h_dscale > maxMDPDownscale)
Saurabh Shah4fdde762013-04-30 18:47:33 -0700536 return false;
537 }
Saurabh Shah4fdde762013-04-30 18:47:33 -0700538 }
539
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800540 if((w_scale < 1.0f) || (h_scale < 1.0f)) {
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530541 const uint32_t upscale = mdpHw.getMaxMDPUpscale();
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800542 const float w_uscale = 1.0f / w_scale;
543 const float h_uscale = 1.0f / h_scale;
544
545 if(w_uscale > upscale || h_uscale > upscale)
546 return false;
547 }
548
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800549 return true;
550}
551
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800552bool MDPComp::isFrameDoable(hwc_context_t *ctx) {
Saurabh Shahaa236822013-04-24 18:07:26 -0700553 bool ret = true;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800554
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800555 if(!isEnabled()) {
556 ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
Saurabh Shahaa236822013-04-24 18:07:26 -0700557 ret = false;
Saurabh Shah19740d02015-04-10 10:05:42 -0700558 } else if(ctx->mVideoTransFlag && isSecondaryConnected(ctx)) {
Saurabh Shahd4e65852013-06-17 11:33:53 -0700559 //1 Padding round to shift pipes across mixers
560 ALOGD_IF(isDebug(),"%s: MDP Comp. video transition padding round",
561 __FUNCTION__);
562 ret = false;
Raj Kamalc0d34242015-03-17 20:53:14 +0530563 } else if((qdutils::MDPVersion::getInstance().is8x26() ||
564 qdutils::MDPVersion::getInstance().is8x16() ||
Prabhanjan Kandulafc541b32015-03-30 20:56:16 +0530565 qdutils::MDPVersion::getInstance().is8x39() ||
566 qdutils::MDPVersion::getInstance().is8x52()) &&
Raj Kamalc0d34242015-03-17 20:53:14 +0530567 !mDpy && isSecondaryAnimating(ctx) &&
568 isYuvPresent(ctx,HWC_DISPLAY_VIRTUAL)) {
569 ALOGD_IF(isDebug(),"%s: Display animation in progress",
570 __FUNCTION__);
571 ret = false;
Ramkumar Radhakrishnanf26fe9e2014-09-09 13:47:54 -0700572 } else if(qdutils::MDPVersion::getInstance().getTotalPipes() < 8) {
573 /* TODO: freeing up all the resources only for the targets having total
574 number of pipes < 8. Need to analyze number of VIG pipes used
575 for primary in previous draw cycle and accordingly decide
576 whether to fall back to full GPU comp or video only comp
577 */
578 if(isSecondaryConfiguring(ctx)) {
579 ALOGD_IF( isDebug(),"%s: External Display connection is pending",
580 __FUNCTION__);
581 ret = false;
582 } else if(ctx->isPaddingRound) {
583 ALOGD_IF(isDebug(), "%s: padding round invoked for dpy %d",
584 __FUNCTION__,mDpy);
585 ret = false;
586 }
Tatenda Chipeperekwadc8d7082014-11-04 16:41:50 -0800587 } else if (ctx->isDMAStateChanging) {
588 // Bail out if a padding round has been invoked in order to switch DMA
589 // state to block mode. We need this to cater for the case when a layer
590 // requires rotation in the current frame.
591 ALOGD_IF(isDebug(), "%s: padding round invoked to switch DMA state",
592 __FUNCTION__);
593 return false;
Saurabh Shah0ceeb6a2013-04-23 10:46:07 -0700594 }
Tatenda Chipeperekwadc8d7082014-11-04 16:41:50 -0800595
Saurabh Shahaa236822013-04-24 18:07:26 -0700596 return ret;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800597}
598
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800599void MDPCompNonSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect &crop,
600 hwc_rect &dst) {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800601 hwc_rect_t roi = ctx->listStats[mDpy].lRoi;
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800602 dst = getIntersection(dst, roi);
603 crop = dst;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800604}
605
606/* 1) Identify layers that are not visible or lying outside the updating ROI and
607 * drop them from composition.
608 * 2) If we have a scaling layer which needs cropping against generated
609 * ROI, reset ROI to full resolution. */
610bool MDPCompNonSplit::validateAndApplyROI(hwc_context_t *ctx,
611 hwc_display_contents_1_t* list) {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700612 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800613 hwc_rect_t visibleRect = ctx->listStats[mDpy].lRoi;
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800614
615 for(int i = numAppLayers - 1; i >= 0; i--){
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800616 if(!isValidRect(visibleRect)) {
617 mCurrentFrame.drop[i] = true;
618 mCurrentFrame.dropCount++;
Jeykumar Sankaran0b961452014-01-21 17:26:12 -0800619 continue;
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800620 }
621
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700622 const hwc_layer_1_t* layer = &list->hwLayers[i];
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700623 hwc_rect_t dstRect = layer->displayFrame;
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800624 hwc_rect_t res = getIntersection(visibleRect, dstRect);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700625
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700626 if(!isValidRect(res)) {
627 mCurrentFrame.drop[i] = true;
628 mCurrentFrame.dropCount++;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800629 } else {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700630 /* Reset frame ROI when any layer which needs scaling also needs ROI
631 * cropping */
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800632 if(!isSameRect(res, dstRect) && needsScaling (layer)) {
Arpita Banerjeed8965982013-11-08 17:27:33 -0800633 ALOGI("%s: Resetting ROI due to scaling", __FUNCTION__);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700634 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
635 mCurrentFrame.dropCount = 0;
636 return false;
637 }
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800638
Jeykumar Sankaran0b961452014-01-21 17:26:12 -0800639 /* deduct any opaque region from visibleRect */
radhakrishna4efbdd62014-11-03 13:19:27 +0530640 if (layer->blending == HWC_BLENDING_NONE &&
641 layer->planeAlpha == 0xFF)
Jeykumar Sankaran0b961452014-01-21 17:26:12 -0800642 visibleRect = deductRect(visibleRect, res);
643 }
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700644 }
645 return true;
646}
647
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800648/* Calculate ROI for the frame by accounting all the layer's dispalyFrame which
649 * are updating. If DirtyRegion is applicable, calculate it by accounting all
650 * the changing layer's dirtyRegion. */
651void MDPCompNonSplit::generateROI(hwc_context_t *ctx,
652 hwc_display_contents_1_t* list) {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700653 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800654 if(!canPartialUpdate(ctx, list))
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700655 return;
656
657 struct hwc_rect roi = (struct hwc_rect){0, 0, 0, 0};
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800658 hwc_rect fullFrame = (struct hwc_rect) {0, 0,(int)ctx->dpyAttr[mDpy].xres,
659 (int)ctx->dpyAttr[mDpy].yres};
660
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700661 for(int index = 0; index < numAppLayers; index++ ) {
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800662 hwc_layer_1_t* layer = &list->hwLayers[index];
663 if ((mCachedFrame.hnd[index] != layer->handle) ||
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800664 isYuvBuffer((private_handle_t *)layer->handle)) {
Jeykumar Sankaran455678c2014-05-30 10:22:38 -0700665 hwc_rect_t dst = layer->displayFrame;
666 hwc_rect_t updatingRect = dst;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800667
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800668#ifdef QCOM_BSP
Dileep Kumar Reddi7399d5c2014-12-31 18:01:19 +0530669 if(!needsScaling(layer) && !layer->transform &&
670 (!isYuvBuffer((private_handle_t *)layer->handle)))
Jeykumar Sankaran455678c2014-05-30 10:22:38 -0700671 {
672 hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
673 int x_off = dst.left - src.left;
674 int y_off = dst.top - src.top;
675 updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
676 }
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800677#endif
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800678
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800679 roi = getUnion(roi, updatingRect);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700680 }
681 }
682
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800683 /* No layer is updating. Still SF wants a refresh.*/
684 if(!isValidRect(roi))
685 return;
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800686
687 // Align ROI coordinates to panel restrictions
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800688 roi = getSanitizeROI(roi, fullFrame);
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800689
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800690 ctx->listStats[mDpy].lRoi = roi;
691 if(!validateAndApplyROI(ctx, list))
692 resetROI(ctx, mDpy);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700693
694 ALOGD_IF(isDebug(),"%s: generated ROI: [%d, %d, %d, %d]", __FUNCTION__,
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800695 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
696 ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom);
697}
698
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800699void MDPCompSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect &crop,
700 hwc_rect &dst) {
701 hwc_rect roi = getUnion(ctx->listStats[mDpy].lRoi,
702 ctx->listStats[mDpy].rRoi);
703 hwc_rect tmpDst = getIntersection(dst, roi);
704 if(!isSameRect(dst, tmpDst)) {
705 crop.left = crop.left + (tmpDst.left - dst.left);
706 crop.top = crop.top + (tmpDst.top - dst.top);
707 crop.right = crop.left + (tmpDst.right - tmpDst.left);
708 crop.bottom = crop.top + (tmpDst.bottom - tmpDst.top);
709 dst = tmpDst;
710 }
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800711}
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800712
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800713/* 1) Identify layers that are not visible or lying outside BOTH the updating
714 * ROI's and drop them from composition. If a layer is spanning across both
715 * the halves of the screen but needed by only ROI, the non-contributing
716 * half will not be programmed for MDP.
717 * 2) If we have a scaling layer which needs cropping against generated
718 * ROI, reset ROI to full resolution. */
719bool MDPCompSplit::validateAndApplyROI(hwc_context_t *ctx,
720 hwc_display_contents_1_t* list) {
721
722 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
723
724 hwc_rect_t visibleRectL = ctx->listStats[mDpy].lRoi;
725 hwc_rect_t visibleRectR = ctx->listStats[mDpy].rRoi;
726
727 for(int i = numAppLayers - 1; i >= 0; i--){
728 if(!isValidRect(visibleRectL) && !isValidRect(visibleRectR))
729 {
730 mCurrentFrame.drop[i] = true;
731 mCurrentFrame.dropCount++;
732 continue;
733 }
734
735 const hwc_layer_1_t* layer = &list->hwLayers[i];
736 hwc_rect_t dstRect = layer->displayFrame;
737
738 hwc_rect_t l_res = getIntersection(visibleRectL, dstRect);
739 hwc_rect_t r_res = getIntersection(visibleRectR, dstRect);
740 hwc_rect_t res = getUnion(l_res, r_res);
741
742 if(!isValidRect(l_res) && !isValidRect(r_res)) {
743 mCurrentFrame.drop[i] = true;
744 mCurrentFrame.dropCount++;
745 } else {
746 /* Reset frame ROI when any layer which needs scaling also needs ROI
747 * cropping */
748 if(!isSameRect(res, dstRect) && needsScaling (layer)) {
749 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
750 mCurrentFrame.dropCount = 0;
751 return false;
752 }
753
radhakrishna4efbdd62014-11-03 13:19:27 +0530754 if (layer->blending == HWC_BLENDING_NONE &&
755 layer->planeAlpha == 0xFF) {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800756 visibleRectL = deductRect(visibleRectL, l_res);
757 visibleRectR = deductRect(visibleRectR, r_res);
758 }
759 }
760 }
761 return true;
762}
763/* Calculate ROI for the frame by accounting all the layer's dispalyFrame which
764 * are updating. If DirtyRegion is applicable, calculate it by accounting all
765 * the changing layer's dirtyRegion. */
766void MDPCompSplit::generateROI(hwc_context_t *ctx,
767 hwc_display_contents_1_t* list) {
768 if(!canPartialUpdate(ctx, list))
769 return;
770
771 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
772 int lSplit = getLeftSplit(ctx, mDpy);
773
774 int hw_h = (int)ctx->dpyAttr[mDpy].yres;
775 int hw_w = (int)ctx->dpyAttr[mDpy].xres;
776
777 struct hwc_rect l_frame = (struct hwc_rect){0, 0, lSplit, hw_h};
778 struct hwc_rect r_frame = (struct hwc_rect){lSplit, 0, hw_w, hw_h};
779
780 struct hwc_rect l_roi = (struct hwc_rect){0, 0, 0, 0};
781 struct hwc_rect r_roi = (struct hwc_rect){0, 0, 0, 0};
782
783 for(int index = 0; index < numAppLayers; index++ ) {
784 hwc_layer_1_t* layer = &list->hwLayers[index];
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800785 private_handle_t *hnd = (private_handle_t *)layer->handle;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800786 if ((mCachedFrame.hnd[index] != layer->handle) ||
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800787 isYuvBuffer(hnd)) {
Jeykumar Sankaran71e597c2014-05-07 16:23:14 -0700788 hwc_rect_t dst = layer->displayFrame;
789 hwc_rect_t updatingRect = dst;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800790
791#ifdef QCOM_BSP
792 if(!needsScaling(layer) && !layer->transform)
Jeykumar Sankaran71e597c2014-05-07 16:23:14 -0700793 {
794 hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
795 int x_off = dst.left - src.left;
796 int y_off = dst.top - src.top;
797 updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
798 }
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800799#endif
800
801 hwc_rect_t l_dst = getIntersection(l_frame, updatingRect);
802 if(isValidRect(l_dst))
803 l_roi = getUnion(l_roi, l_dst);
804
805 hwc_rect_t r_dst = getIntersection(r_frame, updatingRect);
806 if(isValidRect(r_dst))
807 r_roi = getUnion(r_roi, r_dst);
808 }
809 }
810
Jeykumar Sankarana40a9342014-04-25 09:37:10 -0700811 /* For panels that cannot accept commands in both the interfaces, we cannot
812 * send two ROI's (for each half). We merge them into single ROI and split
813 * them across lSplit for MDP mixer use. The ROI's will be merged again
814 * finally before udpating the panel in the driver. */
815 if(qdutils::MDPVersion::getInstance().needsROIMerge()) {
816 hwc_rect_t temp_roi = getUnion(l_roi, r_roi);
817 l_roi = getIntersection(temp_roi, l_frame);
818 r_roi = getIntersection(temp_roi, r_frame);
819 }
820
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800821 /* No layer is updating. Still SF wants a refresh. */
822 if(!isValidRect(l_roi) && !isValidRect(r_roi))
823 return;
824
825 l_roi = getSanitizeROI(l_roi, l_frame);
826 r_roi = getSanitizeROI(r_roi, r_frame);
827
828 ctx->listStats[mDpy].lRoi = l_roi;
829 ctx->listStats[mDpy].rRoi = r_roi;
830
831 if(!validateAndApplyROI(ctx, list))
832 resetROI(ctx, mDpy);
833
834 ALOGD_IF(isDebug(),"%s: generated L_ROI: [%d, %d, %d, %d]"
835 "R_ROI: [%d, %d, %d, %d]", __FUNCTION__,
836 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
837 ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom,
838 ctx->listStats[mDpy].rRoi.left, ctx->listStats[mDpy].rRoi.top,
839 ctx->listStats[mDpy].rRoi.right, ctx->listStats[mDpy].rRoi.bottom);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700840}
841
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800842/* Checks for conditions where all the layers marked for MDP comp cannot be
843 * bypassed. On such conditions we try to bypass atleast YUV layers */
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800844bool MDPComp::tryFullFrame(hwc_context_t *ctx,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800845 hwc_display_contents_1_t* list){
846
Saurabh Shahaa236822013-04-24 18:07:26 -0700847 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800848
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -0700849 // Fall back to video only composition, if AIV video mode is enabled
850 if(ctx->listStats[mDpy].mAIVVideoMode) {
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -0700851 ALOGD_IF(isDebug(), "%s: AIV Video Mode enabled dpy %d",
852 __FUNCTION__, mDpy);
853 return false;
854 }
855
Praveena Pachipulusu47346c22014-12-04 11:06:41 +0530856 /* No Idle fall back if secure display or secure RGB layers are present
857 * or if there is only a single layer being composed */
858 if(sIdleFallBack && !ctx->listStats[mDpy].secureUI &&
859 !ctx->listStats[mDpy].secureRGBCount &&
860 (ctx->listStats[mDpy].numAppLayers > 1)) {
Saurabh Shah2d998a92013-05-14 17:55:58 -0700861 ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
862 return false;
863 }
864
Raj Kamalc0d34242015-03-17 20:53:14 +0530865 if(!mDpy && isSecondaryAnimating(ctx) &&
866 (isYuvPresent(ctx,HWC_DISPLAY_EXTERNAL) ||
867 isYuvPresent(ctx,HWC_DISPLAY_VIRTUAL)) ) {
868 ALOGD_IF(isDebug(),"%s: Display animation in progress",
869 __FUNCTION__);
870 return false;
871 }
872
Ramkumar Radhakrishnanf26fe9e2014-09-09 13:47:54 -0700873 // if secondary is configuring or Padding round, fall back to video only
874 // composition and release all assigned non VIG pipes from primary.
875 if(isSecondaryConfiguring(ctx)) {
876 ALOGD_IF( isDebug(),"%s: External Display connection is pending",
877 __FUNCTION__);
878 return false;
879 } else if(ctx->isPaddingRound) {
880 ALOGD_IF(isDebug(), "%s: padding round invoked for dpy %d",
881 __FUNCTION__,mDpy);
882 return false;
883 }
884
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -0500885 // No MDP composition for 3D
886 if(needs3DComposition(ctx, mDpy))
887 return false;
888
Tatenda Chipeperekwacb2a2432014-08-06 17:45:58 -0700889 // check for action safe flag and MDP scaling mode which requires scaling.
Ramkumar Radhakrishnan4af1ef02013-12-12 11:53:08 -0800890 if(ctx->dpyAttr[mDpy].mActionSafePresent
Tatenda Chipeperekwacb2a2432014-08-06 17:45:58 -0700891 || ctx->dpyAttr[mDpy].mMDPScalingMode) {
Ramkumar Radhakrishnan4af1ef02013-12-12 11:53:08 -0800892 ALOGD_IF(isDebug(), "%s: Scaling needed for this frame",__FUNCTION__);
893 return false;
894 }
895
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800896 for(int i = 0; i < numAppLayers; ++i) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800897 hwc_layer_1_t* layer = &list->hwLayers[i];
898 private_handle_t *hnd = (private_handle_t *)layer->handle;
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -0800899
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800900 if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700901 if(!canUseRotator(ctx, mDpy)) {
902 ALOGD_IF(isDebug(), "%s: Can't use rotator for dpy %d",
903 __FUNCTION__, mDpy);
Amara Venkata Mastan Manoj Kumar9d373c02013-08-20 14:30:09 -0700904 return false;
905 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800906 }
Prabhanjan Kandula9fb032a2013-06-18 17:37:22 +0530907
908 //For 8x26 with panel width>1k, if RGB layer needs HFLIP fail mdp comp
909 // may not need it if Gfx pre-rotation can handle all flips & rotations
Saurabh Shahcad57772014-12-01 14:19:51 -0800910 MDPVersion& mdpHw = MDPVersion::getInstance();
Sushil Chauhanfda00fc2014-03-20 11:08:41 -0700911 int transform = (layer->flags & HWC_COLOR_FILL) ? 0 : layer->transform;
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530912 if( mdpHw.is8x26() && (ctx->dpyAttr[mDpy].xres > 1024) &&
913 (transform & HWC_TRANSFORM_FLIP_H) && (!isYuvBuffer(hnd)))
914 return false;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800915 }
Saurabh Shahaa236822013-04-24 18:07:26 -0700916
Saurabh Shaha9da08f2013-07-03 13:27:53 -0700917 if(ctx->mAD->isDoable()) {
918 return false;
919 }
920
Saurabh Shahaa236822013-04-24 18:07:26 -0700921 //If all above hard conditions are met we can do full or partial MDP comp.
922 bool ret = false;
923 if(fullMDPComp(ctx, list)) {
924 ret = true;
Sushil Chauhandefd3522014-05-13 18:17:12 -0700925 } else if(fullMDPCompWithPTOR(ctx, list)) {
926 ret = true;
Jeykumar Sankaran24c199d2013-05-24 09:40:36 -0700927 } else if(partialMDPComp(ctx, list)) {
Saurabh Shahaa236822013-04-24 18:07:26 -0700928 ret = true;
929 }
Prabhanjan Kandula21918db2013-11-26 15:51:58 +0530930
Saurabh Shahaa236822013-04-24 18:07:26 -0700931 return ret;
932}
933
934bool MDPComp::fullMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -0700935
936 if(sSimulationFlags & MDPCOMP_AVOID_FULL_MDP)
937 return false;
938
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700939 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
940 for(int i = 0; i < numAppLayers; i++) {
941 hwc_layer_1_t* layer = &list->hwLayers[i];
Jeykumar Sankaran880da832014-04-18 10:22:35 -0700942 if(not mCurrentFrame.drop[i] and
943 not isSupportedForMDPComp(ctx, layer)) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700944 ALOGD_IF(isDebug(), "%s: Unsupported layer in list",__FUNCTION__);
945 return false;
946 }
947 }
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800948
Raj Kamalb5f0b4a2015-04-08 15:10:37 +0530949 if(!mDpy && isSecondaryConnected(ctx) &&
950 (qdutils::MDPVersion::getInstance().is8x16() ||
951 qdutils::MDPVersion::getInstance().is8x26() ||
952 qdutils::MDPVersion::getInstance().is8x39()) &&
953 isYuvPresent(ctx, HWC_DISPLAY_VIRTUAL)) {
954 ALOGD_IF(isDebug(), "%s: YUV layer present on secondary", __FUNCTION__);
955 return false;
956 }
957
Saurabh Shahaa236822013-04-24 18:07:26 -0700958 mCurrentFrame.fbCount = 0;
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700959 memcpy(&mCurrentFrame.isFBComposed, &mCurrentFrame.drop,
960 sizeof(mCurrentFrame.isFBComposed));
961 mCurrentFrame.mdpCount = mCurrentFrame.layerCount - mCurrentFrame.fbCount -
962 mCurrentFrame.dropCount;
Saurabh Shahaa236822013-04-24 18:07:26 -0700963
Raj Kamal389d6e32014-08-04 14:43:24 +0530964 if(sEnableYUVsplit){
Saurabh Shah3d4b8042013-12-10 15:19:17 -0800965 adjustForSourceSplit(ctx, list);
radhakrishnac9a67412013-09-25 17:40:42 +0530966 }
967
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800968 if(!postHeuristicsHandling(ctx, list)) {
969 ALOGD_IF(isDebug(), "post heuristic handling failed");
970 reset(ctx);
Saurabh Shah8c5c8522013-08-29 17:32:49 -0700971 return false;
972 }
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -0700973 ALOGD_IF(sSimulationFlags,"%s: FULL_MDP_COMP SUCCEEDED",
974 __FUNCTION__);
Saurabh Shahaa236822013-04-24 18:07:26 -0700975 return true;
976}
977
Sushil Chauhandefd3522014-05-13 18:17:12 -0700978/* Full MDP Composition with Peripheral Tiny Overlap Removal.
979 * MDP bandwidth limitations can be avoided, if the overlap region
980 * covered by the smallest layer at a higher z-order, gets composed
981 * by Copybit on a render buffer, which can be queued to MDP.
982 */
983bool MDPComp::fullMDPCompWithPTOR(hwc_context_t *ctx,
984 hwc_display_contents_1_t* list) {
985
986 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Arun Kumar K.R00b84792015-03-27 11:28:36 -0700987 // PTOR does not qualify when there are layers dropped, but if
988 // dropped layer is only a cursor, PTOR could qualify
989 const int numNonCursorLayers = numAppLayers - mCurrentFrame.dropCount;
Sushil Chauhandefd3522014-05-13 18:17:12 -0700990 const int stagesForMDP = min(sMaxPipesPerMixer,
991 ctx->mOverlay->availablePipes(mDpy, Overlay::MIXER_DEFAULT));
992
993 // Hard checks where we cannot use this mode
Sushil Chauhanbfc2de02014-07-24 11:52:58 -0700994 if (mDpy || !ctx->mCopyBit[mDpy]) {
Sushil Chauhandefd3522014-05-13 18:17:12 -0700995 ALOGD_IF(isDebug(), "%s: Feature not supported!", __FUNCTION__);
996 return false;
997 }
998
Arun Kumar K.R00b84792015-03-27 11:28:36 -0700999 // Frame level checks - consider PTOR in case of dropCount only if the cursor
1000 // layer is dropped, otherwise bail out of PTOR
Sushil Chauhandefd3522014-05-13 18:17:12 -07001001 if ((numAppLayers > stagesForMDP) || isSkipPresent(ctx, mDpy) ||
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001002 isYuvPresent(ctx, mDpy) || isSecurePresent(ctx, mDpy) ||
1003 (mCurrentFrame.dropCount - (int)isCursorPresent(ctx, mDpy))) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001004 ALOGD_IF(isDebug(), "%s: Frame not supported!", __FUNCTION__);
1005 return false;
1006 }
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001007 // MDP comp checks
1008 for(int i = 0; i < numAppLayers; i++) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001009 hwc_layer_1_t* layer = &list->hwLayers[i];
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001010 if(not isSupportedForMDPComp(ctx, layer)) {
1011 ALOGD_IF(isDebug(), "%s: Unsupported layer in list",__FUNCTION__);
1012 return false;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001013 }
1014 }
1015
Raj Kamalb5f0b4a2015-04-08 15:10:37 +05301016 if(!mDpy && isSecondaryConnected(ctx) &&
1017 (qdutils::MDPVersion::getInstance().is8x16() ||
1018 qdutils::MDPVersion::getInstance().is8x26() ||
1019 qdutils::MDPVersion::getInstance().is8x39()) &&
1020 isYuvPresent(ctx, HWC_DISPLAY_VIRTUAL)) {
1021 ALOGD_IF(isDebug(), "%s: YUV layer present on secondary", __FUNCTION__);
1022 return false;
1023 }
1024
Sushil Chauhandefd3522014-05-13 18:17:12 -07001025 /* We cannot use this composition mode, if:
1026 1. A below layer needs scaling.
1027 2. Overlap is not peripheral to display.
1028 3. Overlap or a below layer has 90 degree transform.
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001029 4. Overlap area > (1/3 * FrameBuffer) area, based on Perf inputs.
Sushil Chauhandefd3522014-05-13 18:17:12 -07001030 */
1031
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001032 int minLayerIndex[MAX_PTOR_LAYERS] = { -1, -1};
1033 hwc_rect_t overlapRect[MAX_PTOR_LAYERS];
1034 memset(overlapRect, 0, sizeof(overlapRect));
1035 int layerPixelCount, minPixelCount = 0;
1036 int numPTORLayersFound = 0;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001037 for (int i = numNonCursorLayers - 1; (i >= 0 &&
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001038 numPTORLayersFound < MAX_PTOR_LAYERS); i--) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001039 hwc_layer_1_t* layer = &list->hwLayers[i];
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001040 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
Sushil Chauhandefd3522014-05-13 18:17:12 -07001041 hwc_rect_t dispFrame = layer->displayFrame;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001042 layerPixelCount = (crop.right - crop.left) * (crop.bottom - crop.top);
1043 // PTOR layer should be peripheral and cannot have transform
1044 if (!isPeripheral(dispFrame, ctx->mViewFrame[mDpy]) ||
1045 has90Transform(layer)) {
1046 continue;
1047 }
1048 if((3 * (layerPixelCount + minPixelCount)) >
1049 ((int)ctx->dpyAttr[mDpy].xres * (int)ctx->dpyAttr[mDpy].yres)) {
1050 // Overlap area > (1/3 * FrameBuffer) area, based on Perf inputs.
1051 continue;
1052 }
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001053 bool found = false;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001054 for (int j = i-1; j >= 0; j--) {
1055 // Check if the layers below this layer qualifies for PTOR comp
1056 hwc_layer_1_t* layer = &list->hwLayers[j];
1057 hwc_rect_t disFrame = layer->displayFrame;
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001058 // Layer below PTOR is intersecting and has 90 degree transform or
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001059 // needs scaling cannot be supported.
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001060 if (isValidRect(getIntersection(dispFrame, disFrame))) {
1061 if (has90Transform(layer) || needsScaling(layer)) {
1062 found = false;
1063 break;
1064 }
1065 found = true;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001066 }
1067 }
1068 // Store the minLayer Index
1069 if(found) {
1070 minLayerIndex[numPTORLayersFound] = i;
1071 overlapRect[numPTORLayersFound] = list->hwLayers[i].displayFrame;
1072 minPixelCount += layerPixelCount;
1073 numPTORLayersFound++;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001074 }
1075 }
1076
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001077 // No overlap layers
1078 if (!numPTORLayersFound)
1079 return false;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001080
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001081 // Store the displayFrame and the sourceCrops of the layers
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001082 hwc_rect_t displayFrame[numNonCursorLayers];
1083 hwc_rect_t sourceCrop[numNonCursorLayers];
1084 for(int i = 0; i < numNonCursorLayers; i++) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001085 hwc_layer_1_t* layer = &list->hwLayers[i];
1086 displayFrame[i] = layer->displayFrame;
1087 sourceCrop[i] = integerizeSourceCrop(layer->sourceCropf);
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001088 }
Sushil Chauhandefd3522014-05-13 18:17:12 -07001089
Prabhanjan Kandula9889a202014-09-04 21:50:35 +05301090 /**
1091 * It's possible that 2 PTOR layers might have overlapping.
1092 * In such case, remove the intersection(again if peripheral)
1093 * from the lower PTOR layer to avoid overlapping.
1094 * If intersection is not on peripheral then compromise
1095 * by reducing number of PTOR layers.
1096 **/
1097 hwc_rect_t commonRect = getIntersection(overlapRect[0], overlapRect[1]);
1098 if(isValidRect(commonRect)) {
1099 overlapRect[1] = deductRect(overlapRect[1], commonRect);
1100 list->hwLayers[minLayerIndex[1]].displayFrame = overlapRect[1];
1101 }
1102
1103 ctx->mPtorInfo.count = numPTORLayersFound;
1104 for(int i = 0; i < MAX_PTOR_LAYERS; i++) {
1105 ctx->mPtorInfo.layerIndex[i] = minLayerIndex[i];
1106 }
1107
1108 if (!ctx->mCopyBit[mDpy]->prepareOverlap(ctx, list)) {
1109 // reset PTOR
1110 ctx->mPtorInfo.count = 0;
1111 if(isValidRect(commonRect)) {
1112 // If PTORs are intersecting restore displayframe of PTOR[1]
1113 // before returning, as we have modified it above.
1114 list->hwLayers[minLayerIndex[1]].displayFrame =
1115 displayFrame[minLayerIndex[1]];
1116 }
1117 return false;
1118 }
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001119 private_handle_t *renderBuf = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
1120 Whf layerWhf[numPTORLayersFound]; // To store w,h,f of PTOR layers
1121
Xu Yangcda012c2014-07-30 21:57:21 +08001122 // Store the blending mode, planeAlpha, and transform of PTOR layers
1123 int32_t blending[numPTORLayersFound];
1124 uint8_t planeAlpha[numPTORLayersFound];
1125 uint32_t transform[numPTORLayersFound];
1126
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001127 for(int j = 0; j < numPTORLayersFound; j++) {
1128 int index = ctx->mPtorInfo.layerIndex[j];
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001129
1130 // Update src crop of PTOR layer
1131 hwc_layer_1_t* layer = &list->hwLayers[index];
1132 layer->sourceCropf.left = (float)ctx->mPtorInfo.displayFrame[j].left;
1133 layer->sourceCropf.top = (float)ctx->mPtorInfo.displayFrame[j].top;
1134 layer->sourceCropf.right = (float)ctx->mPtorInfo.displayFrame[j].right;
1135 layer->sourceCropf.bottom =(float)ctx->mPtorInfo.displayFrame[j].bottom;
1136
1137 // Store & update w, h, format of PTOR layer
1138 private_handle_t *hnd = (private_handle_t *)layer->handle;
1139 Whf whf(hnd->width, hnd->height, hnd->format, hnd->size);
1140 layerWhf[j] = whf;
1141 hnd->width = renderBuf->width;
1142 hnd->height = renderBuf->height;
1143 hnd->format = renderBuf->format;
1144
Xu Yangcda012c2014-07-30 21:57:21 +08001145 // Store & update blending mode, planeAlpha and transform of PTOR layer
1146 blending[j] = layer->blending;
1147 planeAlpha[j] = layer->planeAlpha;
1148 transform[j] = layer->transform;
1149 layer->blending = HWC_BLENDING_NONE;
1150 layer->planeAlpha = 0xFF;
1151 layer->transform = 0;
1152
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001153 // Remove overlap from crop & displayFrame of below layers
1154 for (int i = 0; i < index && index !=-1; i++) {
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001155 layer = &list->hwLayers[i];
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001156 if(!isValidRect(getIntersection(layer->displayFrame,
1157 overlapRect[j]))) {
1158 continue;
1159 }
1160 // Update layer attributes
1161 hwc_rect_t srcCrop = integerizeSourceCrop(layer->sourceCropf);
1162 hwc_rect_t destRect = deductRect(layer->displayFrame,
Dileep Kumar Reddi72058b82014-11-11 16:03:03 +05301163 getIntersection(layer->displayFrame, overlapRect[j]));
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001164 qhwc::calculate_crop_rects(srcCrop, layer->displayFrame, destRect,
1165 layer->transform);
1166 layer->sourceCropf.left = (float)srcCrop.left;
1167 layer->sourceCropf.top = (float)srcCrop.top;
1168 layer->sourceCropf.right = (float)srcCrop.right;
1169 layer->sourceCropf.bottom = (float)srcCrop.bottom;
1170 }
Sushil Chauhandefd3522014-05-13 18:17:12 -07001171 }
1172
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001173 mCurrentFrame.mdpCount = numNonCursorLayers;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001174 mCurrentFrame.fbCount = 0;
1175 mCurrentFrame.fbZ = -1;
1176
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001177 for (int j = 0; j < numNonCursorLayers; j++) {
Dileep Kumar Reddi72058b82014-11-11 16:03:03 +05301178 if(isValidRect(list->hwLayers[j].displayFrame)) {
1179 mCurrentFrame.isFBComposed[j] = false;
1180 } else {
1181 mCurrentFrame.mdpCount--;
1182 mCurrentFrame.drop[j] = true;
1183 }
1184 }
Sushil Chauhandefd3522014-05-13 18:17:12 -07001185
1186 bool result = postHeuristicsHandling(ctx, list);
1187
1188 // Restore layer attributes
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001189 for(int i = 0; i < numNonCursorLayers; i++) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001190 hwc_layer_1_t* layer = &list->hwLayers[i];
1191 layer->displayFrame = displayFrame[i];
1192 layer->sourceCropf.left = (float)sourceCrop[i].left;
1193 layer->sourceCropf.top = (float)sourceCrop[i].top;
1194 layer->sourceCropf.right = (float)sourceCrop[i].right;
1195 layer->sourceCropf.bottom = (float)sourceCrop[i].bottom;
1196 }
1197
Xu Yangcda012c2014-07-30 21:57:21 +08001198 // Restore w,h,f, blending attributes, and transform of PTOR layers
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001199 for (int i = 0; i < numPTORLayersFound; i++) {
1200 int idx = ctx->mPtorInfo.layerIndex[i];
Xu Yangcda012c2014-07-30 21:57:21 +08001201 hwc_layer_1_t* layer = &list->hwLayers[idx];
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001202 private_handle_t *hnd = (private_handle_t *)list->hwLayers[idx].handle;
1203 hnd->width = layerWhf[i].w;
1204 hnd->height = layerWhf[i].h;
1205 hnd->format = layerWhf[i].format;
Xu Yangcda012c2014-07-30 21:57:21 +08001206 layer->blending = blending[i];
1207 layer->planeAlpha = planeAlpha[i];
1208 layer->transform = transform[i];
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001209 }
1210
Sushil Chauhandefd3522014-05-13 18:17:12 -07001211 if (!result) {
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001212 // reset PTOR
1213 ctx->mPtorInfo.count = 0;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001214 reset(ctx);
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001215 } else {
1216 ALOGD_IF(isDebug(), "%s: PTOR Indexes: %d and %d", __FUNCTION__,
1217 ctx->mPtorInfo.layerIndex[0], ctx->mPtorInfo.layerIndex[1]);
Sushil Chauhandefd3522014-05-13 18:17:12 -07001218 }
1219
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001220 ALOGD_IF(isDebug(), "%s: Postheuristics %s!", __FUNCTION__,
1221 (result ? "successful" : "failed"));
Sushil Chauhandefd3522014-05-13 18:17:12 -07001222 return result;
1223}
1224
Saurabh Shahaa236822013-04-24 18:07:26 -07001225bool MDPComp::partialMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list)
1226{
radhakrishnac3198ff2015-03-10 17:10:02 +05301227 if(!sEnableMixedMode || !isAlphaPresentinFB(ctx, mDpy)) {
1228 //Mixed mode is disabled/can't be used. No need to even try caching.
Jeykumar Sankaran24c199d2013-05-24 09:40:36 -07001229 return false;
1230 }
1231
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001232 bool ret = false;
Raj Kamal1179d9c2014-10-28 15:31:35 +05301233 if(isSkipPresent(ctx, mDpy) or list->flags & HWC_GEOMETRY_CHANGED) {
1234 //Try load based first
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001235 ret = loadBasedComp(ctx, list) or
Saurabh Shahf2de00f2013-12-11 17:52:53 -08001236 cacheBasedComp(ctx, list);
1237 } else {
1238 ret = cacheBasedComp(ctx, list) or
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001239 loadBasedComp(ctx, list);
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001240 }
1241
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001242 return ret;
1243}
1244
1245bool MDPComp::cacheBasedComp(hwc_context_t *ctx,
1246 hwc_display_contents_1_t* list) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001247 if(sSimulationFlags & MDPCOMP_AVOID_CACHE_MDP)
1248 return false;
1249
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001250 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shahaa236822013-04-24 18:07:26 -07001251 mCurrentFrame.reset(numAppLayers);
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001252 updateLayerCache(ctx, list, mCurrentFrame);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001253
1254 //If an MDP marked layer is unsupported cannot do partial MDP Comp
1255 for(int i = 0; i < numAppLayers; i++) {
1256 if(!mCurrentFrame.isFBComposed[i]) {
1257 hwc_layer_1_t* layer = &list->hwLayers[i];
1258 if(not isSupportedForMDPComp(ctx, layer)) {
1259 ALOGD_IF(isDebug(), "%s: Unsupported layer in list",
1260 __FUNCTION__);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001261 reset(ctx);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001262 return false;
1263 }
1264 }
1265 }
1266
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001267 updateYUV(ctx, list, false /*secure only*/, mCurrentFrame);
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001268 /* mark secure RGB layers for MDP comp */
1269 updateSecureRGB(ctx, list);
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301270 bool ret = markLayersForCaching(ctx, list); //sets up fbZ also
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001271 if(!ret) {
1272 ALOGD_IF(isDebug(),"%s: batching failed, dpy %d",__FUNCTION__, mDpy);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001273 reset(ctx);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001274 return false;
1275 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001276
1277 int mdpCount = mCurrentFrame.mdpCount;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001278
Raj Kamal389d6e32014-08-04 14:43:24 +05301279 if(sEnableYUVsplit){
Saurabh Shah3d4b8042013-12-10 15:19:17 -08001280 adjustForSourceSplit(ctx, list);
radhakrishnac9a67412013-09-25 17:40:42 +05301281 }
1282
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001283 if(!postHeuristicsHandling(ctx, list)) {
1284 ALOGD_IF(isDebug(), "post heuristic handling failed");
1285 reset(ctx);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07001286 return false;
1287 }
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001288 ALOGD_IF(sSimulationFlags,"%s: CACHE_MDP_COMP SUCCEEDED",
1289 __FUNCTION__);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07001290
Saurabh Shahaa236822013-04-24 18:07:26 -07001291 return true;
1292}
1293
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001294bool MDPComp::loadBasedComp(hwc_context_t *ctx,
Saurabh Shahb772ae32013-11-18 15:40:02 -08001295 hwc_display_contents_1_t* list) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001296 if(sSimulationFlags & MDPCOMP_AVOID_LOAD_MDP)
1297 return false;
1298
Arun Kumar K.R2aa44c62014-01-21 23:08:28 -08001299 if(not isLoadBasedCompDoable(ctx)) {
Saurabh Shahf2de00f2013-12-11 17:52:53 -08001300 return false;
1301 }
1302
Saurabh Shahb772ae32013-11-18 15:40:02 -08001303 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001304 const int numNonDroppedLayers = numAppLayers - mCurrentFrame.dropCount;
1305 const int stagesForMDP = min(sMaxPipesPerMixer,
1306 ctx->mOverlay->availablePipes(mDpy, Overlay::MIXER_DEFAULT));
Saurabh Shahf2de00f2013-12-11 17:52:53 -08001307
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001308 int mdpBatchSize = stagesForMDP - 1; //1 stage for FB
1309 int fbBatchSize = numNonDroppedLayers - mdpBatchSize;
1310 int lastMDPSupportedIndex = numAppLayers;
1311 int dropCount = 0;
Saurabh Shahb772ae32013-11-18 15:40:02 -08001312
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001313 //Find the minimum MDP batch size
1314 for(int i = 0; i < numAppLayers;i++) {
1315 if(mCurrentFrame.drop[i]) {
1316 dropCount++;
Jeykumar Sankaran846e2792014-01-23 21:59:58 -08001317 continue;
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001318 }
1319 hwc_layer_1_t* layer = &list->hwLayers[i];
1320 if(not isSupportedForMDPComp(ctx, layer)) {
1321 lastMDPSupportedIndex = i;
1322 mdpBatchSize = min(i - dropCount, stagesForMDP - 1);
1323 fbBatchSize = numNonDroppedLayers - mdpBatchSize;
Jeykumar Sankaran846e2792014-01-23 21:59:58 -08001324 break;
Saurabh Shahb772ae32013-11-18 15:40:02 -08001325 }
Saurabh Shahb772ae32013-11-18 15:40:02 -08001326 }
1327
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001328 ALOGD_IF(isDebug(), "%s:Before optimizing fbBatch, mdpbatch %d, fbbatch %d "
1329 "dropped %d", __FUNCTION__, mdpBatchSize, fbBatchSize,
1330 mCurrentFrame.dropCount);
1331
1332 //Start at a point where the fb batch should at least have 2 layers, for
1333 //this mode to be justified.
1334 while(fbBatchSize < 2) {
1335 ++fbBatchSize;
1336 --mdpBatchSize;
Jeykumar Sankaran846e2792014-01-23 21:59:58 -08001337 }
Saurabh Shahb772ae32013-11-18 15:40:02 -08001338
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001339 //If there are no layers for MDP, this mode doesnt make sense.
1340 if(mdpBatchSize < 1) {
1341 ALOGD_IF(isDebug(), "%s: No MDP layers after optimizing for fbBatch",
1342 __FUNCTION__);
Saurabh Shahb772ae32013-11-18 15:40:02 -08001343 return false;
1344 }
1345
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001346 mCurrentFrame.reset(numAppLayers);
1347
1348 //Try with successively smaller mdp batch sizes until we succeed or reach 1
1349 while(mdpBatchSize > 0) {
1350 //Mark layers for MDP comp
1351 int mdpBatchLeft = mdpBatchSize;
1352 for(int i = 0; i < lastMDPSupportedIndex and mdpBatchLeft; i++) {
1353 if(mCurrentFrame.drop[i]) {
1354 continue;
1355 }
1356 mCurrentFrame.isFBComposed[i] = false;
1357 --mdpBatchLeft;
1358 }
1359
1360 mCurrentFrame.fbZ = mdpBatchSize;
1361 mCurrentFrame.fbCount = fbBatchSize;
1362 mCurrentFrame.mdpCount = mdpBatchSize;
1363
1364 ALOGD_IF(isDebug(), "%s:Trying with: mdpbatch %d fbbatch %d dropped %d",
1365 __FUNCTION__, mdpBatchSize, fbBatchSize,
1366 mCurrentFrame.dropCount);
1367
1368 if(postHeuristicsHandling(ctx, list)) {
1369 ALOGD_IF(isDebug(), "%s: Postheuristics handling succeeded",
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001370 __FUNCTION__);
1371 ALOGD_IF(sSimulationFlags,"%s: LOAD_MDP_COMP SUCCEEDED",
1372 __FUNCTION__);
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001373 return true;
1374 }
1375
1376 reset(ctx);
1377 --mdpBatchSize;
1378 ++fbBatchSize;
1379 }
1380
1381 return false;
Saurabh Shahb772ae32013-11-18 15:40:02 -08001382}
1383
Arun Kumar K.R2aa44c62014-01-21 23:08:28 -08001384bool MDPComp::isLoadBasedCompDoable(hwc_context_t *ctx) {
Prabhanjan Kandula3dbbd882013-12-11 14:43:46 +05301385 if(mDpy or isSecurePresent(ctx, mDpy) or
1386 isYuvPresent(ctx, mDpy)) {
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001387 return false;
1388 }
1389 return true;
1390}
1391
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001392bool MDPComp::canPartialUpdate(hwc_context_t *ctx,
1393 hwc_display_contents_1_t* list){
1394 if(!qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() ||
1395 isSkipPresent(ctx, mDpy) || (list->flags & HWC_GEOMETRY_CHANGED) ||
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001396 isCursorPresent(ctx, mDpy) || !sIsPartialUpdateActive || mDpy) {
1397 // On Async position update, the ROI becomes invalid, hence disable PU
1398 // when cursor is present
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001399 return false;
1400 }
Jeykumar Sankaran4dd10ab2014-07-02 12:23:09 -07001401 if(ctx->listStats[mDpy].secureUI)
1402 return false;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001403 return true;
1404}
1405
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001406bool MDPComp::tryVideoOnly(hwc_context_t *ctx,
1407 hwc_display_contents_1_t* list) {
1408 const bool secureOnly = true;
1409 return videoOnlyComp(ctx, list, not secureOnly) or
1410 videoOnlyComp(ctx, list, secureOnly);
1411}
1412
1413bool MDPComp::videoOnlyComp(hwc_context_t *ctx,
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001414 hwc_display_contents_1_t* list, bool secureOnly) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001415 if(sSimulationFlags & MDPCOMP_AVOID_VIDEO_ONLY)
1416 return false;
Praveena Pachipulusu47346c22014-12-04 11:06:41 +05301417
Saurabh Shahaa236822013-04-24 18:07:26 -07001418 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Praveena Pachipulusu47346c22014-12-04 11:06:41 +05301419 if(!isSecurePresent(ctx, mDpy)) {
1420 /* Bail out if we are processing only secured video layers
1421 * and we dont have any */
1422 if(secureOnly) {
1423 ALOGD_IF(isDebug(),"%s: No Secure Video Layers", __FUNCTION__);
1424 return false;
1425 }
1426 /* No Idle fall back for secure video layers and if there is only
1427 * single layer being composed. */
1428 if(sIdleFallBack && (ctx->listStats[mDpy].numAppLayers > 1)) {
1429 ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
1430 return false;
1431 }
1432 }
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001433
Saurabh Shahaa236822013-04-24 18:07:26 -07001434 mCurrentFrame.reset(numAppLayers);
Jeykumar Sankaraneb3a5e22014-04-08 16:07:55 -07001435 mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001436 updateYUV(ctx, list, secureOnly, mCurrentFrame);
Saurabh Shah4fdde762013-04-30 18:47:33 -07001437 int mdpCount = mCurrentFrame.mdpCount;
Saurabh Shahaa236822013-04-24 18:07:26 -07001438
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001439 if(!isYuvPresent(ctx, mDpy) or (mdpCount == 0)) {
1440 reset(ctx);
Saurabh Shahaa236822013-04-24 18:07:26 -07001441 return false;
1442 }
1443
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001444 if(mCurrentFrame.fbCount)
1445 mCurrentFrame.fbZ = mCurrentFrame.mdpCount;
Saurabh Shah4fdde762013-04-30 18:47:33 -07001446
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05001447 if(sEnableYUVsplit || needs3DComposition(ctx, mDpy)){
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001448 adjustForSourceSplit(ctx, list);
1449 }
1450
1451 if(!postHeuristicsHandling(ctx, list)) {
1452 ALOGD_IF(isDebug(), "post heuristic handling failed");
Justin Philip37ab9a82015-01-06 11:55:12 +05301453 if(errno == ENOBUFS) {
1454 ALOGD_IF(isDebug(), "SMP Allocation failed");
1455 //On SMP allocation failure in video only comp add padding round
1456 ctx->isPaddingRound = true;
1457 }
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001458 reset(ctx);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07001459 return false;
1460 }
1461
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001462 ALOGD_IF(sSimulationFlags,"%s: VIDEO_ONLY_COMP SUCCEEDED",
1463 __FUNCTION__);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001464 return true;
1465}
1466
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001467/* if tryFullFrame fails, try to push all video and secure RGB layers to MDP */
1468bool MDPComp::tryMDPOnlyLayers(hwc_context_t *ctx,
1469 hwc_display_contents_1_t* list) {
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001470 // Fall back to video only composition, if AIV video mode is enabled
1471 if(ctx->listStats[mDpy].mAIVVideoMode) {
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07001472 ALOGD_IF(isDebug(), "%s: AIV Video Mode enabled dpy %d",
1473 __FUNCTION__, mDpy);
1474 return false;
1475 }
1476
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05001477 // No MDP composition for 3D
1478 if(needs3DComposition(ctx,mDpy))
1479 return false;
1480
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001481 const bool secureOnly = true;
1482 return mdpOnlyLayersComp(ctx, list, not secureOnly) or
1483 mdpOnlyLayersComp(ctx, list, secureOnly);
1484
1485}
1486
1487bool MDPComp::mdpOnlyLayersComp(hwc_context_t *ctx,
1488 hwc_display_contents_1_t* list, bool secureOnly) {
1489
1490 if(sSimulationFlags & MDPCOMP_AVOID_MDP_ONLY_LAYERS)
1491 return false;
1492
Praveena Pachipulusu47346c22014-12-04 11:06:41 +05301493 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
1494 if(!isSecurePresent(ctx, mDpy) && !ctx->listStats[mDpy].secureUI) {
1495 /* Bail out if we are processing only secured video/ui layers
1496 * and we dont have any */
1497 if(secureOnly) {
1498 ALOGD_IF(isDebug(), "%s: No secure video/ui layers");
1499 return false;
1500 }
1501 /* No Idle fall back for secure video/ui layers and if there is only
1502 * single layer being composed. */
1503 if(sIdleFallBack && (ctx->listStats[mDpy].numAppLayers > 1)) {
1504 ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
1505 return false;
1506 }
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001507 }
1508
Tatenda Chipeperekwa95675a72014-12-15 17:06:43 -08001509 /* Bail out if we dont have any secure RGB layers */
1510 if (!ctx->listStats[mDpy].secureRGBCount) {
1511 reset(ctx);
1512 return false;
1513 }
1514
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001515 mCurrentFrame.reset(numAppLayers);
1516 mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
1517
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001518 updateYUV(ctx, list, secureOnly, mCurrentFrame);
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001519 /* mark secure RGB layers for MDP comp */
1520 updateSecureRGB(ctx, list);
1521
1522 if(mCurrentFrame.mdpCount == 0) {
1523 reset(ctx);
1524 return false;
1525 }
1526
1527 /* find the maximum batch of layers to be marked for framebuffer */
1528 bool ret = markLayersForCaching(ctx, list); //sets up fbZ also
1529 if(!ret) {
1530 ALOGD_IF(isDebug(),"%s: batching failed, dpy %d",__FUNCTION__, mDpy);
1531 reset(ctx);
1532 return false;
1533 }
1534
1535 if(sEnableYUVsplit){
1536 adjustForSourceSplit(ctx, list);
1537 }
1538
1539 if(!postHeuristicsHandling(ctx, list)) {
1540 ALOGD_IF(isDebug(), "post heuristic handling failed");
1541 reset(ctx);
1542 return false;
1543 }
1544
1545 ALOGD_IF(sSimulationFlags,"%s: MDP_ONLY_LAYERS_COMP SUCCEEDED",
1546 __FUNCTION__);
1547 return true;
1548}
1549
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001550/* Checks for conditions where YUV layers cannot be bypassed */
1551bool MDPComp::isYUVDoable(hwc_context_t* ctx, hwc_layer_1_t* layer) {
Ramkumar Radhakrishnana70981a2013-08-28 11:33:53 -07001552 if(isSkipLayer(layer)) {
Saurabh Shahe2474082013-05-15 16:32:13 -07001553 ALOGD_IF(isDebug(), "%s: Video marked SKIP dpy %d", __FUNCTION__, mDpy);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001554 return false;
1555 }
1556
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08001557 if(has90Transform(layer) && !canUseRotator(ctx, mDpy)) {
Amara Venkata Mastan Manoj Kumar9d373c02013-08-20 14:30:09 -07001558 ALOGD_IF(isDebug(), "%s: no free DMA pipe",__FUNCTION__);
1559 return false;
1560 }
1561
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001562 if(isSecuring(ctx, layer)) {
1563 ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
1564 return false;
1565 }
1566
Saurabh Shah4fdde762013-04-30 18:47:33 -07001567 if(!isValidDimension(ctx, layer)) {
1568 ALOGD_IF(isDebug(), "%s: Buffer is of invalid width",
1569 __FUNCTION__);
1570 return false;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001571 }
Saurabh Shah4fdde762013-04-30 18:47:33 -07001572
Naseer Ahmeddc61a972013-07-10 17:50:54 -04001573 if(layer->planeAlpha < 0xFF) {
1574 ALOGD_IF(isDebug(), "%s: Cannot handle YUV layer with plane alpha\
1575 in video only mode",
1576 __FUNCTION__);
1577 return false;
1578 }
1579
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001580 return true;
1581}
1582
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001583/* Checks for conditions where Secure RGB layers cannot be bypassed */
1584bool MDPComp::isSecureRGBDoable(hwc_context_t* ctx, hwc_layer_1_t* layer) {
1585 if(isSkipLayer(layer)) {
1586 ALOGD_IF(isDebug(), "%s: Secure RGB layer marked SKIP dpy %d",
1587 __FUNCTION__, mDpy);
1588 return false;
1589 }
1590
1591 if(isSecuring(ctx, layer)) {
1592 ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
1593 return false;
1594 }
1595
1596 if(not isSupportedForMDPComp(ctx, layer)) {
1597 ALOGD_IF(isDebug(), "%s: Unsupported secure RGB layer",
1598 __FUNCTION__);
1599 return false;
1600 }
1601 return true;
1602}
1603
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301604/* starts at fromIndex and check for each layer to find
1605 * if it it has overlapping with any Updating layer above it in zorder
1606 * till the end of the batch. returns true if it finds any intersection */
1607bool MDPComp::canPushBatchToTop(const hwc_display_contents_1_t* list,
1608 int fromIndex, int toIndex) {
1609 for(int i = fromIndex; i < toIndex; i++) {
1610 if(mCurrentFrame.isFBComposed[i] && !mCurrentFrame.drop[i]) {
1611 if(intersectingUpdatingLayers(list, i+1, toIndex, i)) {
1612 return false;
1613 }
1614 }
1615 }
1616 return true;
1617}
1618
1619/* Checks if given layer at targetLayerIndex has any
1620 * intersection with all the updating layers in beween
1621 * fromIndex and toIndex. Returns true if it finds intersectiion */
1622bool MDPComp::intersectingUpdatingLayers(const hwc_display_contents_1_t* list,
1623 int fromIndex, int toIndex, int targetLayerIndex) {
1624 for(int i = fromIndex; i <= toIndex; i++) {
1625 if(!mCurrentFrame.isFBComposed[i]) {
1626 if(areLayersIntersecting(&list->hwLayers[i],
1627 &list->hwLayers[targetLayerIndex])) {
1628 return true;
1629 }
1630 }
1631 }
1632 return false;
1633}
1634
1635int MDPComp::getBatch(hwc_display_contents_1_t* list,
1636 int& maxBatchStart, int& maxBatchEnd,
1637 int& maxBatchCount) {
1638 int i = 0;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301639 int fbZOrder =-1;
Jeykumar Sankaran9502f352014-01-20 12:25:32 -08001640 int droppedLayerCt = 0;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301641 while (i < mCurrentFrame.layerCount) {
1642 int batchCount = 0;
1643 int batchStart = i;
1644 int batchEnd = i;
Jeykumar Sankaran9502f352014-01-20 12:25:32 -08001645 /* Adjust batch Z order with the dropped layers so far */
1646 int fbZ = batchStart - droppedLayerCt;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301647 int firstZReverseIndex = -1;
Prabhanjan Kandula0ed2cc92013-12-06 12:39:04 +05301648 int updatingLayersAbove = 0;//Updating layer count in middle of batch
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301649 while(i < mCurrentFrame.layerCount) {
1650 if(!mCurrentFrame.isFBComposed[i]) {
1651 if(!batchCount) {
1652 i++;
1653 break;
1654 }
1655 updatingLayersAbove++;
1656 i++;
1657 continue;
1658 } else {
1659 if(mCurrentFrame.drop[i]) {
1660 i++;
Jeykumar Sankaran9502f352014-01-20 12:25:32 -08001661 droppedLayerCt++;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301662 continue;
1663 } else if(updatingLayersAbove <= 0) {
1664 batchCount++;
1665 batchEnd = i;
1666 i++;
1667 continue;
1668 } else { //Layer is FBComposed, not a drop & updatingLayer > 0
1669
1670 // We have a valid updating layer already. If layer-i not
1671 // have overlapping with all updating layers in between
1672 // batch-start and i, then we can add layer i to batch.
1673 if(!intersectingUpdatingLayers(list, batchStart, i-1, i)) {
1674 batchCount++;
1675 batchEnd = i;
1676 i++;
1677 continue;
1678 } else if(canPushBatchToTop(list, batchStart, i)) {
1679 //If All the non-updating layers with in this batch
1680 //does not have intersection with the updating layers
1681 //above in z-order, then we can safely move the batch to
1682 //higher z-order. Increment fbZ as it is moving up.
1683 if( firstZReverseIndex < 0) {
1684 firstZReverseIndex = i;
1685 }
1686 batchCount++;
1687 batchEnd = i;
1688 fbZ += updatingLayersAbove;
1689 i++;
1690 updatingLayersAbove = 0;
1691 continue;
1692 } else {
1693 //both failed.start the loop again from here.
1694 if(firstZReverseIndex >= 0) {
1695 i = firstZReverseIndex;
1696 }
1697 break;
1698 }
1699 }
1700 }
1701 }
1702 if(batchCount > maxBatchCount) {
1703 maxBatchCount = batchCount;
1704 maxBatchStart = batchStart;
1705 maxBatchEnd = batchEnd;
1706 fbZOrder = fbZ;
1707 }
1708 }
1709 return fbZOrder;
1710}
1711
1712bool MDPComp::markLayersForCaching(hwc_context_t* ctx,
1713 hwc_display_contents_1_t* list) {
1714 /* Idea is to keep as many non-updating(cached) layers in FB and
1715 * send rest of them through MDP. This is done in 2 steps.
1716 * 1. Find the maximum contiguous batch of non-updating layers.
1717 * 2. See if we can improve this batch size for caching by adding
1718 * opaque layers around the batch, if they don't have
1719 * any overlapping with the updating layers in between.
1720 * NEVER mark an updating layer for caching.
1721 * But cached ones can be marked for MDP */
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001722
1723 int maxBatchStart = -1;
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001724 int maxBatchEnd = -1;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001725 int maxBatchCount = 0;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301726 int fbZ = -1;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001727
Saurabh Shahd53bc5f2014-02-05 10:17:43 -08001728 /* Nothing is cached. No batching needed */
1729 if(mCurrentFrame.fbCount == 0) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001730 return true;
Saurabh Shahaa236822013-04-24 18:07:26 -07001731 }
Saurabh Shahd53bc5f2014-02-05 10:17:43 -08001732
1733 /* No MDP comp layers, try to use other comp modes */
1734 if(mCurrentFrame.mdpCount == 0) {
1735 return false;
Saurabh Shahaa236822013-04-24 18:07:26 -07001736 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001737
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301738 fbZ = getBatch(list, maxBatchStart, maxBatchEnd, maxBatchCount);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001739
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301740 /* reset rest of the layers lying inside ROI for MDP comp */
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001741 for(int i = 0; i < mCurrentFrame.layerCount; i++) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001742 hwc_layer_1_t* layer = &list->hwLayers[i];
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001743 if((i < maxBatchStart || i > maxBatchEnd) &&
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301744 mCurrentFrame.isFBComposed[i]){
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001745 if(!mCurrentFrame.drop[i]){
1746 //If an unsupported layer is being attempted to
1747 //be pulled out we should fail
1748 if(not isSupportedForMDPComp(ctx, layer)) {
1749 return false;
1750 }
1751 mCurrentFrame.isFBComposed[i] = false;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001752 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001753 }
1754 }
1755
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301756 // update the frame data
1757 mCurrentFrame.fbZ = fbZ;
1758 mCurrentFrame.fbCount = maxBatchCount;
Saurabh Shahaa236822013-04-24 18:07:26 -07001759 mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001760 mCurrentFrame.fbCount - mCurrentFrame.dropCount;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001761
1762 ALOGD_IF(isDebug(),"%s: cached count: %d",__FUNCTION__,
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301763 mCurrentFrame.fbCount);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001764
1765 return true;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001766}
Saurabh Shah85234ec2013-04-12 17:09:00 -07001767
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001768void MDPComp::updateLayerCache(hwc_context_t* ctx,
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001769 hwc_display_contents_1_t* list, FrameInfo& frame) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001770 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001771 int fbCount = 0;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001772
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001773 for(int i = 0; i < numAppLayers; i++) {
1774 if (mCachedFrame.hnd[i] == list->hwLayers[i].handle) {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001775 if(!frame.drop[i])
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001776 fbCount++;
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001777 frame.isFBComposed[i] = true;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001778 } else {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001779 frame.isFBComposed[i] = false;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001780 }
1781 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001782
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001783 frame.fbCount = fbCount;
1784 frame.mdpCount = frame.layerCount - frame.fbCount
1785 - frame.dropCount;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001786
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001787 ALOGD_IF(isDebug(),"%s: MDP count: %d FB count %d drop count: %d",
1788 __FUNCTION__, frame.mdpCount, frame.fbCount, frame.dropCount);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001789}
1790
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001791// drop other non-AIV layers from external display list.
1792void MDPComp::dropNonAIVLayers(hwc_context_t* ctx,
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07001793 hwc_display_contents_1_t* list) {
1794 for (size_t i = 0; i < (size_t)ctx->listStats[mDpy].numAppLayers; i++) {
1795 hwc_layer_1_t * layer = &list->hwLayers[i];
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001796 if(!(isAIVVideoLayer(layer) || isAIVCCLayer(layer))) {
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07001797 mCurrentFrame.dropCount++;
1798 mCurrentFrame.drop[i] = true;
1799 }
1800 }
1801 mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
1802 mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
1803 mCurrentFrame.fbCount - mCurrentFrame.dropCount;
1804 ALOGD_IF(isDebug(),"%s: fb count: %d mdp count %d drop count %d",
1805 __FUNCTION__, mCurrentFrame.fbCount, mCurrentFrame.mdpCount,
1806 mCurrentFrame.dropCount);
1807}
1808
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001809void MDPComp::updateYUV(hwc_context_t* ctx, hwc_display_contents_1_t* list,
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001810 bool secureOnly, FrameInfo& frame) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001811 int nYuvCount = ctx->listStats[mDpy].yuvCount;
radhakrishna03640472015-05-25 17:34:13 +05301812 int nVGpipes = qdutils::MDPVersion::getInstance().getVGPipes();
1813
1814 /* If number of YUV layers in the layer list is more than the number of
1815 VG pipes available in the target (non-split), try to program maximum
1816 possible number of YUV layers to MDP, instead of falling back to GPU
1817 completely.*/
1818 nYuvCount = (nYuvCount > nVGpipes) ? nVGpipes : nYuvCount;
1819
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001820 for(int index = 0;index < nYuvCount; index++){
1821 int nYuvIndex = ctx->listStats[mDpy].yuvIndices[index];
1822 hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
1823
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001824 if(mCurrentFrame.drop[nYuvIndex]) {
1825 continue;
1826 }
1827
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001828 if(!isYUVDoable(ctx, layer)) {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001829 if(!frame.isFBComposed[nYuvIndex]) {
1830 frame.isFBComposed[nYuvIndex] = true;
1831 frame.fbCount++;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001832 }
1833 } else {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001834 if(frame.isFBComposed[nYuvIndex]) {
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001835 private_handle_t *hnd = (private_handle_t *)layer->handle;
1836 if(!secureOnly || isSecureBuffer(hnd)) {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001837 frame.isFBComposed[nYuvIndex] = false;
1838 frame.fbCount--;
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001839 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001840 }
1841 }
1842 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001843
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001844 frame.mdpCount = frame.layerCount - frame.fbCount - frame.dropCount;
1845 ALOGD_IF(isDebug(),"%s: fb count: %d",__FUNCTION__, frame.fbCount);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001846}
1847
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001848void MDPComp::updateSecureRGB(hwc_context_t* ctx,
1849 hwc_display_contents_1_t* list) {
1850 int nSecureRGBCount = ctx->listStats[mDpy].secureRGBCount;
1851 for(int index = 0;index < nSecureRGBCount; index++){
1852 int nSecureRGBIndex = ctx->listStats[mDpy].secureRGBIndices[index];
1853 hwc_layer_1_t* layer = &list->hwLayers[nSecureRGBIndex];
1854
1855 if(!isSecureRGBDoable(ctx, layer)) {
1856 if(!mCurrentFrame.isFBComposed[nSecureRGBIndex]) {
1857 mCurrentFrame.isFBComposed[nSecureRGBIndex] = true;
1858 mCurrentFrame.fbCount++;
1859 }
1860 } else {
1861 if(mCurrentFrame.isFBComposed[nSecureRGBIndex]) {
1862 mCurrentFrame.isFBComposed[nSecureRGBIndex] = false;
1863 mCurrentFrame.fbCount--;
1864 }
1865 }
1866 }
1867
1868 mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
1869 mCurrentFrame.fbCount - mCurrentFrame.dropCount;
1870 ALOGD_IF(isDebug(),"%s: fb count: %d",__FUNCTION__,
1871 mCurrentFrame.fbCount);
1872}
1873
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001874hwc_rect_t MDPComp::getUpdatingFBRect(hwc_context_t *ctx,
1875 hwc_display_contents_1_t* list){
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001876 hwc_rect_t fbRect = (struct hwc_rect){0, 0, 0, 0};
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001877
1878 /* Update only the region of FB needed for composition */
1879 for(int i = 0; i < mCurrentFrame.layerCount; i++ ) {
1880 if(mCurrentFrame.isFBComposed[i] && !mCurrentFrame.drop[i]) {
1881 hwc_layer_1_t* layer = &list->hwLayers[i];
1882 hwc_rect_t dst = layer->displayFrame;
1883 fbRect = getUnion(fbRect, dst);
1884 }
1885 }
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08001886 trimAgainstROI(ctx, fbRect, fbRect);
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001887 return fbRect;
1888}
1889
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001890bool MDPComp::postHeuristicsHandling(hwc_context_t *ctx,
1891 hwc_display_contents_1_t* list) {
1892
1893 //Capability checks
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08001894 if(!resourceCheck(ctx, list)) {
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001895 ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
1896 return false;
1897 }
1898
1899 //Limitations checks
1900 if(!hwLimitationsCheck(ctx, list)) {
1901 ALOGD_IF(isDebug(), "%s: HW limitations",__FUNCTION__);
1902 return false;
1903 }
1904
Saurabh Shah3d4b8042013-12-10 15:19:17 -08001905 //Configure framebuffer first if applicable
1906 if(mCurrentFrame.fbZ >= 0) {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001907 hwc_rect_t fbRect = getUpdatingFBRect(ctx, list);
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001908 if(!ctx->mFBUpdate[mDpy]->prepare(ctx, list, fbRect, mCurrentFrame.fbZ))
1909 {
Saurabh Shah3d4b8042013-12-10 15:19:17 -08001910 ALOGD_IF(isDebug(), "%s configure framebuffer failed",
1911 __FUNCTION__);
1912 return false;
1913 }
1914 }
1915
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001916 mCurrentFrame.map();
1917
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001918 if(!allocLayerPipes(ctx, list)) {
1919 ALOGD_IF(isDebug(), "%s: Unable to allocate MDP pipes", __FUNCTION__);
Saurabh Shahaa236822013-04-24 18:07:26 -07001920 return false;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001921 }
1922
1923 for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
Saurabh Shahaa236822013-04-24 18:07:26 -07001924 index++) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001925 if(!mCurrentFrame.isFBComposed[index]) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001926 int mdpIndex = mCurrentFrame.layerToMDP[index];
1927 hwc_layer_1_t* layer = &list->hwLayers[index];
1928
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301929 //Leave fbZ for framebuffer. CACHE/GLES layers go here.
1930 if(mdpNextZOrder == mCurrentFrame.fbZ) {
1931 mdpNextZOrder++;
1932 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001933 MdpPipeInfo* cur_pipe = mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
1934 cur_pipe->zOrder = mdpNextZOrder++;
1935
radhakrishnac9a67412013-09-25 17:40:42 +05301936 private_handle_t *hnd = (private_handle_t *)layer->handle;
Raj Kamal389d6e32014-08-04 14:43:24 +05301937 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
radhakrishnac9a67412013-09-25 17:40:42 +05301938 if(configure4k2kYuv(ctx, layer,
1939 mCurrentFrame.mdpToLayer[mdpIndex])
1940 != 0 ){
1941 ALOGD_IF(isDebug(), "%s: Failed to configure split pipes \
1942 for layer %d",__FUNCTION__, index);
1943 return false;
1944 }
1945 else{
1946 mdpNextZOrder++;
1947 }
1948 continue;
1949 }
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05001950 if(needs3DComposition(ctx,mDpy) && get3DFormat(hnd) != HAL_NO_3D) {
1951 mdpNextZOrder++;
1952 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001953 if(configure(ctx, layer, mCurrentFrame.mdpToLayer[mdpIndex]) != 0 ){
1954 ALOGD_IF(isDebug(), "%s: Failed to configure overlay for \
radhakrishnac9a67412013-09-25 17:40:42 +05301955 layer %d",__FUNCTION__, index);
Saurabh Shahaa236822013-04-24 18:07:26 -07001956 return false;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001957 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001958 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001959 }
1960
Saurabh Shaha36be922013-12-16 18:18:39 -08001961 if(!ctx->mOverlay->validateAndSet(mDpy, ctx->dpyAttr[mDpy].fd)) {
1962 ALOGD_IF(isDebug(), "%s: Failed to validate and set overlay for dpy %d"
1963 ,__FUNCTION__, mDpy);
1964 return false;
1965 }
1966
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001967 setRedraw(ctx, list);
Saurabh Shahaa236822013-04-24 18:07:26 -07001968 return true;
1969}
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001970
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08001971bool MDPComp::resourceCheck(hwc_context_t* ctx,
1972 hwc_display_contents_1_t* list) {
Saurabh Shah173f4242013-11-20 09:50:12 -08001973 const bool fbUsed = mCurrentFrame.fbCount;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001974 int cursorInUse = 0;
1975 if(mDpy == HWC_DISPLAY_PRIMARY) {
1976 // check if cursor is in use for primary
1977 cursorInUse = HWCursor::getInstance()->isCursorSet();
1978 }
1979 int maxStages = qdutils::MDPVersion::getInstance().getBlendStages();
1980 // HW Cursor needs one blending stage, account for that in the check below
1981 // On high end targets(8994) has 8 blending stages, HAL is configured to use < 8.
1982 // Make use of the remaining stages for HW Cursor so that the composition
1983 // strategy would not fail due to this limitation.
1984 if (maxStages > sMaxPipesPerMixer) {
1985 cursorInUse = 0;
1986 }
1987 if(mCurrentFrame.mdpCount > (sMaxPipesPerMixer - fbUsed - cursorInUse)) {
Saurabh Shah173f4242013-11-20 09:50:12 -08001988 ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
1989 return false;
1990 }
Saurabh Shahacec8e42014-11-25 11:07:04 -08001991
1992 //Will benefit cases where a video has non-updating background.
1993 if((mDpy > HWC_DISPLAY_PRIMARY) and
1994 (mCurrentFrame.mdpCount > sMaxSecLayers)) {
1995 ALOGD_IF(isDebug(), "%s: Exceeds max secondary pipes",__FUNCTION__);
1996 return false;
1997 }
1998
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08001999 // Init rotCount to number of rotate sessions used by other displays
2000 int rotCount = ctx->mRotMgr->getNumActiveSessions();
2001 // Count the number of rotator sessions required for current display
2002 for (int index = 0; index < mCurrentFrame.layerCount; index++) {
2003 if(!mCurrentFrame.isFBComposed[index]) {
2004 hwc_layer_1_t* layer = &list->hwLayers[index];
2005 private_handle_t *hnd = (private_handle_t *)layer->handle;
2006 if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
2007 rotCount++;
2008 }
2009 }
2010 }
2011 // if number of layers to rotate exceeds max rotator sessions, bail out.
2012 if(rotCount > RotMgr::MAX_ROT_SESS) {
2013 ALOGD_IF(isDebug(), "%s: Exceeds max rotator sessions %d",
2014 __FUNCTION__, mDpy);
2015 return false;
2016 }
Saurabh Shah173f4242013-11-20 09:50:12 -08002017 return true;
2018}
2019
Prabhanjan Kandula21918db2013-11-26 15:51:58 +05302020bool MDPComp::hwLimitationsCheck(hwc_context_t* ctx,
2021 hwc_display_contents_1_t* list) {
2022
2023 //A-family hw limitation:
2024 //If a layer need alpha scaling, MDP can not support.
2025 if(ctx->mMDP.version < qdutils::MDSS_V5) {
2026 for(int i = 0; i < mCurrentFrame.layerCount; ++i) {
2027 if(!mCurrentFrame.isFBComposed[i] &&
2028 isAlphaScaled( &list->hwLayers[i])) {
2029 ALOGD_IF(isDebug(), "%s:frame needs alphaScaling",__FUNCTION__);
2030 return false;
2031 }
2032 }
2033 }
2034
2035 // On 8x26 & 8974 hw, we have a limitation of downscaling+blending.
2036 //If multiple layers requires downscaling and also they are overlapping
2037 //fall back to GPU since MDSS can not handle it.
2038 if(qdutils::MDPVersion::getInstance().is8x74v2() ||
2039 qdutils::MDPVersion::getInstance().is8x26()) {
2040 for(int i = 0; i < mCurrentFrame.layerCount-1; ++i) {
2041 hwc_layer_1_t* botLayer = &list->hwLayers[i];
2042 if(!mCurrentFrame.isFBComposed[i] &&
2043 isDownscaleRequired(botLayer)) {
2044 //if layer-i is marked for MDP and needs downscaling
2045 //check if any MDP layer on top of i & overlaps with layer-i
2046 for(int j = i+1; j < mCurrentFrame.layerCount; ++j) {
2047 hwc_layer_1_t* topLayer = &list->hwLayers[j];
2048 if(!mCurrentFrame.isFBComposed[j] &&
2049 isDownscaleRequired(topLayer)) {
2050 hwc_rect_t r = getIntersection(botLayer->displayFrame,
2051 topLayer->displayFrame);
2052 if(isValidRect(r))
2053 return false;
2054 }
2055 }
2056 }
2057 }
2058 }
2059 return true;
2060}
2061
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002062static bool validForCursor(hwc_context_t* ctx, int dpy, hwc_layer_1_t* layer) {
2063 private_handle_t *hnd = (private_handle_t *)layer->handle;
2064 hwc_rect dst = layer->displayFrame;
2065 hwc_rect src = integerizeSourceCrop(layer->sourceCropf);
2066 int srcW = src.right - src.left;
2067 int srcH = src.bottom - src.top;
2068 int dstW = dst.right - dst.left;
2069 int dstH = dst.bottom - dst.top;
2070 qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
2071 uint32_t maxCursorSize = mdpVersion.getMaxCursorSize();
2072 uint32_t numHwCursors = mdpVersion.getCursorPipes();
2073 bool primarySplit = isDisplaySplit(ctx, HWC_DISPLAY_PRIMARY);
2074 uint32_t cursorPipesNeeded = 1; // One cursor pipe needed(default)
2075 bool ret = false;
2076
2077 if(dpy > HWC_DISPLAY_PRIMARY) {
2078 // Cursor not supported on secondary displays, as it involves scaling
2079 // in most of the cases
2080 return false;
2081 } else if (isSkipLayer(layer)) {
2082 return false;
2083 // Checks for HW limitation
2084 } else if (numHwCursors == 0 || maxCursorSize <= 0) {
2085 return false;
2086 } else if (needsScaling(layer)) {
2087 return false;
2088 } else if (layer->transform != 0) {
2089 return false;
2090 } else if (hnd->format != HAL_PIXEL_FORMAT_RGBA_8888) {
2091 return false;
2092 } else if (srcW > (int)maxCursorSize || srcH > (int)maxCursorSize) {
2093 return false;
2094 }
2095
2096 if (isDisplaySplit(ctx, dpy) && !mdpVersion.isSrcSplit()) {
2097 // In case of split display with no srcSplit, the driver allocates two
2098 // pipes to support async position update across mixers, hence
2099 // need to account for that here.
2100 cursorPipesNeeded = 2;
2101 }
2102 if (cursorPipesNeeded <= numHwCursors) {
2103 ret = true;
2104 }
2105 return ret;
2106}
2107
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08002108// Checks only if videos or single layer(RGB) is updating
2109// which is used for setting dynamic fps or perf hint for single
2110// layer video playback
2111bool MDPComp::onlyVideosUpdating(hwc_context_t *ctx,
2112 hwc_display_contents_1_t* list) {
2113 bool support = false;
2114 FrameInfo frame;
2115 frame.reset(mCurrentFrame.layerCount);
2116 memset(&frame.drop, 0, sizeof(frame.drop));
2117 frame.dropCount = 0;
2118 ALOGD_IF(isDebug(), "%s: Update Cache and YUVInfo", __FUNCTION__);
2119 updateLayerCache(ctx, list, frame);
2120 updateYUV(ctx, list, false /*secure only*/, frame);
2121 // There are only updating YUV layers or there is single RGB
2122 // Layer(Youtube)
2123 if((ctx->listStats[mDpy].yuvCount == frame.mdpCount) ||
2124 (frame.layerCount == 1)) {
2125 support = true;
2126 }
2127 return support;
2128}
2129
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302130void MDPComp::setDynRefreshRate(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
2131 //For primary display, set the dynamic refreshrate
2132 if(!mDpy && qdutils::MDPVersion::getInstance().isDynFpsSupported() &&
2133 ctx->mUseMetaDataRefreshRate) {
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302134 uint32_t refreshRate = ctx->dpyAttr[mDpy].refreshRate;
2135 MDPVersion& mdpHw = MDPVersion::getInstance();
2136 if(sIdleFallBack) {
2137 //Set minimum panel refresh rate during idle timeout
2138 refreshRate = mdpHw.getMinFpsSupported();
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08002139 } else if(onlyVideosUpdating(ctx, list)) {
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302140 //Set the new fresh rate, if there is only one updating YUV layer
2141 //or there is one single RGB layer with this request
2142 refreshRate = ctx->listStats[mDpy].refreshRateRequest;
2143 }
2144 setRefreshRate(ctx, mDpy, refreshRate);
2145 }
2146}
2147
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002148int MDPComp::prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002149 int ret = 0;
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07002150 char property[PROPERTY_VALUE_MAX];
2151
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002152 if(!list) {
2153 ALOGE("%s: Invalid list", __FUNCTION__);
Raj Kamal4393eaa2014-06-06 13:45:20 +05302154 mCachedFrame.reset();
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002155 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Raj Kamal4393eaa2014-06-06 13:45:20 +05302156 return -1;
2157 }
2158
2159 const int numLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shah286cf122014-09-08 14:13:08 -07002160 if(mDpy == HWC_DISPLAY_PRIMARY) {
2161 sSimulationFlags = 0;
2162 if(property_get("debug.hwc.simulate", property, NULL) > 0) {
2163 int currentFlags = atoi(property);
2164 if(currentFlags != sSimulationFlags) {
2165 sSimulationFlags = currentFlags;
2166 ALOGI("%s: Simulation Flag read: 0x%x (%d)", __FUNCTION__,
2167 sSimulationFlags, sSimulationFlags);
2168 }
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07002169 }
2170 }
Ramkumar Radhakrishnanc5893f12013-06-06 19:43:53 -07002171
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302172 //reset old data
2173 mCurrentFrame.reset(numLayers);
2174 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
2175 mCurrentFrame.dropCount = 0;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002176 mCurrentFrame.hwCursorIndex = -1;
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302177
Raj Kamal9ed3d6b2014-02-07 16:15:17 +05302178 //Do not cache the information for next draw cycle.
2179 if(numLayers > MAX_NUM_APP_LAYERS or (!numLayers)) {
2180 ALOGI("%s: Unsupported layer count for mdp composition",
2181 __FUNCTION__);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002182 mCachedFrame.reset();
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302183#ifdef DYNAMIC_FPS
2184 setDynRefreshRate(ctx, list);
2185#endif
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002186 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002187 return -1;
2188 }
2189
Ramkumar Radhakrishnana70981a2013-08-28 11:33:53 -07002190 // Detect the start of animation and fall back to GPU only once to cache
2191 // all the layers in FB and display FB content untill animation completes.
2192 if(ctx->listStats[mDpy].isDisplayAnimating) {
2193 mCurrentFrame.needsRedraw = false;
2194 if(ctx->mAnimationState[mDpy] == ANIMATION_STOPPED) {
2195 mCurrentFrame.needsRedraw = true;
2196 ctx->mAnimationState[mDpy] = ANIMATION_STARTED;
2197 }
2198 setMDPCompLayerFlags(ctx, list);
2199 mCachedFrame.updateCounts(mCurrentFrame);
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302200#ifdef DYNAMIC_FPS
2201 setDynRefreshRate(ctx, list);
2202#endif
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002203 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Ramkumar Radhakrishnana70981a2013-08-28 11:33:53 -07002204 ret = -1;
2205 return ret;
2206 } else {
2207 ctx->mAnimationState[mDpy] = ANIMATION_STOPPED;
2208 }
2209
Raj Kamalfdfdddf2015-03-16 21:59:25 +05302210 if(!mDpy and !isSecondaryConnected(ctx) and !mPrevModeOn and
2211 mCachedFrame.isSameFrame(ctx,mDpy,list)) {
2212
2213 ALOGD_IF(isDebug(),"%s: Avoid new composition",__FUNCTION__);
2214 mCurrentFrame.needsRedraw = false;
2215 setMDPCompLayerFlags(ctx, list);
2216 mCachedFrame.updateCounts(mCurrentFrame);
2217#ifdef DYNAMIC_FPS
2218 setDynRefreshRate(ctx, list);
2219#endif
2220 return -1;
2221
2222 }
2223
Saurabh Shahb39f8152013-08-22 10:21:44 -07002224 //Hard conditions, if not met, cannot do MDP comp
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002225 if(isFrameDoable(ctx)) {
2226 generateROI(ctx, list);
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07002227 // if AIV Video mode is enabled, drop all non AIV layers from the
2228 // external display list.
2229 if(ctx->listStats[mDpy].mAIVVideoMode) {
2230 dropNonAIVLayers(ctx, list);
2231 }
Saurabh Shahb39f8152013-08-22 10:21:44 -07002232
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002233 // Configure the cursor if present
2234 int topIndex = ctx->listStats[mDpy].numAppLayers - 1;
2235 if(ctx->listStats[mDpy].cursorLayerPresent &&
2236 validForCursor(ctx, mDpy, &(list->hwLayers[topIndex]))) {
2237 if(configHwCursor(ctx->dpyAttr[mDpy].fd, mDpy,
2238 &(list->hwLayers[topIndex]))) {
2239 // As cursor is configured, mark that layer as dropped, so that
2240 // it wont be considered for composition by other strategies.
2241 mCurrentFrame.hwCursorIndex = topIndex;
2242 mCurrentFrame.drop[topIndex] = true;
2243 mCurrentFrame.dropCount++;
2244 }
2245 } else {
2246 // Release the hw cursor
2247 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
2248 }
2249
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07002250 // if tryFullFrame fails, try to push all video and secure RGB layers
2251 // to MDP for composition.
2252 mModeOn = tryFullFrame(ctx, list) || tryMDPOnlyLayers(ctx, list) ||
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07002253 tryVideoOnly(ctx, list);
Raj Kamal4393eaa2014-06-06 13:45:20 +05302254 if(mModeOn) {
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002255 setMDPCompLayerFlags(ctx, list);
2256 } else {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08002257 resetROI(ctx, mDpy);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002258 reset(ctx);
2259 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
2260 mCurrentFrame.dropCount = 0;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002261 // Check if cursor is in use for primary and mark accordingly
2262 if(!mDpy && HWCursor::getInstance()->isCursorSet()) {
2263 int topIndex = ctx->listStats[mDpy].numAppLayers - 1;
2264 hwc_layer_1_t *layer = &(list->hwLayers[topIndex]);
2265 layer->compositionType = HWC_CURSOR_OVERLAY;
2266 }
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002267 ret = -1;
Saurabh Shah286cf122014-09-08 14:13:08 -07002268 ALOGE_IF(sSimulationFlags && (mDpy == HWC_DISPLAY_PRIMARY),
2269 "MDP Composition Strategies Failed");
Saurabh Shahb39f8152013-08-22 10:21:44 -07002270 }
2271 } else {
Dileep Kumar Reddi4070e932014-09-30 09:00:57 +05302272 if ((ctx->mMDP.version == qdutils::MDP_V3_0_5) && ctx->mCopyBit[mDpy] &&
2273 enablePartialUpdateForMDP3) {
2274 generateROI(ctx, list);
2275 for(int i = 0; i < ctx->listStats[mDpy].numAppLayers; i++) {
2276 ctx->copybitDrop[i] = mCurrentFrame.drop[i];
2277 }
2278 }
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002279 ALOGD_IF( isDebug(),"%s: MDP Comp not possible for this frame",
2280 __FUNCTION__);
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002281 // Release the hw cursor
2282 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002283 ret = -1;
Saurabh Shahb39f8152013-08-22 10:21:44 -07002284 }
Saurabh Shahb39f8152013-08-22 10:21:44 -07002285
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002286 if(isDebug()) {
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002287 ALOGD("GEOMETRY change: %d",
2288 (list->flags & HWC_GEOMETRY_CHANGED));
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002289 android::String8 sDump("");
Jeykumar Sankaran6850ac62014-05-27 10:07:26 -07002290 dump(sDump, ctx);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002291 ALOGD("%s",sDump.string());
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002292 }
2293
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07002294#ifdef DYNAMIC_FPS
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302295 setDynRefreshRate(ctx, list);
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07002296#endif
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08002297 setPerfHint(ctx, list);
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07002298
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002299 mCachedFrame.cacheAll(list);
2300 mCachedFrame.updateCounts(mCurrentFrame);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002301 return ret;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002302}
2303
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002304bool MDPComp::allocSplitVGPipes(hwc_context_t *ctx, int index) {
radhakrishnac9a67412013-09-25 17:40:42 +05302305
2306 bool bRet = true;
radhakrishnac9a67412013-09-25 17:40:42 +05302307 int mdpIndex = mCurrentFrame.layerToMDP[index];
2308 PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
2309 info.pipeInfo = new MdpYUVPipeInfo;
2310 info.rot = NULL;
2311 MdpYUVPipeInfo& pipe_info = *(MdpYUVPipeInfo*)info.pipeInfo;
radhakrishnac9a67412013-09-25 17:40:42 +05302312
2313 pipe_info.lIndex = ovutils::OV_INVALID;
2314 pipe_info.rIndex = ovutils::OV_INVALID;
2315
Saurabh Shahc62f3982014-03-05 14:28:26 -08002316 Overlay::PipeSpecs pipeSpecs;
2317 pipeSpecs.formatClass = Overlay::FORMAT_YUV;
2318 pipeSpecs.needsScaling = true;
2319 pipeSpecs.dpy = mDpy;
2320 pipeSpecs.fb = false;
2321
2322 pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
radhakrishnac9a67412013-09-25 17:40:42 +05302323 if(pipe_info.lIndex == ovutils::OV_INVALID){
2324 bRet = false;
2325 ALOGD_IF(isDebug(),"%s: allocating first VG pipe failed",
2326 __FUNCTION__);
2327 }
Saurabh Shahc62f3982014-03-05 14:28:26 -08002328 pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
radhakrishnac9a67412013-09-25 17:40:42 +05302329 if(pipe_info.rIndex == ovutils::OV_INVALID){
2330 bRet = false;
2331 ALOGD_IF(isDebug(),"%s: allocating second VG pipe failed",
2332 __FUNCTION__);
2333 }
2334 return bRet;
2335}
Sushil Chauhandefd3522014-05-13 18:17:12 -07002336
2337int MDPComp::drawOverlap(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
2338 int fd = -1;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002339 if (ctx->mPtorInfo.isActive()) {
2340 fd = ctx->mCopyBit[mDpy]->drawOverlap(ctx, list);
Sushil Chauhandefd3522014-05-13 18:17:12 -07002341 if (fd < 0) {
2342 ALOGD_IF(isDebug(),"%s: failed", __FUNCTION__);
Sushil Chauhandefd3522014-05-13 18:17:12 -07002343 }
2344 }
2345 return fd;
2346}
Arun Kumar K.R2aa44c62014-01-21 23:08:28 -08002347//=============MDPCompNonSplit==================================================
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002348
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002349void MDPCompNonSplit::adjustForSourceSplit(hwc_context_t *ctx,
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302350 hwc_display_contents_1_t* list) {
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002351 //If 4k2k Yuv layer split is possible, and if
2352 //fbz is above 4k2k layer, increment fb zorder by 1
2353 //as we split 4k2k layer and increment zorder for right half
2354 //of the layer
Shalaj Jaina70b4352014-06-15 13:47:47 -07002355 if(!ctx)
2356 return;
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002357 if(mCurrentFrame.fbZ >= 0) {
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302358 for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
2359 index++) {
2360 if(!mCurrentFrame.isFBComposed[index]) {
2361 if(mdpNextZOrder == mCurrentFrame.fbZ) {
2362 mdpNextZOrder++;
2363 }
2364 mdpNextZOrder++;
2365 hwc_layer_1_t* layer = &list->hwLayers[index];
2366 private_handle_t *hnd = (private_handle_t *)layer->handle;
Raj Kamal389d6e32014-08-04 14:43:24 +05302367 if(isYUVSplitNeeded(hnd)) {
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302368 if(mdpNextZOrder <= mCurrentFrame.fbZ)
2369 mCurrentFrame.fbZ += 1;
2370 mdpNextZOrder++;
2371 //As we split 4kx2k yuv layer and program to 2 VG pipes
2372 //(if available) increase mdpcount by 1.
2373 mCurrentFrame.mdpCount++;
2374 }
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002375 }
2376 }
2377 }
radhakrishnac9a67412013-09-25 17:40:42 +05302378}
2379
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002380/*
2381 * Configures pipe(s) for MDP composition
2382 */
Saurabh Shah88e4d272013-09-03 13:31:29 -07002383int MDPCompNonSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002384 PipeLayerPair& PipeLayerPair) {
Saurabh Shah88e4d272013-09-03 13:31:29 -07002385 MdpPipeInfoNonSplit& mdp_info =
2386 *(static_cast<MdpPipeInfoNonSplit*>(PipeLayerPair.pipeInfo));
Justin Philipd6166602014-08-12 13:42:21 +05302387 eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shahacf10202013-02-26 10:15:15 -08002388 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Saurabh Shahacf10202013-02-26 10:15:15 -08002389 eDest dest = mdp_info.index;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002390
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002391 ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipe: %d",
2392 __FUNCTION__, layer, zOrder, dest);
2393
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002394 return configureNonSplit(ctx, layer, mDpy, mdpFlags, zOrder, dest,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002395 &PipeLayerPair.rot);
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002396}
2397
Saurabh Shah88e4d272013-09-03 13:31:29 -07002398bool MDPCompNonSplit::allocLayerPipes(hwc_context_t *ctx,
Saurabh Shahe51f8ca2013-05-06 17:26:16 -07002399 hwc_display_contents_1_t* list) {
Saurabh Shah8cc77712015-03-31 10:48:51 -07002400 for(uint32_t formatType = FORMAT_YUV; formatType < FORMAT_MAX;
2401 formatType++) {
2402 for(int index = 0; index < mCurrentFrame.layerCount; index++) {
2403 if(mCurrentFrame.isFBComposed[index]) continue;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002404
Saurabh Shah8cc77712015-03-31 10:48:51 -07002405 hwc_layer_1_t* layer = &list->hwLayers[index];
2406 private_handle_t *hnd = (private_handle_t *)layer->handle;
2407 if(formatType == FORMAT_YUV && !isYuvBuffer(hnd))
radhakrishnac9a67412013-09-25 17:40:42 +05302408 continue;
Saurabh Shah8cc77712015-03-31 10:48:51 -07002409 if(formatType == FORMAT_RGB && isYuvBuffer(hnd))
2410 continue;
2411
2412 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
2413 if(allocSplitVGPipes(ctx, index)){
2414 continue;
2415 }
radhakrishnac9a67412013-09-25 17:40:42 +05302416 }
radhakrishnac9a67412013-09-25 17:40:42 +05302417
Saurabh Shah8cc77712015-03-31 10:48:51 -07002418 int mdpIndex = mCurrentFrame.layerToMDP[index];
2419 PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
2420 info.pipeInfo = new MdpPipeInfoNonSplit;
2421 info.rot = NULL;
2422 MdpPipeInfoNonSplit& pipe_info =
2423 *(MdpPipeInfoNonSplit*)info.pipeInfo;
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -08002424
Saurabh Shah8cc77712015-03-31 10:48:51 -07002425 Overlay::PipeSpecs pipeSpecs;
2426 pipeSpecs.formatClass = isYuvBuffer(hnd) ?
2427 Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
2428 pipeSpecs.needsScaling = qhwc::needsScaling(layer) or
2429 (qdutils::MDPVersion::getInstance().is8x26() and
2430 ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres > 1024);
2431 pipeSpecs.dpy = mDpy;
2432 pipeSpecs.fb = false;
2433 pipeSpecs.numActiveDisplays = ctx->numActiveDisplays;
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -08002434
Saurabh Shah8cc77712015-03-31 10:48:51 -07002435 pipe_info.index = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahc62f3982014-03-05 14:28:26 -08002436
Saurabh Shah8cc77712015-03-31 10:48:51 -07002437 if(pipe_info.index == ovutils::OV_INVALID) {
2438 ALOGD_IF(isDebug(), "%s: Unable to get pipe for layer %d of "\
2439 "format type %d", __FUNCTION__, index, formatType);
2440 return false;
2441 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002442 }
2443 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002444 return true;
2445}
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002446
radhakrishnac9a67412013-09-25 17:40:42 +05302447int MDPCompNonSplit::configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
2448 PipeLayerPair& PipeLayerPair) {
2449 MdpYUVPipeInfo& mdp_info =
2450 *(static_cast<MdpYUVPipeInfo*>(PipeLayerPair.pipeInfo));
2451 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Justin Philipd6166602014-08-12 13:42:21 +05302452 eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
radhakrishnac9a67412013-09-25 17:40:42 +05302453 eDest lDest = mdp_info.lIndex;
2454 eDest rDest = mdp_info.rIndex;
2455
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002456 return configureSourceSplit(ctx, layer, mDpy, mdpFlagsL, zOrder,
radhakrishnac9a67412013-09-25 17:40:42 +05302457 lDest, rDest, &PipeLayerPair.rot);
2458}
2459
Saurabh Shah88e4d272013-09-03 13:31:29 -07002460bool MDPCompNonSplit::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002461
Raj Kamal4393eaa2014-06-06 13:45:20 +05302462 if(!isEnabled() or !mModeOn) {
2463 ALOGD_IF(isDebug(),"%s: MDP Comp not enabled/configured", __FUNCTION__);
Prabhanjan Kandula08222fc2013-07-10 17:20:59 +05302464 return true;
2465 }
2466
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002467 overlay::Overlay& ov = *ctx->mOverlay;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002468 LayerProp *layerProp = ctx->layerProp[mDpy];
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002469
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002470 int numHwLayers = ctx->listStats[mDpy].numAppLayers;
2471 for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ )
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002472 {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002473 if(mCurrentFrame.isFBComposed[i]) continue;
2474
Naseer Ahmed5b6708a2012-08-02 13:46:08 -07002475 hwc_layer_1_t *layer = &list->hwLayers[i];
Saurabh Shahacf10202013-02-26 10:15:15 -08002476 private_handle_t *hnd = (private_handle_t *)layer->handle;
2477 if(!hnd) {
Sushil Chauhan897a9c32013-07-18 11:09:55 -07002478 if (!(layer->flags & HWC_COLOR_FILL)) {
2479 ALOGE("%s handle null", __FUNCTION__);
2480 return false;
2481 }
2482 // No PLAY for Color layer
2483 layerProp[i].mFlags &= ~HWC_MDPCOMP;
2484 continue;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002485 }
2486
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002487 int mdpIndex = mCurrentFrame.layerToMDP[i];
2488
Raj Kamal389d6e32014-08-04 14:43:24 +05302489 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit)
radhakrishnac9a67412013-09-25 17:40:42 +05302490 {
2491 MdpYUVPipeInfo& pipe_info =
2492 *(MdpYUVPipeInfo*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
2493 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
2494 ovutils::eDest indexL = pipe_info.lIndex;
2495 ovutils::eDest indexR = pipe_info.rIndex;
2496 int fd = hnd->fd;
Praveena Pachipulusud9443c72014-02-17 10:42:28 +05302497 uint32_t offset = (uint32_t)hnd->offset;
radhakrishnac9a67412013-09-25 17:40:42 +05302498 if(rot) {
2499 rot->queueBuffer(fd, offset);
2500 fd = rot->getDstMemId();
2501 offset = rot->getDstOffset();
2502 }
2503 if(indexL != ovutils::OV_INVALID) {
2504 ovutils::eDest destL = (ovutils::eDest)indexL;
2505 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2506 using pipe: %d", __FUNCTION__, layer, hnd, indexL );
2507 if (!ov.queueBuffer(fd, offset, destL)) {
2508 ALOGE("%s: queueBuffer failed for display:%d",
2509 __FUNCTION__, mDpy);
2510 return false;
2511 }
2512 }
2513
2514 if(indexR != ovutils::OV_INVALID) {
2515 ovutils::eDest destR = (ovutils::eDest)indexR;
2516 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2517 using pipe: %d", __FUNCTION__, layer, hnd, indexR );
2518 if (!ov.queueBuffer(fd, offset, destR)) {
2519 ALOGE("%s: queueBuffer failed for display:%d",
2520 __FUNCTION__, mDpy);
2521 return false;
2522 }
2523 }
2524 }
2525 else{
2526 MdpPipeInfoNonSplit& pipe_info =
Saurabh Shah88e4d272013-09-03 13:31:29 -07002527 *(MdpPipeInfoNonSplit*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
radhakrishnac9a67412013-09-25 17:40:42 +05302528 ovutils::eDest dest = pipe_info.index;
2529 if(dest == ovutils::OV_INVALID) {
2530 ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, dest);
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002531 return false;
radhakrishnac9a67412013-09-25 17:40:42 +05302532 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002533
radhakrishnac9a67412013-09-25 17:40:42 +05302534 if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
2535 continue;
2536 }
2537
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002538 int fd = hnd->fd;
2539 uint32_t offset = (uint32_t)hnd->offset;
2540 int index = ctx->mPtorInfo.getPTORArrayIndex(i);
2541 if (!mDpy && (index != -1)) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07002542 hnd = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002543 fd = hnd->fd;
Sushil Chauhan875a92e2014-07-25 12:20:23 -07002544 offset = 0;
Sushil Chauhandefd3522014-05-13 18:17:12 -07002545 }
2546
radhakrishnac9a67412013-09-25 17:40:42 +05302547 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2548 using pipe: %d", __FUNCTION__, layer,
2549 hnd, dest );
2550
radhakrishnac9a67412013-09-25 17:40:42 +05302551 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
2552 if(rot) {
2553 if(!rot->queueBuffer(fd, offset))
2554 return false;
2555 fd = rot->getDstMemId();
2556 offset = rot->getDstOffset();
2557 }
2558
2559 if (!ov.queueBuffer(fd, offset, dest)) {
2560 ALOGE("%s: queueBuffer failed for display:%d ",
2561 __FUNCTION__, mDpy);
2562 return false;
2563 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002564 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002565
2566 layerProp[i].mFlags &= ~HWC_MDPCOMP;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002567 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002568 return true;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002569}
2570
Saurabh Shah88e4d272013-09-03 13:31:29 -07002571//=============MDPCompSplit===================================================
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002572
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002573void MDPCompSplit::adjustForSourceSplit(hwc_context_t *ctx,
radhakrishnac9a67412013-09-25 17:40:42 +05302574 hwc_display_contents_1_t* list){
2575 //if 4kx2k yuv layer is totally present in either in left half
2576 //or right half then try splitting the yuv layer to avoid decimation
radhakrishnac9a67412013-09-25 17:40:42 +05302577 const int lSplit = getLeftSplit(ctx, mDpy);
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302578 if(mCurrentFrame.fbZ >= 0) {
2579 for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
2580 index++) {
2581 if(!mCurrentFrame.isFBComposed[index]) {
2582 if(mdpNextZOrder == mCurrentFrame.fbZ) {
2583 mdpNextZOrder++;
2584 }
2585 mdpNextZOrder++;
2586 hwc_layer_1_t* layer = &list->hwLayers[index];
2587 private_handle_t *hnd = (private_handle_t *)layer->handle;
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002588 if(isYUVSplitNeeded(hnd) ||
2589 (needs3DComposition(ctx,mDpy) &&
2590 get3DFormat(hnd) != HAL_NO_3D)) {
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302591 hwc_rect_t dst = layer->displayFrame;
2592 if((dst.left > lSplit) || (dst.right < lSplit)) {
2593 mCurrentFrame.mdpCount += 1;
2594 }
2595 if(mdpNextZOrder <= mCurrentFrame.fbZ)
2596 mCurrentFrame.fbZ += 1;
2597 mdpNextZOrder++;
2598 }
2599 }
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002600 }
radhakrishnac9a67412013-09-25 17:40:42 +05302601 }
2602}
2603
Saurabh Shah88e4d272013-09-03 13:31:29 -07002604bool MDPCompSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
Saurabh Shahc62f3982014-03-05 14:28:26 -08002605 MdpPipeInfoSplit& pipe_info) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002606
Saurabh Shahc62f3982014-03-05 14:28:26 -08002607 const int lSplit = getLeftSplit(ctx, mDpy);
2608 private_handle_t *hnd = (private_handle_t *)layer->handle;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002609 hwc_rect_t dst = layer->displayFrame;
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002610 pipe_info.lIndex = ovutils::OV_INVALID;
2611 pipe_info.rIndex = ovutils::OV_INVALID;
2612
Saurabh Shahc62f3982014-03-05 14:28:26 -08002613 Overlay::PipeSpecs pipeSpecs;
2614 pipeSpecs.formatClass = isYuvBuffer(hnd) ?
2615 Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
2616 pipeSpecs.needsScaling = qhwc::needsScalingWithSplit(ctx, layer, mDpy);
2617 pipeSpecs.dpy = mDpy;
2618 pipeSpecs.mixer = Overlay::MIXER_LEFT;
2619 pipeSpecs.fb = false;
2620
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08002621 // Acquire pipe only for the updating half
2622 hwc_rect_t l_roi = ctx->listStats[mDpy].lRoi;
2623 hwc_rect_t r_roi = ctx->listStats[mDpy].rRoi;
2624
2625 if (dst.left < lSplit && isValidRect(getIntersection(dst, l_roi))) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002626 pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002627 if(pipe_info.lIndex == ovutils::OV_INVALID)
2628 return false;
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002629 }
2630
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08002631 if(dst.right > lSplit && isValidRect(getIntersection(dst, r_roi))) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002632 pipeSpecs.mixer = Overlay::MIXER_RIGHT;
2633 pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002634 if(pipe_info.rIndex == ovutils::OV_INVALID)
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002635 return false;
2636 }
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002637
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002638 return true;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002639}
2640
Saurabh Shah88e4d272013-09-03 13:31:29 -07002641bool MDPCompSplit::allocLayerPipes(hwc_context_t *ctx,
Saurabh Shahe51f8ca2013-05-06 17:26:16 -07002642 hwc_display_contents_1_t* list) {
Saurabh Shah8cc77712015-03-31 10:48:51 -07002643 for(uint32_t formatType = FORMAT_YUV; formatType < FORMAT_MAX;
2644 formatType++) {
2645 for(int index = 0 ; index < mCurrentFrame.layerCount; index++) {
2646 if(mCurrentFrame.isFBComposed[index]) continue;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002647
Saurabh Shah8cc77712015-03-31 10:48:51 -07002648 hwc_layer_1_t* layer = &list->hwLayers[index];
2649 private_handle_t *hnd = (private_handle_t *)layer->handle;
2650 if(formatType == FORMAT_YUV && !isYuvBuffer(hnd))
2651 continue;
2652 if(formatType == FORMAT_RGB && isYuvBuffer(hnd))
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002653 continue;
2654
Saurabh Shah8cc77712015-03-31 10:48:51 -07002655 hwc_rect_t dst = layer->displayFrame;
2656 const int lSplit = getLeftSplit(ctx, mDpy);
2657 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
2658 if((dst.left > lSplit)||(dst.right < lSplit)){
2659 if(allocSplitVGPipes(ctx, index)){
2660 continue;
2661 }
2662 }
2663 }
2664 //XXX: Check for forced 2D composition
2665 if(needs3DComposition(ctx, mDpy) && get3DFormat(hnd) != HAL_NO_3D)
2666 if(allocSplitVGPipes(ctx,index))
2667 continue;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002668
Saurabh Shah8cc77712015-03-31 10:48:51 -07002669 int mdpIndex = mCurrentFrame.layerToMDP[index];
2670 PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
2671 info.pipeInfo = new MdpPipeInfoSplit;
2672 info.rot = NULL;
2673 MdpPipeInfoSplit& pipe_info = *(MdpPipeInfoSplit*)info.pipeInfo;
2674
2675 if(!acquireMDPPipes(ctx, layer, pipe_info)) {
2676 ALOGD_IF(isDebug(), "%s: Unable to get pipe for layer %d of "\
2677 "format type %d", __FUNCTION__, index, formatType);
2678 return false;
2679 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002680 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002681 }
2682 return true;
2683}
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002684
radhakrishnac9a67412013-09-25 17:40:42 +05302685int MDPCompSplit::configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
2686 PipeLayerPair& PipeLayerPair) {
2687 const int lSplit = getLeftSplit(ctx, mDpy);
2688 hwc_rect_t dst = layer->displayFrame;
2689 if((dst.left > lSplit)||(dst.right < lSplit)){
2690 MdpYUVPipeInfo& mdp_info =
2691 *(static_cast<MdpYUVPipeInfo*>(PipeLayerPair.pipeInfo));
2692 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Justin Philipd6166602014-08-12 13:42:21 +05302693 eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
radhakrishnac9a67412013-09-25 17:40:42 +05302694 eDest lDest = mdp_info.lIndex;
2695 eDest rDest = mdp_info.rIndex;
2696
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002697 return configureSourceSplit(ctx, layer, mDpy, mdpFlagsL, zOrder,
radhakrishnac9a67412013-09-25 17:40:42 +05302698 lDest, rDest, &PipeLayerPair.rot);
2699 }
2700 else{
2701 return configure(ctx, layer, PipeLayerPair);
2702 }
2703}
2704
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002705/*
2706 * Configures pipe(s) for MDP composition
2707 */
Saurabh Shah88e4d272013-09-03 13:31:29 -07002708int MDPCompSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
Saurabh Shah67a38c32013-06-10 16:23:15 -07002709 PipeLayerPair& PipeLayerPair) {
Saurabh Shah88e4d272013-09-03 13:31:29 -07002710 MdpPipeInfoSplit& mdp_info =
2711 *(static_cast<MdpPipeInfoSplit*>(PipeLayerPair.pipeInfo));
Saurabh Shahacf10202013-02-26 10:15:15 -08002712 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Justin Philipd6166602014-08-12 13:42:21 +05302713 eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shahacf10202013-02-26 10:15:15 -08002714 eDest lDest = mdp_info.lIndex;
2715 eDest rDest = mdp_info.rIndex;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002716
2717 ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
Jeykumar Sankaran39305802014-12-12 17:55:57 -08002718 "dest_pipeR: %d",__FUNCTION__, layer, zOrder, lDest, rDest);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002719
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002720 return configureSplit(ctx, layer, mDpy, mdpFlagsL, zOrder, lDest,
Jeykumar Sankaran39305802014-12-12 17:55:57 -08002721 rDest, &PipeLayerPair.rot);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002722}
2723
Saurabh Shah88e4d272013-09-03 13:31:29 -07002724bool MDPCompSplit::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002725
Raj Kamal4393eaa2014-06-06 13:45:20 +05302726 if(!isEnabled() or !mModeOn) {
2727 ALOGD_IF(isDebug(),"%s: MDP Comp not enabled/configured", __FUNCTION__);
Prabhanjan Kandula08222fc2013-07-10 17:20:59 +05302728 return true;
2729 }
2730
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002731 overlay::Overlay& ov = *ctx->mOverlay;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002732 LayerProp *layerProp = ctx->layerProp[mDpy];
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002733
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002734 int numHwLayers = ctx->listStats[mDpy].numAppLayers;
2735 for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ )
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002736 {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002737 if(mCurrentFrame.isFBComposed[i]) continue;
2738
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002739 hwc_layer_1_t *layer = &list->hwLayers[i];
Saurabh Shahacf10202013-02-26 10:15:15 -08002740 private_handle_t *hnd = (private_handle_t *)layer->handle;
2741 if(!hnd) {
2742 ALOGE("%s handle null", __FUNCTION__);
2743 return false;
2744 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002745
2746 if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
2747 continue;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002748 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002749
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002750 int mdpIndex = mCurrentFrame.layerToMDP[i];
2751
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002752 if((isYUVSplitNeeded(hnd) && sEnableYUVsplit) ||
2753 (needs3DComposition(ctx, mDpy) && get3DFormat(hnd) != HAL_NO_3D))
radhakrishnac9a67412013-09-25 17:40:42 +05302754 {
2755 MdpYUVPipeInfo& pipe_info =
2756 *(MdpYUVPipeInfo*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
2757 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
2758 ovutils::eDest indexL = pipe_info.lIndex;
2759 ovutils::eDest indexR = pipe_info.rIndex;
2760 int fd = hnd->fd;
Praveena Pachipulusud9443c72014-02-17 10:42:28 +05302761 uint32_t offset = (uint32_t)hnd->offset;
radhakrishnac9a67412013-09-25 17:40:42 +05302762 if(rot) {
2763 rot->queueBuffer(fd, offset);
2764 fd = rot->getDstMemId();
2765 offset = rot->getDstOffset();
2766 }
2767 if(indexL != ovutils::OV_INVALID) {
2768 ovutils::eDest destL = (ovutils::eDest)indexL;
2769 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2770 using pipe: %d", __FUNCTION__, layer, hnd, indexL );
2771 if (!ov.queueBuffer(fd, offset, destL)) {
2772 ALOGE("%s: queueBuffer failed for display:%d",
2773 __FUNCTION__, mDpy);
2774 return false;
2775 }
2776 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002777
radhakrishnac9a67412013-09-25 17:40:42 +05302778 if(indexR != ovutils::OV_INVALID) {
2779 ovutils::eDest destR = (ovutils::eDest)indexR;
2780 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2781 using pipe: %d", __FUNCTION__, layer, hnd, indexR );
2782 if (!ov.queueBuffer(fd, offset, destR)) {
2783 ALOGE("%s: queueBuffer failed for display:%d",
2784 __FUNCTION__, mDpy);
2785 return false;
2786 }
Saurabh Shaha9da08f2013-07-03 13:27:53 -07002787 }
2788 }
radhakrishnac9a67412013-09-25 17:40:42 +05302789 else{
2790 MdpPipeInfoSplit& pipe_info =
2791 *(MdpPipeInfoSplit*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
2792 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
Saurabh Shaha9da08f2013-07-03 13:27:53 -07002793
radhakrishnac9a67412013-09-25 17:40:42 +05302794 ovutils::eDest indexL = pipe_info.lIndex;
2795 ovutils::eDest indexR = pipe_info.rIndex;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002796
radhakrishnac9a67412013-09-25 17:40:42 +05302797 int fd = hnd->fd;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002798 uint32_t offset = (uint32_t)hnd->offset;
2799 int index = ctx->mPtorInfo.getPTORArrayIndex(i);
2800 if (!mDpy && (index != -1)) {
2801 hnd = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
2802 fd = hnd->fd;
Sushil Chauhan875a92e2014-07-25 12:20:23 -07002803 offset = 0;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002804 }
radhakrishnac9a67412013-09-25 17:40:42 +05302805
Tatenda Chipeperekwa88fe6352014-04-14 10:36:06 -07002806 if(ctx->mAD->draw(ctx, fd, offset)) {
2807 fd = ctx->mAD->getDstFd();
2808 offset = ctx->mAD->getDstOffset();
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002809 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002810
radhakrishnac9a67412013-09-25 17:40:42 +05302811 if(rot) {
2812 rot->queueBuffer(fd, offset);
2813 fd = rot->getDstMemId();
2814 offset = rot->getDstOffset();
2815 }
2816
2817 //************* play left mixer **********
2818 if(indexL != ovutils::OV_INVALID) {
2819 ovutils::eDest destL = (ovutils::eDest)indexL;
2820 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2821 using pipe: %d", __FUNCTION__, layer, hnd, indexL );
2822 if (!ov.queueBuffer(fd, offset, destL)) {
2823 ALOGE("%s: queueBuffer failed for left mixer",
2824 __FUNCTION__);
2825 return false;
2826 }
2827 }
2828
2829 //************* play right mixer **********
2830 if(indexR != ovutils::OV_INVALID) {
2831 ovutils::eDest destR = (ovutils::eDest)indexR;
2832 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2833 using pipe: %d", __FUNCTION__, layer, hnd, indexR );
2834 if (!ov.queueBuffer(fd, offset, destR)) {
2835 ALOGE("%s: queueBuffer failed for right mixer",
2836 __FUNCTION__);
2837 return false;
2838 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002839 }
2840 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002841
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002842 layerProp[i].mFlags &= ~HWC_MDPCOMP;
2843 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002844
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002845 return true;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002846}
Saurabh Shahab47c692014-02-12 18:45:57 -08002847
2848//================MDPCompSrcSplit==============================================
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08002849
2850bool MDPCompSrcSplit::validateAndApplyROI(hwc_context_t *ctx,
2851 hwc_display_contents_1_t* list) {
2852 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
2853 hwc_rect_t visibleRect = ctx->listStats[mDpy].lRoi;
2854
2855 for(int i = numAppLayers - 1; i >= 0; i--) {
2856 if(!isValidRect(visibleRect)) {
2857 mCurrentFrame.drop[i] = true;
2858 mCurrentFrame.dropCount++;
2859 continue;
2860 }
2861
2862 const hwc_layer_1_t* layer = &list->hwLayers[i];
2863 hwc_rect_t dstRect = layer->displayFrame;
2864 hwc_rect_t res = getIntersection(visibleRect, dstRect);
2865
2866 if(!isValidRect(res)) {
2867 mCurrentFrame.drop[i] = true;
2868 mCurrentFrame.dropCount++;
2869 } else {
2870 /* Reset frame ROI when any layer which needs scaling also needs ROI
2871 * cropping */
2872 if(!isSameRect(res, dstRect) && needsScaling (layer)) {
2873 ALOGI("%s: Resetting ROI due to scaling", __FUNCTION__);
2874 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
2875 mCurrentFrame.dropCount = 0;
2876 return false;
2877 }
2878
2879 /* deduct any opaque region from visibleRect */
2880 if (layer->blending == HWC_BLENDING_NONE &&
2881 layer->planeAlpha == 0xFF)
2882 visibleRect = deductRect(visibleRect, res);
2883 }
2884 }
2885 return true;
2886}
2887
2888/*
2889 * HW Limitation: ping pong split can always split the ping pong output
2890 * equally across two DSI's. So the ROI programmed should be of equal width
2891 * for both the halves
2892 */
2893void MDPCompSrcSplit::generateROI(hwc_context_t *ctx,
2894 hwc_display_contents_1_t* list) {
2895 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
2896
2897
2898 if(!canPartialUpdate(ctx, list))
2899 return;
2900
2901 struct hwc_rect roi = (struct hwc_rect){0, 0, 0, 0};
2902 hwc_rect fullFrame = (struct hwc_rect) {0, 0,(int)ctx->dpyAttr[mDpy].xres,
2903 (int)ctx->dpyAttr[mDpy].yres};
2904
2905 for(int index = 0; index < numAppLayers; index++ ) {
2906 hwc_layer_1_t* layer = &list->hwLayers[index];
2907
2908 // If we have a RGB layer which needs rotation, no partial update
2909 if(!isYuvBuffer((private_handle_t *)layer->handle) && layer->transform)
2910 return;
2911
2912 if ((mCachedFrame.hnd[index] != layer->handle) ||
2913 isYuvBuffer((private_handle_t *)layer->handle)) {
2914 hwc_rect_t dst = layer->displayFrame;
2915 hwc_rect_t updatingRect = dst;
2916
2917#ifdef QCOM_BSP
2918 if(!needsScaling(layer) && !layer->transform)
2919 {
2920 hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
2921 int x_off = dst.left - src.left;
2922 int y_off = dst.top - src.top;
2923 updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
2924 }
2925#endif
2926
2927 roi = getUnion(roi, updatingRect);
2928 }
2929 }
2930
2931 /* No layer is updating. Still SF wants a refresh.*/
2932 if(!isValidRect(roi))
2933 return;
2934
2935 roi = expandROIFromMidPoint(roi, fullFrame);
2936
2937 hwc_rect lFrame = fullFrame;
2938 lFrame.right /= 2;
2939 hwc_rect lRoi = getIntersection(roi, lFrame);
2940
2941 // Align ROI coordinates to panel restrictions
2942 lRoi = getSanitizeROI(lRoi, lFrame);
2943
2944 hwc_rect rFrame = fullFrame;
2945 rFrame.left = lFrame.right;
2946 hwc_rect rRoi = getIntersection(roi, rFrame);
2947
2948 // Align ROI coordinates to panel restrictions
2949 rRoi = getSanitizeROI(rRoi, rFrame);
2950
2951 roi = getUnion(lRoi, rRoi);
2952
2953 ctx->listStats[mDpy].lRoi = roi;
2954 if(!validateAndApplyROI(ctx, list))
2955 resetROI(ctx, mDpy);
2956
2957 ALOGD_IF(isDebug(),"%s: generated ROI: [%d, %d, %d, %d] [%d, %d, %d, %d]",
2958 __FUNCTION__,
2959 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
2960 ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom,
2961 ctx->listStats[mDpy].rRoi.left, ctx->listStats[mDpy].rRoi.top,
2962 ctx->listStats[mDpy].rRoi.right, ctx->listStats[mDpy].rRoi.bottom);
2963}
2964
Saurabh Shahab47c692014-02-12 18:45:57 -08002965bool MDPCompSrcSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
Saurabh Shahc62f3982014-03-05 14:28:26 -08002966 MdpPipeInfoSplit& pipe_info) {
Saurabh Shahab47c692014-02-12 18:45:57 -08002967 private_handle_t *hnd = (private_handle_t *)layer->handle;
2968 hwc_rect_t dst = layer->displayFrame;
2969 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
2970 pipe_info.lIndex = ovutils::OV_INVALID;
2971 pipe_info.rIndex = ovutils::OV_INVALID;
2972
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08002973 if(qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() && !mDpy)
2974 trimAgainstROI(ctx,crop, dst);
2975
Saurabh Shahab47c692014-02-12 18:45:57 -08002976 //If 2 pipes are staged on a single stage of a mixer, then the left pipe
2977 //should have a higher priority than the right one. Pipe priorities are
2978 //starting with VG0, VG1 ... , RGB0 ..., DMA1
Saurabh Shahab47c692014-02-12 18:45:57 -08002979
Saurabh Shahc62f3982014-03-05 14:28:26 -08002980 Overlay::PipeSpecs pipeSpecs;
2981 pipeSpecs.formatClass = isYuvBuffer(hnd) ?
2982 Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
2983 pipeSpecs.needsScaling = qhwc::needsScaling(layer);
2984 pipeSpecs.dpy = mDpy;
2985 pipeSpecs.fb = false;
2986
Saurabh Shahab47c692014-02-12 18:45:57 -08002987 //1 pipe by default for a layer
Saurabh Shahc62f3982014-03-05 14:28:26 -08002988 pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahab47c692014-02-12 18:45:57 -08002989 if(pipe_info.lIndex == ovutils::OV_INVALID) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002990 return false;
Saurabh Shahab47c692014-02-12 18:45:57 -08002991 }
2992
Saurabh Shahea7a01d2014-05-22 17:45:36 -07002993 /* Use 2 pipes IF
2994 a) Layer's crop width is > 2048 or
2995 b) Layer's dest width > 2048 or
2996 c) On primary, driver has indicated with caps to split always. This is
2997 based on an empirically derived value of panel height. Applied only
2998 if the layer's width is > mixer's width
2999 */
3000
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +05303001 MDPVersion& mdpHw = MDPVersion::getInstance();
Saurabh Shahea7a01d2014-05-22 17:45:36 -07003002 bool primarySplitAlways = (mDpy == HWC_DISPLAY_PRIMARY) and
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +05303003 mdpHw.isSrcSplitAlways();
Saurabh Shah514759d2014-11-11 18:02:24 -08003004 const uint32_t lSplit = getLeftSplit(ctx, mDpy);
3005 const uint32_t dstWidth = dst.right - dst.left;
3006 const uint32_t dstHeight = dst.bottom - dst.top;
Saurabh Shah05f4e222015-02-05 14:36:22 -08003007 uint32_t cropWidth = has90Transform(layer) ? crop.bottom - crop.top :
Saurabh Shah189f23d2014-09-26 17:21:00 -07003008 crop.right - crop.left;
Saurabh Shah05f4e222015-02-05 14:36:22 -08003009 uint32_t cropHeight = has90Transform(layer) ? crop.right - crop.left :
Saurabh Shah514759d2014-11-11 18:02:24 -08003010 crop.bottom - crop.top;
3011 //Approximation to actual clock, ignoring the common factors in pipe and
3012 //mixer cases like line_time
3013 const uint32_t layerClock = getLayerClock(dstWidth, dstHeight, cropHeight);
3014 const uint32_t mixerClock = lSplit;
Saurabh Shahea7a01d2014-05-22 17:45:36 -07003015
Saurabh Shah05f4e222015-02-05 14:36:22 -08003016 const uint32_t downscale = getRotDownscale(ctx, layer);
3017 if(downscale) {
3018 cropWidth /= downscale;
3019 cropHeight /= downscale;
3020 }
3021
Jeykumar Sankaran39305802014-12-12 17:55:57 -08003022 if(dstWidth > mdpHw.getMaxPipeWidth() or
3023 cropWidth > mdpHw.getMaxPipeWidth() or
Saurabh Shah514759d2014-11-11 18:02:24 -08003024 (primarySplitAlways and
3025 (cropWidth > lSplit or layerClock > mixerClock))) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08003026 pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahab47c692014-02-12 18:45:57 -08003027 if(pipe_info.rIndex == ovutils::OV_INVALID) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08003028 return false;
Saurabh Shahdd8237a2014-02-28 14:29:09 -08003029 }
3030
Jeykumar Sankaran89e23ab2015-01-28 15:57:46 -08003031 if(ctx->mOverlay->needsPrioritySwap(pipe_info.lIndex,
3032 pipe_info.rIndex)) {
Saurabh Shahdd8237a2014-02-28 14:29:09 -08003033 qhwc::swap(pipe_info.lIndex, pipe_info.rIndex);
Saurabh Shahab47c692014-02-12 18:45:57 -08003034 }
3035 }
3036
3037 return true;
3038}
3039
Saurabh Shahab47c692014-02-12 18:45:57 -08003040int MDPCompSrcSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
3041 PipeLayerPair& PipeLayerPair) {
3042 private_handle_t *hnd = (private_handle_t *)layer->handle;
3043 if(!hnd) {
3044 ALOGE("%s: layer handle is NULL", __FUNCTION__);
3045 return -1;
3046 }
3047 MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
3048 MdpPipeInfoSplit& mdp_info =
3049 *(static_cast<MdpPipeInfoSplit*>(PipeLayerPair.pipeInfo));
3050 Rotator **rot = &PipeLayerPair.rot;
3051 eZorder z = static_cast<eZorder>(mdp_info.zOrder);
Saurabh Shahab47c692014-02-12 18:45:57 -08003052 eDest lDest = mdp_info.lIndex;
3053 eDest rDest = mdp_info.rIndex;
3054 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
3055 hwc_rect_t dst = layer->displayFrame;
3056 int transform = layer->transform;
3057 eTransform orient = static_cast<eTransform>(transform);
Saurabh Shahab47c692014-02-12 18:45:57 -08003058 int rotFlags = ROT_FLAGS_NONE;
Sushil Chauhan65e26302015-01-14 10:48:57 -08003059 uint32_t format = ovutils::getMdpFormat(hnd->format, hnd->flags);
Saurabh Shahab47c692014-02-12 18:45:57 -08003060 Whf whf(getWidth(hnd), getHeight(hnd), format, hnd->size);
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05003061 eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shahab47c692014-02-12 18:45:57 -08003062
3063 ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
3064 "dest_pipeR: %d",__FUNCTION__, layer, z, lDest, rDest);
3065
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08003066 if(qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() && !mDpy) {
3067 /* MDP driver crops layer coordinates against ROI in Non-Split
3068 * and Split MDP comp. But HWC needs to crop them for source split.
3069 * Reason: 1) Source split is efficient only when the final effective
3070 * load is distributed evenly across mixers.
3071 * 2) We have to know the effective width of the layer that
3072 * the ROI needs to find the no. of pipes the layer needs.
3073 */
3074 trimAgainstROI(ctx, crop, dst);
3075 }
3076
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05003077 if(needs3DComposition(ctx, mDpy) &&
3078 get3DFormat(hnd) != HAL_NO_3D){
3079 return configure3DVideo(ctx, layer, mDpy, mdpFlags, z, lDest,
3080 rDest, &PipeLayerPair.rot);
3081 }
3082
Saurabh Shahab47c692014-02-12 18:45:57 -08003083 // Handle R/B swap
3084 if (layer->flags & HWC_FORMAT_RB_SWAP) {
3085 if (hnd->format == HAL_PIXEL_FORMAT_RGBA_8888)
3086 whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRA_8888);
3087 else if (hnd->format == HAL_PIXEL_FORMAT_RGBX_8888)
3088 whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
3089 }
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07003090 // update source crop and destination position of AIV video layer.
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07003091 if(ctx->listStats[mDpy].mAIVVideoMode && isYuvBuffer(hnd)) {
3092 updateCoordinates(ctx, crop, dst, mDpy);
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07003093 }
Ramkumar Radhakrishnana5c72872014-08-28 19:04:18 -07003094 /* Calculate the external display position based on MDP downscale,
3095 ActionSafe, and extorientation features. */
3096 calcExtDisplayPosition(ctx, hnd, mDpy, crop, dst, transform, orient);
Saurabh Shahab47c692014-02-12 18:45:57 -08003097
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003098 int downscale = getRotDownscale(ctx, layer);
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003099 setMdpFlags(ctx, layer, mdpFlags, downscale, transform);
Saurabh Shahab47c692014-02-12 18:45:57 -08003100
3101 if(lDest != OV_INVALID && rDest != OV_INVALID) {
3102 //Enable overfetch
Saurabh Shah97e2d802014-04-14 18:03:54 -07003103 setMdpFlags(mdpFlags, OV_MDSS_MDP_DUAL_PIPE);
Saurabh Shahab47c692014-02-12 18:45:57 -08003104 }
3105
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003106 if((has90Transform(layer) or downscale) and isRotationDoable(ctx, hnd)) {
Saurabh Shahab47c692014-02-12 18:45:57 -08003107 (*rot) = ctx->mRotMgr->getNext();
3108 if((*rot) == NULL) return -1;
Saurabh Shah39240c92014-03-31 10:31:42 -07003109 ctx->mLayerRotMap[mDpy]->add(layer, *rot);
Saurabh Shah1bd5b6f2014-05-19 12:23:13 -07003110 //If the video is using a single pipe, enable BWC
3111 if(rDest == OV_INVALID) {
Saurabh Shahcd018352014-11-11 13:54:19 -08003112 BwcPM::setBwc(ctx, mDpy, hnd, crop, dst, transform, downscale,
3113 mdpFlags);
Saurabh Shah1bd5b6f2014-05-19 12:23:13 -07003114 }
Saurabh Shahab47c692014-02-12 18:45:57 -08003115 //Configure rotator for pre-rotation
Saurabh Shah97e2d802014-04-14 18:03:54 -07003116 if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale) < 0) {
Saurabh Shahab47c692014-02-12 18:45:57 -08003117 ALOGE("%s: configRotator failed!", __FUNCTION__);
3118 return -1;
3119 }
Saurabh Shah8ec9b5e2014-06-30 14:37:17 -07003120 updateSource(orient, whf, crop, *rot);
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003121 rotFlags |= ovutils::ROT_PREROTATED;
Saurabh Shahab47c692014-02-12 18:45:57 -08003122 }
3123
3124 //If 2 pipes being used, divide layer into half, crop and dst
3125 hwc_rect_t cropL = crop;
3126 hwc_rect_t cropR = crop;
3127 hwc_rect_t dstL = dst;
3128 hwc_rect_t dstR = dst;
3129 if(lDest != OV_INVALID && rDest != OV_INVALID) {
3130 cropL.right = (crop.right + crop.left) / 2;
3131 cropR.left = cropL.right;
3132 sanitizeSourceCrop(cropL, cropR, hnd);
3133
Saurabh Shahb729b192014-08-15 18:04:24 -07003134 bool cropSwap = false;
Saurabh Shahab47c692014-02-12 18:45:57 -08003135 //Swap crops on H flip since 2 pipes are being used
3136 if((orient & OVERLAY_TRANSFORM_FLIP_H) && (*rot) == NULL) {
3137 hwc_rect_t tmp = cropL;
3138 cropL = cropR;
3139 cropR = tmp;
Saurabh Shahb729b192014-08-15 18:04:24 -07003140 cropSwap = true;
Saurabh Shahab47c692014-02-12 18:45:57 -08003141 }
3142
Saurabh Shahb729b192014-08-15 18:04:24 -07003143 //cropSwap trick: If the src and dst widths are both odd, let us say
3144 //2507, then splitting both into half would cause left width to be 1253
3145 //and right 1254. If crop is swapped because of H flip, this will cause
3146 //left crop width to be 1254, whereas left dst width remains 1253, thus
3147 //inducing a scaling that is unaccounted for. To overcome that we add 1
3148 //to the dst width if there is a cropSwap. So if the original width was
3149 //2507, the left dst width will be 1254. Even if the original width was
3150 //even for ex: 2508, the left dst width will still remain 1254.
3151 dstL.right = (dst.right + dst.left + cropSwap) / 2;
Saurabh Shahab47c692014-02-12 18:45:57 -08003152 dstR.left = dstL.right;
3153 }
3154
3155 //For the mdp, since either we are pre-rotating or MDP does flips
3156 orient = OVERLAY_TRANSFORM_0;
3157 transform = 0;
3158
3159 //configure left pipe
3160 if(lDest != OV_INVALID) {
Saurabh Shah2c8ad052014-08-15 13:27:46 -07003161 PipeArgs pargL(mdpFlags, whf, z,
Saurabh Shahab47c692014-02-12 18:45:57 -08003162 static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
3163 (ovutils::eBlending) getBlending(layer->blending));
3164
3165 if(configMdp(ctx->mOverlay, pargL, orient,
3166 cropL, dstL, metadata, lDest) < 0) {
3167 ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
3168 return -1;
3169 }
3170 }
3171
3172 //configure right pipe
3173 if(rDest != OV_INVALID) {
Saurabh Shah2c8ad052014-08-15 13:27:46 -07003174 PipeArgs pargR(mdpFlags, whf, z,
Saurabh Shahab47c692014-02-12 18:45:57 -08003175 static_cast<eRotFlags>(rotFlags),
3176 layer->planeAlpha,
3177 (ovutils::eBlending) getBlending(layer->blending));
3178 if(configMdp(ctx->mOverlay, pargR, orient,
3179 cropR, dstR, metadata, rDest) < 0) {
3180 ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
3181 return -1;
3182 }
3183 }
3184
3185 return 0;
3186}
3187
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -08003188bool MDPComp::getPartialUpdatePref(hwc_context_t *ctx) {
3189 Locker::Autolock _l(ctx->mDrawLock);
3190 const int fbNum = Overlay::getFbForDpy(Overlay::DPY_PRIMARY);
3191 char path[MAX_SYSFS_FILE_PATH];
3192 snprintf (path, sizeof(path), "sys/class/graphics/fb%d/dyn_pu", fbNum);
3193 int fd = open(path, O_RDONLY);
3194 if(fd < 0) {
3195 ALOGE("%s: Failed to open sysfd node: %s", __FUNCTION__, path);
3196 return -1;
3197 }
3198 char value[4];
3199 ssize_t size_read = read(fd, value, sizeof(value)-1);
3200 if(size_read <= 0) {
3201 ALOGE("%s: Failed to read sysfd node: %s", __FUNCTION__, path);
3202 close(fd);
3203 return -1;
3204 }
3205 close(fd);
3206 value[size_read] = '\0';
3207 return atoi(value);
3208}
3209
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003210int MDPComp::setPartialUpdatePref(hwc_context_t *ctx, bool enable) {
3211 Locker::Autolock _l(ctx->mDrawLock);
3212 const int fbNum = Overlay::getFbForDpy(Overlay::DPY_PRIMARY);
3213 char path[MAX_SYSFS_FILE_PATH];
3214 snprintf (path, sizeof(path), "sys/class/graphics/fb%d/dyn_pu", fbNum);
3215 int fd = open(path, O_WRONLY);
3216 if(fd < 0) {
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -08003217 ALOGE("%s: Failed to open sysfd node: %s", __FUNCTION__, path);
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003218 return -1;
3219 }
3220 char value[4];
3221 snprintf(value, sizeof(value), "%d", (int)enable);
3222 ssize_t ret = write(fd, value, strlen(value));
3223 if(ret <= 0) {
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -08003224 ALOGE("%s: Failed to write to sysfd nodes: %s", __FUNCTION__, path);
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003225 close(fd);
3226 return -1;
3227 }
3228 close(fd);
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003229 return 0;
3230}
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08003231
3232bool MDPComp::loadPerfLib() {
3233 char perfLibPath[PROPERTY_VALUE_MAX] = {0};
3234 bool success = false;
3235 if((property_get("ro.vendor.extension_library", perfLibPath, NULL) <= 0)) {
3236 ALOGE("vendor library not set in ro.vendor.extension_library");
3237 return false;
3238 }
3239
3240 sLibPerfHint = dlopen(perfLibPath, RTLD_NOW);
3241 if(sLibPerfHint) {
3242 *(void **)&sPerfLockAcquire = dlsym(sLibPerfHint, "perf_lock_acq");
3243 *(void **)&sPerfLockRelease = dlsym(sLibPerfHint, "perf_lock_rel");
3244 if (!sPerfLockAcquire || !sPerfLockRelease) {
3245 ALOGE("Failed to load symbols for perfLock");
3246 dlclose(sLibPerfHint);
3247 sLibPerfHint = NULL;
3248 return false;
3249 }
3250 success = true;
3251 ALOGI("Successfully Loaded perf hint API's");
3252 } else {
3253 ALOGE("Failed to open %s : %s", perfLibPath, dlerror());
3254 }
3255 return success;
3256}
3257
3258void MDPComp::setPerfHint(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
3259 if ((sPerfHintWindow < 0) || mDpy || !sLibPerfHint) {
3260 return;
3261 }
3262 static int count = sPerfHintWindow;
3263 static int perflockFlag = 0;
3264
3265 /* Send hint to mpctl when single layer is updated
3266 * for a successful number of windows. Hint release
3267 * happens immediately upon multiple layer update.
3268 */
3269 if (onlyVideosUpdating(ctx, list)) {
3270 if(count) {
3271 count--;
3272 }
3273 } else {
3274 if (perflockFlag) {
3275 perflockFlag = 0;
3276 sPerfLockRelease(sPerfLockHandle);
3277 }
3278 count = sPerfHintWindow;
3279 }
3280 if (count == 0 && !perflockFlag) {
3281 int perfHint = 0x4501; // 45-display layer hint, 01-Enable
3282 sPerfLockHandle = sPerfLockAcquire(0 /*handle*/, 0/*duration*/,
3283 &perfHint, sizeof(perfHint)/sizeof(int));
Arun Kumar K.R8b927022015-02-24 12:34:21 -08003284 if(sPerfLockHandle > 0) {
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08003285 perflockFlag = 1;
3286 }
3287 }
3288}
3289
Naseer Ahmed7c958d42012-07-31 18:57:03 -07003290}; //namespace
3291