blob: 77d52dc5d54c0258406acbf45ec886f87fd6680c [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;
Raj Kamal83605462015-05-27 11:30:16 +0530558 } else if (ctx->isDMAStateChanging) {
559 // Bail out if a padding round has been invoked in order to switch DMA
560 // state to block mode. We need this to cater for the case when a layer
561 // requires rotation in the current frame.
562 ALOGD_IF(isDebug(), "%s: padding round invoked to switch DMA state",
563 __FUNCTION__);
564 ret = false;
Saurabh Shah19740d02015-04-10 10:05:42 -0700565 } else if(ctx->mVideoTransFlag && isSecondaryConnected(ctx)) {
Saurabh Shahd4e65852013-06-17 11:33:53 -0700566 //1 Padding round to shift pipes across mixers
567 ALOGD_IF(isDebug(),"%s: MDP Comp. video transition padding round",
568 __FUNCTION__);
569 ret = false;
Raj Kamalc0d34242015-03-17 20:53:14 +0530570 } else if((qdutils::MDPVersion::getInstance().is8x26() ||
571 qdutils::MDPVersion::getInstance().is8x16() ||
Prabhanjan Kandulafc541b32015-03-30 20:56:16 +0530572 qdutils::MDPVersion::getInstance().is8x39() ||
573 qdutils::MDPVersion::getInstance().is8x52()) &&
Raj Kamalc0d34242015-03-17 20:53:14 +0530574 !mDpy && isSecondaryAnimating(ctx) &&
575 isYuvPresent(ctx,HWC_DISPLAY_VIRTUAL)) {
576 ALOGD_IF(isDebug(),"%s: Display animation in progress",
577 __FUNCTION__);
578 ret = false;
Ramkumar Radhakrishnanf26fe9e2014-09-09 13:47:54 -0700579 } else if(qdutils::MDPVersion::getInstance().getTotalPipes() < 8) {
580 /* TODO: freeing up all the resources only for the targets having total
581 number of pipes < 8. Need to analyze number of VIG pipes used
582 for primary in previous draw cycle and accordingly decide
583 whether to fall back to full GPU comp or video only comp
584 */
585 if(isSecondaryConfiguring(ctx)) {
586 ALOGD_IF( isDebug(),"%s: External Display connection is pending",
587 __FUNCTION__);
588 ret = false;
589 } else if(ctx->isPaddingRound) {
590 ALOGD_IF(isDebug(), "%s: padding round invoked for dpy %d",
591 __FUNCTION__,mDpy);
592 ret = false;
593 }
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
Praveena Pachipulusu1c5431e2015-05-29 19:38:30 +05302184 // Reset refresh rate
2185 setRefreshRate(ctx, mDpy, ctx->dpyAttr[mDpy].refreshRate);
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302186#endif
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002187 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002188 return -1;
2189 }
2190
Ramkumar Radhakrishnana70981a2013-08-28 11:33:53 -07002191 // Detect the start of animation and fall back to GPU only once to cache
2192 // all the layers in FB and display FB content untill animation completes.
2193 if(ctx->listStats[mDpy].isDisplayAnimating) {
2194 mCurrentFrame.needsRedraw = false;
2195 if(ctx->mAnimationState[mDpy] == ANIMATION_STOPPED) {
2196 mCurrentFrame.needsRedraw = true;
2197 ctx->mAnimationState[mDpy] = ANIMATION_STARTED;
2198 }
2199 setMDPCompLayerFlags(ctx, list);
2200 mCachedFrame.updateCounts(mCurrentFrame);
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302201#ifdef DYNAMIC_FPS
Praveena Pachipulusu1c5431e2015-05-29 19:38:30 +05302202 // Reset refresh rate
2203 setRefreshRate(ctx, mDpy, ctx->dpyAttr[mDpy].refreshRate);
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302204#endif
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002205 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Ramkumar Radhakrishnana70981a2013-08-28 11:33:53 -07002206 ret = -1;
2207 return ret;
2208 } else {
2209 ctx->mAnimationState[mDpy] = ANIMATION_STOPPED;
2210 }
2211
Raj Kamalfdfdddf2015-03-16 21:59:25 +05302212 if(!mDpy and !isSecondaryConnected(ctx) and !mPrevModeOn and
2213 mCachedFrame.isSameFrame(ctx,mDpy,list)) {
2214
2215 ALOGD_IF(isDebug(),"%s: Avoid new composition",__FUNCTION__);
2216 mCurrentFrame.needsRedraw = false;
2217 setMDPCompLayerFlags(ctx, list);
2218 mCachedFrame.updateCounts(mCurrentFrame);
2219#ifdef DYNAMIC_FPS
2220 setDynRefreshRate(ctx, list);
2221#endif
2222 return -1;
2223
2224 }
2225
Saurabh Shahb39f8152013-08-22 10:21:44 -07002226 //Hard conditions, if not met, cannot do MDP comp
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002227 if(isFrameDoable(ctx)) {
2228 generateROI(ctx, list);
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07002229 // if AIV Video mode is enabled, drop all non AIV layers from the
2230 // external display list.
2231 if(ctx->listStats[mDpy].mAIVVideoMode) {
2232 dropNonAIVLayers(ctx, list);
2233 }
Saurabh Shahb39f8152013-08-22 10:21:44 -07002234
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002235 // Configure the cursor if present
2236 int topIndex = ctx->listStats[mDpy].numAppLayers - 1;
2237 if(ctx->listStats[mDpy].cursorLayerPresent &&
2238 validForCursor(ctx, mDpy, &(list->hwLayers[topIndex]))) {
2239 if(configHwCursor(ctx->dpyAttr[mDpy].fd, mDpy,
2240 &(list->hwLayers[topIndex]))) {
2241 // As cursor is configured, mark that layer as dropped, so that
2242 // it wont be considered for composition by other strategies.
2243 mCurrentFrame.hwCursorIndex = topIndex;
2244 mCurrentFrame.drop[topIndex] = true;
2245 mCurrentFrame.dropCount++;
2246 }
2247 } else {
2248 // Release the hw cursor
2249 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
2250 }
2251
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07002252 // if tryFullFrame fails, try to push all video and secure RGB layers
2253 // to MDP for composition.
2254 mModeOn = tryFullFrame(ctx, list) || tryMDPOnlyLayers(ctx, list) ||
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07002255 tryVideoOnly(ctx, list);
Raj Kamal4393eaa2014-06-06 13:45:20 +05302256 if(mModeOn) {
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002257 setMDPCompLayerFlags(ctx, list);
2258 } else {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08002259 resetROI(ctx, mDpy);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002260 reset(ctx);
2261 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
2262 mCurrentFrame.dropCount = 0;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002263 // Check if cursor is in use for primary and mark accordingly
2264 if(!mDpy && HWCursor::getInstance()->isCursorSet()) {
2265 int topIndex = ctx->listStats[mDpy].numAppLayers - 1;
2266 hwc_layer_1_t *layer = &(list->hwLayers[topIndex]);
2267 layer->compositionType = HWC_CURSOR_OVERLAY;
2268 }
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002269 ret = -1;
Saurabh Shah286cf122014-09-08 14:13:08 -07002270 ALOGE_IF(sSimulationFlags && (mDpy == HWC_DISPLAY_PRIMARY),
2271 "MDP Composition Strategies Failed");
Saurabh Shahb39f8152013-08-22 10:21:44 -07002272 }
2273 } else {
Dileep Kumar Reddi4070e932014-09-30 09:00:57 +05302274 if ((ctx->mMDP.version == qdutils::MDP_V3_0_5) && ctx->mCopyBit[mDpy] &&
2275 enablePartialUpdateForMDP3) {
2276 generateROI(ctx, list);
2277 for(int i = 0; i < ctx->listStats[mDpy].numAppLayers; i++) {
2278 ctx->copybitDrop[i] = mCurrentFrame.drop[i];
2279 }
2280 }
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002281 ALOGD_IF( isDebug(),"%s: MDP Comp not possible for this frame",
2282 __FUNCTION__);
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002283 // Release the hw cursor
2284 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002285 ret = -1;
Saurabh Shahb39f8152013-08-22 10:21:44 -07002286 }
Saurabh Shahb39f8152013-08-22 10:21:44 -07002287
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002288 if(isDebug()) {
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002289 ALOGD("GEOMETRY change: %d",
2290 (list->flags & HWC_GEOMETRY_CHANGED));
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002291 android::String8 sDump("");
Jeykumar Sankaran6850ac62014-05-27 10:07:26 -07002292 dump(sDump, ctx);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002293 ALOGD("%s",sDump.string());
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002294 }
2295
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07002296#ifdef DYNAMIC_FPS
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302297 setDynRefreshRate(ctx, list);
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07002298#endif
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08002299 setPerfHint(ctx, list);
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07002300
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002301 mCachedFrame.cacheAll(list);
2302 mCachedFrame.updateCounts(mCurrentFrame);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002303 return ret;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002304}
2305
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002306bool MDPComp::allocSplitVGPipes(hwc_context_t *ctx, int index) {
radhakrishnac9a67412013-09-25 17:40:42 +05302307
2308 bool bRet = true;
radhakrishnac9a67412013-09-25 17:40:42 +05302309 int mdpIndex = mCurrentFrame.layerToMDP[index];
2310 PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
2311 info.pipeInfo = new MdpYUVPipeInfo;
2312 info.rot = NULL;
2313 MdpYUVPipeInfo& pipe_info = *(MdpYUVPipeInfo*)info.pipeInfo;
radhakrishnac9a67412013-09-25 17:40:42 +05302314
2315 pipe_info.lIndex = ovutils::OV_INVALID;
2316 pipe_info.rIndex = ovutils::OV_INVALID;
2317
Saurabh Shahc62f3982014-03-05 14:28:26 -08002318 Overlay::PipeSpecs pipeSpecs;
2319 pipeSpecs.formatClass = Overlay::FORMAT_YUV;
2320 pipeSpecs.needsScaling = true;
2321 pipeSpecs.dpy = mDpy;
2322 pipeSpecs.fb = false;
2323
2324 pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
radhakrishnac9a67412013-09-25 17:40:42 +05302325 if(pipe_info.lIndex == ovutils::OV_INVALID){
2326 bRet = false;
2327 ALOGD_IF(isDebug(),"%s: allocating first VG pipe failed",
2328 __FUNCTION__);
2329 }
Saurabh Shahc62f3982014-03-05 14:28:26 -08002330 pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
radhakrishnac9a67412013-09-25 17:40:42 +05302331 if(pipe_info.rIndex == ovutils::OV_INVALID){
2332 bRet = false;
2333 ALOGD_IF(isDebug(),"%s: allocating second VG pipe failed",
2334 __FUNCTION__);
2335 }
2336 return bRet;
2337}
Sushil Chauhandefd3522014-05-13 18:17:12 -07002338
2339int MDPComp::drawOverlap(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
2340 int fd = -1;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002341 if (ctx->mPtorInfo.isActive()) {
2342 fd = ctx->mCopyBit[mDpy]->drawOverlap(ctx, list);
Sushil Chauhandefd3522014-05-13 18:17:12 -07002343 if (fd < 0) {
2344 ALOGD_IF(isDebug(),"%s: failed", __FUNCTION__);
Sushil Chauhandefd3522014-05-13 18:17:12 -07002345 }
2346 }
2347 return fd;
2348}
Arun Kumar K.R2aa44c62014-01-21 23:08:28 -08002349//=============MDPCompNonSplit==================================================
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002350
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002351void MDPCompNonSplit::adjustForSourceSplit(hwc_context_t *ctx,
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302352 hwc_display_contents_1_t* list) {
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002353 //If 4k2k Yuv layer split is possible, and if
2354 //fbz is above 4k2k layer, increment fb zorder by 1
2355 //as we split 4k2k layer and increment zorder for right half
2356 //of the layer
Shalaj Jaina70b4352014-06-15 13:47:47 -07002357 if(!ctx)
2358 return;
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002359 if(mCurrentFrame.fbZ >= 0) {
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302360 for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
2361 index++) {
2362 if(!mCurrentFrame.isFBComposed[index]) {
2363 if(mdpNextZOrder == mCurrentFrame.fbZ) {
2364 mdpNextZOrder++;
2365 }
2366 mdpNextZOrder++;
2367 hwc_layer_1_t* layer = &list->hwLayers[index];
2368 private_handle_t *hnd = (private_handle_t *)layer->handle;
Raj Kamal389d6e32014-08-04 14:43:24 +05302369 if(isYUVSplitNeeded(hnd)) {
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302370 if(mdpNextZOrder <= mCurrentFrame.fbZ)
2371 mCurrentFrame.fbZ += 1;
2372 mdpNextZOrder++;
2373 //As we split 4kx2k yuv layer and program to 2 VG pipes
2374 //(if available) increase mdpcount by 1.
2375 mCurrentFrame.mdpCount++;
2376 }
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002377 }
2378 }
2379 }
radhakrishnac9a67412013-09-25 17:40:42 +05302380}
2381
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002382/*
2383 * Configures pipe(s) for MDP composition
2384 */
Saurabh Shah88e4d272013-09-03 13:31:29 -07002385int MDPCompNonSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002386 PipeLayerPair& PipeLayerPair) {
Saurabh Shah88e4d272013-09-03 13:31:29 -07002387 MdpPipeInfoNonSplit& mdp_info =
2388 *(static_cast<MdpPipeInfoNonSplit*>(PipeLayerPair.pipeInfo));
Justin Philipd6166602014-08-12 13:42:21 +05302389 eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shahacf10202013-02-26 10:15:15 -08002390 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Saurabh Shahacf10202013-02-26 10:15:15 -08002391 eDest dest = mdp_info.index;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002392
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002393 ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipe: %d",
2394 __FUNCTION__, layer, zOrder, dest);
2395
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002396 return configureNonSplit(ctx, layer, mDpy, mdpFlags, zOrder, dest,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002397 &PipeLayerPair.rot);
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002398}
2399
Saurabh Shah88e4d272013-09-03 13:31:29 -07002400bool MDPCompNonSplit::allocLayerPipes(hwc_context_t *ctx,
Saurabh Shahe51f8ca2013-05-06 17:26:16 -07002401 hwc_display_contents_1_t* list) {
Saurabh Shah8cc77712015-03-31 10:48:51 -07002402 for(uint32_t formatType = FORMAT_YUV; formatType < FORMAT_MAX;
2403 formatType++) {
2404 for(int index = 0; index < mCurrentFrame.layerCount; index++) {
2405 if(mCurrentFrame.isFBComposed[index]) continue;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002406
Saurabh Shah8cc77712015-03-31 10:48:51 -07002407 hwc_layer_1_t* layer = &list->hwLayers[index];
2408 private_handle_t *hnd = (private_handle_t *)layer->handle;
2409 if(formatType == FORMAT_YUV && !isYuvBuffer(hnd))
radhakrishnac9a67412013-09-25 17:40:42 +05302410 continue;
Saurabh Shah8cc77712015-03-31 10:48:51 -07002411 if(formatType == FORMAT_RGB && isYuvBuffer(hnd))
2412 continue;
2413
2414 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
2415 if(allocSplitVGPipes(ctx, index)){
2416 continue;
2417 }
radhakrishnac9a67412013-09-25 17:40:42 +05302418 }
radhakrishnac9a67412013-09-25 17:40:42 +05302419
Saurabh Shah8cc77712015-03-31 10:48:51 -07002420 int mdpIndex = mCurrentFrame.layerToMDP[index];
2421 PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
2422 info.pipeInfo = new MdpPipeInfoNonSplit;
2423 info.rot = NULL;
2424 MdpPipeInfoNonSplit& pipe_info =
2425 *(MdpPipeInfoNonSplit*)info.pipeInfo;
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -08002426
Saurabh Shah8cc77712015-03-31 10:48:51 -07002427 Overlay::PipeSpecs pipeSpecs;
2428 pipeSpecs.formatClass = isYuvBuffer(hnd) ?
2429 Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
2430 pipeSpecs.needsScaling = qhwc::needsScaling(layer) or
2431 (qdutils::MDPVersion::getInstance().is8x26() and
2432 ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres > 1024);
2433 pipeSpecs.dpy = mDpy;
2434 pipeSpecs.fb = false;
2435 pipeSpecs.numActiveDisplays = ctx->numActiveDisplays;
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -08002436
Saurabh Shah8cc77712015-03-31 10:48:51 -07002437 pipe_info.index = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahc62f3982014-03-05 14:28:26 -08002438
Saurabh Shah8cc77712015-03-31 10:48:51 -07002439 if(pipe_info.index == ovutils::OV_INVALID) {
2440 ALOGD_IF(isDebug(), "%s: Unable to get pipe for layer %d of "\
2441 "format type %d", __FUNCTION__, index, formatType);
2442 return false;
2443 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002444 }
2445 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002446 return true;
2447}
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002448
radhakrishnac9a67412013-09-25 17:40:42 +05302449int MDPCompNonSplit::configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
2450 PipeLayerPair& PipeLayerPair) {
2451 MdpYUVPipeInfo& mdp_info =
2452 *(static_cast<MdpYUVPipeInfo*>(PipeLayerPair.pipeInfo));
2453 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Justin Philipd6166602014-08-12 13:42:21 +05302454 eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
radhakrishnac9a67412013-09-25 17:40:42 +05302455 eDest lDest = mdp_info.lIndex;
2456 eDest rDest = mdp_info.rIndex;
2457
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002458 return configureSourceSplit(ctx, layer, mDpy, mdpFlagsL, zOrder,
radhakrishnac9a67412013-09-25 17:40:42 +05302459 lDest, rDest, &PipeLayerPair.rot);
2460}
2461
Saurabh Shah88e4d272013-09-03 13:31:29 -07002462bool MDPCompNonSplit::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002463
Raj Kamal4393eaa2014-06-06 13:45:20 +05302464 if(!isEnabled() or !mModeOn) {
2465 ALOGD_IF(isDebug(),"%s: MDP Comp not enabled/configured", __FUNCTION__);
Prabhanjan Kandula08222fc2013-07-10 17:20:59 +05302466 return true;
2467 }
2468
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002469 overlay::Overlay& ov = *ctx->mOverlay;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002470 LayerProp *layerProp = ctx->layerProp[mDpy];
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002471
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002472 int numHwLayers = ctx->listStats[mDpy].numAppLayers;
2473 for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ )
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002474 {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002475 if(mCurrentFrame.isFBComposed[i]) continue;
2476
Naseer Ahmed5b6708a2012-08-02 13:46:08 -07002477 hwc_layer_1_t *layer = &list->hwLayers[i];
Saurabh Shahacf10202013-02-26 10:15:15 -08002478 private_handle_t *hnd = (private_handle_t *)layer->handle;
2479 if(!hnd) {
Sushil Chauhan897a9c32013-07-18 11:09:55 -07002480 if (!(layer->flags & HWC_COLOR_FILL)) {
2481 ALOGE("%s handle null", __FUNCTION__);
2482 return false;
2483 }
2484 // No PLAY for Color layer
2485 layerProp[i].mFlags &= ~HWC_MDPCOMP;
2486 continue;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002487 }
2488
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002489 int mdpIndex = mCurrentFrame.layerToMDP[i];
2490
Raj Kamal389d6e32014-08-04 14:43:24 +05302491 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit)
radhakrishnac9a67412013-09-25 17:40:42 +05302492 {
2493 MdpYUVPipeInfo& pipe_info =
2494 *(MdpYUVPipeInfo*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
2495 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
2496 ovutils::eDest indexL = pipe_info.lIndex;
2497 ovutils::eDest indexR = pipe_info.rIndex;
2498 int fd = hnd->fd;
Praveena Pachipulusud9443c72014-02-17 10:42:28 +05302499 uint32_t offset = (uint32_t)hnd->offset;
radhakrishnac9a67412013-09-25 17:40:42 +05302500 if(rot) {
2501 rot->queueBuffer(fd, offset);
2502 fd = rot->getDstMemId();
2503 offset = rot->getDstOffset();
2504 }
2505 if(indexL != ovutils::OV_INVALID) {
2506 ovutils::eDest destL = (ovutils::eDest)indexL;
2507 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2508 using pipe: %d", __FUNCTION__, layer, hnd, indexL );
2509 if (!ov.queueBuffer(fd, offset, destL)) {
2510 ALOGE("%s: queueBuffer failed for display:%d",
2511 __FUNCTION__, mDpy);
2512 return false;
2513 }
2514 }
2515
2516 if(indexR != ovutils::OV_INVALID) {
2517 ovutils::eDest destR = (ovutils::eDest)indexR;
2518 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2519 using pipe: %d", __FUNCTION__, layer, hnd, indexR );
2520 if (!ov.queueBuffer(fd, offset, destR)) {
2521 ALOGE("%s: queueBuffer failed for display:%d",
2522 __FUNCTION__, mDpy);
2523 return false;
2524 }
2525 }
2526 }
2527 else{
2528 MdpPipeInfoNonSplit& pipe_info =
Saurabh Shah88e4d272013-09-03 13:31:29 -07002529 *(MdpPipeInfoNonSplit*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
radhakrishnac9a67412013-09-25 17:40:42 +05302530 ovutils::eDest dest = pipe_info.index;
2531 if(dest == ovutils::OV_INVALID) {
2532 ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, dest);
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002533 return false;
radhakrishnac9a67412013-09-25 17:40:42 +05302534 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002535
radhakrishnac9a67412013-09-25 17:40:42 +05302536 if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
2537 continue;
2538 }
2539
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002540 int fd = hnd->fd;
2541 uint32_t offset = (uint32_t)hnd->offset;
2542 int index = ctx->mPtorInfo.getPTORArrayIndex(i);
2543 if (!mDpy && (index != -1)) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07002544 hnd = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002545 fd = hnd->fd;
Sushil Chauhan875a92e2014-07-25 12:20:23 -07002546 offset = 0;
Sushil Chauhandefd3522014-05-13 18:17:12 -07002547 }
2548
radhakrishnac9a67412013-09-25 17:40:42 +05302549 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2550 using pipe: %d", __FUNCTION__, layer,
2551 hnd, dest );
2552
radhakrishnac9a67412013-09-25 17:40:42 +05302553 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
2554 if(rot) {
2555 if(!rot->queueBuffer(fd, offset))
2556 return false;
2557 fd = rot->getDstMemId();
2558 offset = rot->getDstOffset();
2559 }
2560
2561 if (!ov.queueBuffer(fd, offset, dest)) {
2562 ALOGE("%s: queueBuffer failed for display:%d ",
2563 __FUNCTION__, mDpy);
2564 return false;
2565 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002566 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002567
2568 layerProp[i].mFlags &= ~HWC_MDPCOMP;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002569 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002570 return true;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002571}
2572
Saurabh Shah88e4d272013-09-03 13:31:29 -07002573//=============MDPCompSplit===================================================
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002574
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002575void MDPCompSplit::adjustForSourceSplit(hwc_context_t *ctx,
radhakrishnac9a67412013-09-25 17:40:42 +05302576 hwc_display_contents_1_t* list){
2577 //if 4kx2k yuv layer is totally present in either in left half
2578 //or right half then try splitting the yuv layer to avoid decimation
radhakrishnac9a67412013-09-25 17:40:42 +05302579 const int lSplit = getLeftSplit(ctx, mDpy);
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302580 if(mCurrentFrame.fbZ >= 0) {
2581 for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
2582 index++) {
2583 if(!mCurrentFrame.isFBComposed[index]) {
2584 if(mdpNextZOrder == mCurrentFrame.fbZ) {
2585 mdpNextZOrder++;
2586 }
2587 mdpNextZOrder++;
2588 hwc_layer_1_t* layer = &list->hwLayers[index];
2589 private_handle_t *hnd = (private_handle_t *)layer->handle;
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002590 if(isYUVSplitNeeded(hnd) ||
2591 (needs3DComposition(ctx,mDpy) &&
2592 get3DFormat(hnd) != HAL_NO_3D)) {
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302593 hwc_rect_t dst = layer->displayFrame;
2594 if((dst.left > lSplit) || (dst.right < lSplit)) {
2595 mCurrentFrame.mdpCount += 1;
2596 }
2597 if(mdpNextZOrder <= mCurrentFrame.fbZ)
2598 mCurrentFrame.fbZ += 1;
2599 mdpNextZOrder++;
2600 }
2601 }
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002602 }
radhakrishnac9a67412013-09-25 17:40:42 +05302603 }
2604}
2605
Saurabh Shah88e4d272013-09-03 13:31:29 -07002606bool MDPCompSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
Saurabh Shahc62f3982014-03-05 14:28:26 -08002607 MdpPipeInfoSplit& pipe_info) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002608
Saurabh Shahc62f3982014-03-05 14:28:26 -08002609 const int lSplit = getLeftSplit(ctx, mDpy);
2610 private_handle_t *hnd = (private_handle_t *)layer->handle;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002611 hwc_rect_t dst = layer->displayFrame;
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002612 pipe_info.lIndex = ovutils::OV_INVALID;
2613 pipe_info.rIndex = ovutils::OV_INVALID;
2614
Saurabh Shahc62f3982014-03-05 14:28:26 -08002615 Overlay::PipeSpecs pipeSpecs;
2616 pipeSpecs.formatClass = isYuvBuffer(hnd) ?
2617 Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
2618 pipeSpecs.needsScaling = qhwc::needsScalingWithSplit(ctx, layer, mDpy);
2619 pipeSpecs.dpy = mDpy;
2620 pipeSpecs.mixer = Overlay::MIXER_LEFT;
2621 pipeSpecs.fb = false;
2622
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08002623 // Acquire pipe only for the updating half
2624 hwc_rect_t l_roi = ctx->listStats[mDpy].lRoi;
2625 hwc_rect_t r_roi = ctx->listStats[mDpy].rRoi;
2626
2627 if (dst.left < lSplit && isValidRect(getIntersection(dst, l_roi))) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002628 pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002629 if(pipe_info.lIndex == ovutils::OV_INVALID)
2630 return false;
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002631 }
2632
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08002633 if(dst.right > lSplit && isValidRect(getIntersection(dst, r_roi))) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002634 pipeSpecs.mixer = Overlay::MIXER_RIGHT;
2635 pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002636 if(pipe_info.rIndex == ovutils::OV_INVALID)
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002637 return false;
2638 }
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002639
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002640 return true;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002641}
2642
Saurabh Shah88e4d272013-09-03 13:31:29 -07002643bool MDPCompSplit::allocLayerPipes(hwc_context_t *ctx,
Saurabh Shahe51f8ca2013-05-06 17:26:16 -07002644 hwc_display_contents_1_t* list) {
Saurabh Shah8cc77712015-03-31 10:48:51 -07002645 for(uint32_t formatType = FORMAT_YUV; formatType < FORMAT_MAX;
2646 formatType++) {
2647 for(int index = 0 ; index < mCurrentFrame.layerCount; index++) {
2648 if(mCurrentFrame.isFBComposed[index]) continue;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002649
Saurabh Shah8cc77712015-03-31 10:48:51 -07002650 hwc_layer_1_t* layer = &list->hwLayers[index];
2651 private_handle_t *hnd = (private_handle_t *)layer->handle;
2652 if(formatType == FORMAT_YUV && !isYuvBuffer(hnd))
2653 continue;
2654 if(formatType == FORMAT_RGB && isYuvBuffer(hnd))
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002655 continue;
2656
Saurabh Shah8cc77712015-03-31 10:48:51 -07002657 hwc_rect_t dst = layer->displayFrame;
2658 const int lSplit = getLeftSplit(ctx, mDpy);
2659 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
2660 if((dst.left > lSplit)||(dst.right < lSplit)){
2661 if(allocSplitVGPipes(ctx, index)){
2662 continue;
2663 }
2664 }
2665 }
2666 //XXX: Check for forced 2D composition
2667 if(needs3DComposition(ctx, mDpy) && get3DFormat(hnd) != HAL_NO_3D)
2668 if(allocSplitVGPipes(ctx,index))
2669 continue;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002670
Saurabh Shah8cc77712015-03-31 10:48:51 -07002671 int mdpIndex = mCurrentFrame.layerToMDP[index];
2672 PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
2673 info.pipeInfo = new MdpPipeInfoSplit;
2674 info.rot = NULL;
2675 MdpPipeInfoSplit& pipe_info = *(MdpPipeInfoSplit*)info.pipeInfo;
2676
2677 if(!acquireMDPPipes(ctx, layer, pipe_info)) {
2678 ALOGD_IF(isDebug(), "%s: Unable to get pipe for layer %d of "\
2679 "format type %d", __FUNCTION__, index, formatType);
2680 return false;
2681 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002682 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002683 }
2684 return true;
2685}
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002686
radhakrishnac9a67412013-09-25 17:40:42 +05302687int MDPCompSplit::configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
2688 PipeLayerPair& PipeLayerPair) {
2689 const int lSplit = getLeftSplit(ctx, mDpy);
2690 hwc_rect_t dst = layer->displayFrame;
2691 if((dst.left > lSplit)||(dst.right < lSplit)){
2692 MdpYUVPipeInfo& mdp_info =
2693 *(static_cast<MdpYUVPipeInfo*>(PipeLayerPair.pipeInfo));
2694 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Justin Philipd6166602014-08-12 13:42:21 +05302695 eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
radhakrishnac9a67412013-09-25 17:40:42 +05302696 eDest lDest = mdp_info.lIndex;
2697 eDest rDest = mdp_info.rIndex;
2698
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002699 return configureSourceSplit(ctx, layer, mDpy, mdpFlagsL, zOrder,
radhakrishnac9a67412013-09-25 17:40:42 +05302700 lDest, rDest, &PipeLayerPair.rot);
2701 }
2702 else{
2703 return configure(ctx, layer, PipeLayerPair);
2704 }
2705}
2706
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002707/*
2708 * Configures pipe(s) for MDP composition
2709 */
Saurabh Shah88e4d272013-09-03 13:31:29 -07002710int MDPCompSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
Saurabh Shah67a38c32013-06-10 16:23:15 -07002711 PipeLayerPair& PipeLayerPair) {
Saurabh Shah88e4d272013-09-03 13:31:29 -07002712 MdpPipeInfoSplit& mdp_info =
2713 *(static_cast<MdpPipeInfoSplit*>(PipeLayerPair.pipeInfo));
Saurabh Shahacf10202013-02-26 10:15:15 -08002714 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Justin Philipd6166602014-08-12 13:42:21 +05302715 eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shahacf10202013-02-26 10:15:15 -08002716 eDest lDest = mdp_info.lIndex;
2717 eDest rDest = mdp_info.rIndex;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002718
2719 ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
Jeykumar Sankaran39305802014-12-12 17:55:57 -08002720 "dest_pipeR: %d",__FUNCTION__, layer, zOrder, lDest, rDest);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002721
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002722 return configureSplit(ctx, layer, mDpy, mdpFlagsL, zOrder, lDest,
Jeykumar Sankaran39305802014-12-12 17:55:57 -08002723 rDest, &PipeLayerPair.rot);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002724}
2725
Saurabh Shah88e4d272013-09-03 13:31:29 -07002726bool MDPCompSplit::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002727
Raj Kamal4393eaa2014-06-06 13:45:20 +05302728 if(!isEnabled() or !mModeOn) {
2729 ALOGD_IF(isDebug(),"%s: MDP Comp not enabled/configured", __FUNCTION__);
Prabhanjan Kandula08222fc2013-07-10 17:20:59 +05302730 return true;
2731 }
2732
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002733 overlay::Overlay& ov = *ctx->mOverlay;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002734 LayerProp *layerProp = ctx->layerProp[mDpy];
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002735
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002736 int numHwLayers = ctx->listStats[mDpy].numAppLayers;
2737 for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ )
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002738 {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002739 if(mCurrentFrame.isFBComposed[i]) continue;
2740
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002741 hwc_layer_1_t *layer = &list->hwLayers[i];
Saurabh Shahacf10202013-02-26 10:15:15 -08002742 private_handle_t *hnd = (private_handle_t *)layer->handle;
2743 if(!hnd) {
2744 ALOGE("%s handle null", __FUNCTION__);
2745 return false;
2746 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002747
2748 if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
2749 continue;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002750 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002751
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002752 int mdpIndex = mCurrentFrame.layerToMDP[i];
2753
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002754 if((isYUVSplitNeeded(hnd) && sEnableYUVsplit) ||
2755 (needs3DComposition(ctx, mDpy) && get3DFormat(hnd) != HAL_NO_3D))
radhakrishnac9a67412013-09-25 17:40:42 +05302756 {
2757 MdpYUVPipeInfo& pipe_info =
2758 *(MdpYUVPipeInfo*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
2759 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
2760 ovutils::eDest indexL = pipe_info.lIndex;
2761 ovutils::eDest indexR = pipe_info.rIndex;
2762 int fd = hnd->fd;
Praveena Pachipulusud9443c72014-02-17 10:42:28 +05302763 uint32_t offset = (uint32_t)hnd->offset;
radhakrishnac9a67412013-09-25 17:40:42 +05302764 if(rot) {
2765 rot->queueBuffer(fd, offset);
2766 fd = rot->getDstMemId();
2767 offset = rot->getDstOffset();
2768 }
2769 if(indexL != ovutils::OV_INVALID) {
2770 ovutils::eDest destL = (ovutils::eDest)indexL;
2771 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2772 using pipe: %d", __FUNCTION__, layer, hnd, indexL );
2773 if (!ov.queueBuffer(fd, offset, destL)) {
2774 ALOGE("%s: queueBuffer failed for display:%d",
2775 __FUNCTION__, mDpy);
2776 return false;
2777 }
2778 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002779
radhakrishnac9a67412013-09-25 17:40:42 +05302780 if(indexR != ovutils::OV_INVALID) {
2781 ovutils::eDest destR = (ovutils::eDest)indexR;
2782 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2783 using pipe: %d", __FUNCTION__, layer, hnd, indexR );
2784 if (!ov.queueBuffer(fd, offset, destR)) {
2785 ALOGE("%s: queueBuffer failed for display:%d",
2786 __FUNCTION__, mDpy);
2787 return false;
2788 }
Saurabh Shaha9da08f2013-07-03 13:27:53 -07002789 }
2790 }
radhakrishnac9a67412013-09-25 17:40:42 +05302791 else{
2792 MdpPipeInfoSplit& pipe_info =
2793 *(MdpPipeInfoSplit*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
2794 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
Saurabh Shaha9da08f2013-07-03 13:27:53 -07002795
radhakrishnac9a67412013-09-25 17:40:42 +05302796 ovutils::eDest indexL = pipe_info.lIndex;
2797 ovutils::eDest indexR = pipe_info.rIndex;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002798
radhakrishnac9a67412013-09-25 17:40:42 +05302799 int fd = hnd->fd;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002800 uint32_t offset = (uint32_t)hnd->offset;
2801 int index = ctx->mPtorInfo.getPTORArrayIndex(i);
2802 if (!mDpy && (index != -1)) {
2803 hnd = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
2804 fd = hnd->fd;
Sushil Chauhan875a92e2014-07-25 12:20:23 -07002805 offset = 0;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002806 }
radhakrishnac9a67412013-09-25 17:40:42 +05302807
Tatenda Chipeperekwa88fe6352014-04-14 10:36:06 -07002808 if(ctx->mAD->draw(ctx, fd, offset)) {
2809 fd = ctx->mAD->getDstFd();
2810 offset = ctx->mAD->getDstOffset();
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002811 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002812
radhakrishnac9a67412013-09-25 17:40:42 +05302813 if(rot) {
2814 rot->queueBuffer(fd, offset);
2815 fd = rot->getDstMemId();
2816 offset = rot->getDstOffset();
2817 }
2818
2819 //************* play left mixer **********
2820 if(indexL != ovutils::OV_INVALID) {
2821 ovutils::eDest destL = (ovutils::eDest)indexL;
2822 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2823 using pipe: %d", __FUNCTION__, layer, hnd, indexL );
2824 if (!ov.queueBuffer(fd, offset, destL)) {
2825 ALOGE("%s: queueBuffer failed for left mixer",
2826 __FUNCTION__);
2827 return false;
2828 }
2829 }
2830
2831 //************* play right mixer **********
2832 if(indexR != ovutils::OV_INVALID) {
2833 ovutils::eDest destR = (ovutils::eDest)indexR;
2834 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2835 using pipe: %d", __FUNCTION__, layer, hnd, indexR );
2836 if (!ov.queueBuffer(fd, offset, destR)) {
2837 ALOGE("%s: queueBuffer failed for right mixer",
2838 __FUNCTION__);
2839 return false;
2840 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002841 }
2842 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002843
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002844 layerProp[i].mFlags &= ~HWC_MDPCOMP;
2845 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002846
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002847 return true;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002848}
Saurabh Shahab47c692014-02-12 18:45:57 -08002849
2850//================MDPCompSrcSplit==============================================
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08002851
2852bool MDPCompSrcSplit::validateAndApplyROI(hwc_context_t *ctx,
2853 hwc_display_contents_1_t* list) {
2854 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
2855 hwc_rect_t visibleRect = ctx->listStats[mDpy].lRoi;
2856
2857 for(int i = numAppLayers - 1; i >= 0; i--) {
2858 if(!isValidRect(visibleRect)) {
2859 mCurrentFrame.drop[i] = true;
2860 mCurrentFrame.dropCount++;
2861 continue;
2862 }
2863
2864 const hwc_layer_1_t* layer = &list->hwLayers[i];
2865 hwc_rect_t dstRect = layer->displayFrame;
2866 hwc_rect_t res = getIntersection(visibleRect, dstRect);
2867
2868 if(!isValidRect(res)) {
2869 mCurrentFrame.drop[i] = true;
2870 mCurrentFrame.dropCount++;
2871 } else {
2872 /* Reset frame ROI when any layer which needs scaling also needs ROI
2873 * cropping */
2874 if(!isSameRect(res, dstRect) && needsScaling (layer)) {
2875 ALOGI("%s: Resetting ROI due to scaling", __FUNCTION__);
2876 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
2877 mCurrentFrame.dropCount = 0;
2878 return false;
2879 }
2880
2881 /* deduct any opaque region from visibleRect */
2882 if (layer->blending == HWC_BLENDING_NONE &&
2883 layer->planeAlpha == 0xFF)
2884 visibleRect = deductRect(visibleRect, res);
2885 }
2886 }
2887 return true;
2888}
2889
2890/*
2891 * HW Limitation: ping pong split can always split the ping pong output
2892 * equally across two DSI's. So the ROI programmed should be of equal width
2893 * for both the halves
2894 */
2895void MDPCompSrcSplit::generateROI(hwc_context_t *ctx,
2896 hwc_display_contents_1_t* list) {
2897 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
2898
2899
2900 if(!canPartialUpdate(ctx, list))
2901 return;
2902
2903 struct hwc_rect roi = (struct hwc_rect){0, 0, 0, 0};
2904 hwc_rect fullFrame = (struct hwc_rect) {0, 0,(int)ctx->dpyAttr[mDpy].xres,
2905 (int)ctx->dpyAttr[mDpy].yres};
2906
2907 for(int index = 0; index < numAppLayers; index++ ) {
2908 hwc_layer_1_t* layer = &list->hwLayers[index];
2909
2910 // If we have a RGB layer which needs rotation, no partial update
2911 if(!isYuvBuffer((private_handle_t *)layer->handle) && layer->transform)
2912 return;
2913
2914 if ((mCachedFrame.hnd[index] != layer->handle) ||
2915 isYuvBuffer((private_handle_t *)layer->handle)) {
2916 hwc_rect_t dst = layer->displayFrame;
2917 hwc_rect_t updatingRect = dst;
2918
2919#ifdef QCOM_BSP
2920 if(!needsScaling(layer) && !layer->transform)
2921 {
2922 hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
2923 int x_off = dst.left - src.left;
2924 int y_off = dst.top - src.top;
2925 updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
2926 }
2927#endif
2928
2929 roi = getUnion(roi, updatingRect);
2930 }
2931 }
2932
2933 /* No layer is updating. Still SF wants a refresh.*/
2934 if(!isValidRect(roi))
2935 return;
2936
2937 roi = expandROIFromMidPoint(roi, fullFrame);
2938
2939 hwc_rect lFrame = fullFrame;
2940 lFrame.right /= 2;
2941 hwc_rect lRoi = getIntersection(roi, lFrame);
2942
2943 // Align ROI coordinates to panel restrictions
2944 lRoi = getSanitizeROI(lRoi, lFrame);
2945
2946 hwc_rect rFrame = fullFrame;
2947 rFrame.left = lFrame.right;
2948 hwc_rect rRoi = getIntersection(roi, rFrame);
2949
2950 // Align ROI coordinates to panel restrictions
2951 rRoi = getSanitizeROI(rRoi, rFrame);
2952
2953 roi = getUnion(lRoi, rRoi);
2954
2955 ctx->listStats[mDpy].lRoi = roi;
2956 if(!validateAndApplyROI(ctx, list))
2957 resetROI(ctx, mDpy);
2958
2959 ALOGD_IF(isDebug(),"%s: generated ROI: [%d, %d, %d, %d] [%d, %d, %d, %d]",
2960 __FUNCTION__,
2961 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
2962 ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom,
2963 ctx->listStats[mDpy].rRoi.left, ctx->listStats[mDpy].rRoi.top,
2964 ctx->listStats[mDpy].rRoi.right, ctx->listStats[mDpy].rRoi.bottom);
2965}
2966
Saurabh Shahab47c692014-02-12 18:45:57 -08002967bool MDPCompSrcSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
Saurabh Shahc62f3982014-03-05 14:28:26 -08002968 MdpPipeInfoSplit& pipe_info) {
Saurabh Shahab47c692014-02-12 18:45:57 -08002969 private_handle_t *hnd = (private_handle_t *)layer->handle;
2970 hwc_rect_t dst = layer->displayFrame;
2971 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
2972 pipe_info.lIndex = ovutils::OV_INVALID;
2973 pipe_info.rIndex = ovutils::OV_INVALID;
2974
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08002975 if(qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() && !mDpy)
2976 trimAgainstROI(ctx,crop, dst);
2977
Saurabh Shahab47c692014-02-12 18:45:57 -08002978 //If 2 pipes are staged on a single stage of a mixer, then the left pipe
2979 //should have a higher priority than the right one. Pipe priorities are
2980 //starting with VG0, VG1 ... , RGB0 ..., DMA1
Saurabh Shahab47c692014-02-12 18:45:57 -08002981
Saurabh Shahc62f3982014-03-05 14:28:26 -08002982 Overlay::PipeSpecs pipeSpecs;
2983 pipeSpecs.formatClass = isYuvBuffer(hnd) ?
2984 Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
2985 pipeSpecs.needsScaling = qhwc::needsScaling(layer);
2986 pipeSpecs.dpy = mDpy;
2987 pipeSpecs.fb = false;
2988
Saurabh Shahab47c692014-02-12 18:45:57 -08002989 //1 pipe by default for a layer
Saurabh Shahc62f3982014-03-05 14:28:26 -08002990 pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahab47c692014-02-12 18:45:57 -08002991 if(pipe_info.lIndex == ovutils::OV_INVALID) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002992 return false;
Saurabh Shahab47c692014-02-12 18:45:57 -08002993 }
2994
Saurabh Shahea7a01d2014-05-22 17:45:36 -07002995 /* Use 2 pipes IF
2996 a) Layer's crop width is > 2048 or
2997 b) Layer's dest width > 2048 or
2998 c) On primary, driver has indicated with caps to split always. This is
2999 based on an empirically derived value of panel height. Applied only
3000 if the layer's width is > mixer's width
3001 */
3002
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +05303003 MDPVersion& mdpHw = MDPVersion::getInstance();
Saurabh Shahea7a01d2014-05-22 17:45:36 -07003004 bool primarySplitAlways = (mDpy == HWC_DISPLAY_PRIMARY) and
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +05303005 mdpHw.isSrcSplitAlways();
Saurabh Shah514759d2014-11-11 18:02:24 -08003006 const uint32_t lSplit = getLeftSplit(ctx, mDpy);
3007 const uint32_t dstWidth = dst.right - dst.left;
3008 const uint32_t dstHeight = dst.bottom - dst.top;
Saurabh Shah05f4e222015-02-05 14:36:22 -08003009 uint32_t cropWidth = has90Transform(layer) ? crop.bottom - crop.top :
Saurabh Shah189f23d2014-09-26 17:21:00 -07003010 crop.right - crop.left;
Saurabh Shah05f4e222015-02-05 14:36:22 -08003011 uint32_t cropHeight = has90Transform(layer) ? crop.right - crop.left :
Saurabh Shah514759d2014-11-11 18:02:24 -08003012 crop.bottom - crop.top;
3013 //Approximation to actual clock, ignoring the common factors in pipe and
3014 //mixer cases like line_time
3015 const uint32_t layerClock = getLayerClock(dstWidth, dstHeight, cropHeight);
3016 const uint32_t mixerClock = lSplit;
Saurabh Shahea7a01d2014-05-22 17:45:36 -07003017
Saurabh Shah05f4e222015-02-05 14:36:22 -08003018 const uint32_t downscale = getRotDownscale(ctx, layer);
3019 if(downscale) {
3020 cropWidth /= downscale;
3021 cropHeight /= downscale;
3022 }
3023
Jeykumar Sankaran39305802014-12-12 17:55:57 -08003024 if(dstWidth > mdpHw.getMaxPipeWidth() or
3025 cropWidth > mdpHw.getMaxPipeWidth() or
Saurabh Shah514759d2014-11-11 18:02:24 -08003026 (primarySplitAlways and
3027 (cropWidth > lSplit or layerClock > mixerClock))) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08003028 pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahab47c692014-02-12 18:45:57 -08003029 if(pipe_info.rIndex == ovutils::OV_INVALID) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08003030 return false;
Saurabh Shahdd8237a2014-02-28 14:29:09 -08003031 }
3032
Jeykumar Sankaran89e23ab2015-01-28 15:57:46 -08003033 if(ctx->mOverlay->needsPrioritySwap(pipe_info.lIndex,
3034 pipe_info.rIndex)) {
Saurabh Shahdd8237a2014-02-28 14:29:09 -08003035 qhwc::swap(pipe_info.lIndex, pipe_info.rIndex);
Saurabh Shahab47c692014-02-12 18:45:57 -08003036 }
3037 }
3038
3039 return true;
3040}
3041
Saurabh Shahab47c692014-02-12 18:45:57 -08003042int MDPCompSrcSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
3043 PipeLayerPair& PipeLayerPair) {
3044 private_handle_t *hnd = (private_handle_t *)layer->handle;
3045 if(!hnd) {
3046 ALOGE("%s: layer handle is NULL", __FUNCTION__);
3047 return -1;
3048 }
3049 MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
3050 MdpPipeInfoSplit& mdp_info =
3051 *(static_cast<MdpPipeInfoSplit*>(PipeLayerPair.pipeInfo));
3052 Rotator **rot = &PipeLayerPair.rot;
3053 eZorder z = static_cast<eZorder>(mdp_info.zOrder);
Saurabh Shahab47c692014-02-12 18:45:57 -08003054 eDest lDest = mdp_info.lIndex;
3055 eDest rDest = mdp_info.rIndex;
3056 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
3057 hwc_rect_t dst = layer->displayFrame;
3058 int transform = layer->transform;
3059 eTransform orient = static_cast<eTransform>(transform);
Saurabh Shahab47c692014-02-12 18:45:57 -08003060 int rotFlags = ROT_FLAGS_NONE;
Sushil Chauhan65e26302015-01-14 10:48:57 -08003061 uint32_t format = ovutils::getMdpFormat(hnd->format, hnd->flags);
Saurabh Shahab47c692014-02-12 18:45:57 -08003062 Whf whf(getWidth(hnd), getHeight(hnd), format, hnd->size);
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05003063 eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shahab47c692014-02-12 18:45:57 -08003064
3065 ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
3066 "dest_pipeR: %d",__FUNCTION__, layer, z, lDest, rDest);
3067
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08003068 if(qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() && !mDpy) {
3069 /* MDP driver crops layer coordinates against ROI in Non-Split
3070 * and Split MDP comp. But HWC needs to crop them for source split.
3071 * Reason: 1) Source split is efficient only when the final effective
3072 * load is distributed evenly across mixers.
3073 * 2) We have to know the effective width of the layer that
3074 * the ROI needs to find the no. of pipes the layer needs.
3075 */
3076 trimAgainstROI(ctx, crop, dst);
3077 }
3078
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05003079 if(needs3DComposition(ctx, mDpy) &&
3080 get3DFormat(hnd) != HAL_NO_3D){
3081 return configure3DVideo(ctx, layer, mDpy, mdpFlags, z, lDest,
3082 rDest, &PipeLayerPair.rot);
3083 }
3084
Saurabh Shahab47c692014-02-12 18:45:57 -08003085 // Handle R/B swap
3086 if (layer->flags & HWC_FORMAT_RB_SWAP) {
3087 if (hnd->format == HAL_PIXEL_FORMAT_RGBA_8888)
3088 whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRA_8888);
3089 else if (hnd->format == HAL_PIXEL_FORMAT_RGBX_8888)
3090 whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
3091 }
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07003092 // update source crop and destination position of AIV video layer.
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07003093 if(ctx->listStats[mDpy].mAIVVideoMode && isYuvBuffer(hnd)) {
3094 updateCoordinates(ctx, crop, dst, mDpy);
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07003095 }
Ramkumar Radhakrishnana5c72872014-08-28 19:04:18 -07003096 /* Calculate the external display position based on MDP downscale,
3097 ActionSafe, and extorientation features. */
3098 calcExtDisplayPosition(ctx, hnd, mDpy, crop, dst, transform, orient);
Saurabh Shahab47c692014-02-12 18:45:57 -08003099
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003100 int downscale = getRotDownscale(ctx, layer);
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003101 setMdpFlags(ctx, layer, mdpFlags, downscale, transform);
Saurabh Shahab47c692014-02-12 18:45:57 -08003102
3103 if(lDest != OV_INVALID && rDest != OV_INVALID) {
3104 //Enable overfetch
Saurabh Shah97e2d802014-04-14 18:03:54 -07003105 setMdpFlags(mdpFlags, OV_MDSS_MDP_DUAL_PIPE);
Saurabh Shahab47c692014-02-12 18:45:57 -08003106 }
3107
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003108 if((has90Transform(layer) or downscale) and isRotationDoable(ctx, hnd)) {
Saurabh Shahab47c692014-02-12 18:45:57 -08003109 (*rot) = ctx->mRotMgr->getNext();
3110 if((*rot) == NULL) return -1;
Saurabh Shah39240c92014-03-31 10:31:42 -07003111 ctx->mLayerRotMap[mDpy]->add(layer, *rot);
Saurabh Shah1bd5b6f2014-05-19 12:23:13 -07003112 //If the video is using a single pipe, enable BWC
3113 if(rDest == OV_INVALID) {
Saurabh Shahcd018352014-11-11 13:54:19 -08003114 BwcPM::setBwc(ctx, mDpy, hnd, crop, dst, transform, downscale,
3115 mdpFlags);
Saurabh Shah1bd5b6f2014-05-19 12:23:13 -07003116 }
radhakrishnab8e2c952015-06-04 16:09:16 +05303117 uint32_t frame_rate = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].refreshRate;
3118 if(!mDpy && !isSecondaryConnected(ctx)) {
3119 if(metadata && (metadata->operation & UPDATE_REFRESH_RATE))
3120 frame_rate = metadata->refreshrate;
3121 }
Saurabh Shahab47c692014-02-12 18:45:57 -08003122 //Configure rotator for pre-rotation
radhakrishnab8e2c952015-06-04 16:09:16 +05303123 if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale,
3124 frame_rate) < 0) {
Saurabh Shahab47c692014-02-12 18:45:57 -08003125 ALOGE("%s: configRotator failed!", __FUNCTION__);
3126 return -1;
3127 }
Saurabh Shah8ec9b5e2014-06-30 14:37:17 -07003128 updateSource(orient, whf, crop, *rot);
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003129 rotFlags |= ovutils::ROT_PREROTATED;
Saurabh Shahab47c692014-02-12 18:45:57 -08003130 }
3131
3132 //If 2 pipes being used, divide layer into half, crop and dst
3133 hwc_rect_t cropL = crop;
3134 hwc_rect_t cropR = crop;
3135 hwc_rect_t dstL = dst;
3136 hwc_rect_t dstR = dst;
3137 if(lDest != OV_INVALID && rDest != OV_INVALID) {
3138 cropL.right = (crop.right + crop.left) / 2;
3139 cropR.left = cropL.right;
3140 sanitizeSourceCrop(cropL, cropR, hnd);
3141
Saurabh Shahb729b192014-08-15 18:04:24 -07003142 bool cropSwap = false;
Saurabh Shahab47c692014-02-12 18:45:57 -08003143 //Swap crops on H flip since 2 pipes are being used
3144 if((orient & OVERLAY_TRANSFORM_FLIP_H) && (*rot) == NULL) {
3145 hwc_rect_t tmp = cropL;
3146 cropL = cropR;
3147 cropR = tmp;
Saurabh Shahb729b192014-08-15 18:04:24 -07003148 cropSwap = true;
Saurabh Shahab47c692014-02-12 18:45:57 -08003149 }
3150
Saurabh Shahb729b192014-08-15 18:04:24 -07003151 //cropSwap trick: If the src and dst widths are both odd, let us say
3152 //2507, then splitting both into half would cause left width to be 1253
3153 //and right 1254. If crop is swapped because of H flip, this will cause
3154 //left crop width to be 1254, whereas left dst width remains 1253, thus
3155 //inducing a scaling that is unaccounted for. To overcome that we add 1
3156 //to the dst width if there is a cropSwap. So if the original width was
3157 //2507, the left dst width will be 1254. Even if the original width was
3158 //even for ex: 2508, the left dst width will still remain 1254.
3159 dstL.right = (dst.right + dst.left + cropSwap) / 2;
Saurabh Shahab47c692014-02-12 18:45:57 -08003160 dstR.left = dstL.right;
3161 }
3162
3163 //For the mdp, since either we are pre-rotating or MDP does flips
3164 orient = OVERLAY_TRANSFORM_0;
3165 transform = 0;
3166
3167 //configure left pipe
3168 if(lDest != OV_INVALID) {
Saurabh Shah2c8ad052014-08-15 13:27:46 -07003169 PipeArgs pargL(mdpFlags, whf, z,
Saurabh Shahab47c692014-02-12 18:45:57 -08003170 static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
3171 (ovutils::eBlending) getBlending(layer->blending));
3172
3173 if(configMdp(ctx->mOverlay, pargL, orient,
3174 cropL, dstL, metadata, lDest) < 0) {
3175 ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
3176 return -1;
3177 }
3178 }
3179
3180 //configure right pipe
3181 if(rDest != OV_INVALID) {
Saurabh Shah2c8ad052014-08-15 13:27:46 -07003182 PipeArgs pargR(mdpFlags, whf, z,
Saurabh Shahab47c692014-02-12 18:45:57 -08003183 static_cast<eRotFlags>(rotFlags),
3184 layer->planeAlpha,
3185 (ovutils::eBlending) getBlending(layer->blending));
3186 if(configMdp(ctx->mOverlay, pargR, orient,
3187 cropR, dstR, metadata, rDest) < 0) {
3188 ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
3189 return -1;
3190 }
3191 }
3192
3193 return 0;
3194}
3195
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -08003196bool MDPComp::getPartialUpdatePref(hwc_context_t *ctx) {
3197 Locker::Autolock _l(ctx->mDrawLock);
3198 const int fbNum = Overlay::getFbForDpy(Overlay::DPY_PRIMARY);
3199 char path[MAX_SYSFS_FILE_PATH];
3200 snprintf (path, sizeof(path), "sys/class/graphics/fb%d/dyn_pu", fbNum);
3201 int fd = open(path, O_RDONLY);
3202 if(fd < 0) {
3203 ALOGE("%s: Failed to open sysfd node: %s", __FUNCTION__, path);
3204 return -1;
3205 }
3206 char value[4];
3207 ssize_t size_read = read(fd, value, sizeof(value)-1);
3208 if(size_read <= 0) {
3209 ALOGE("%s: Failed to read sysfd node: %s", __FUNCTION__, path);
3210 close(fd);
3211 return -1;
3212 }
3213 close(fd);
3214 value[size_read] = '\0';
3215 return atoi(value);
3216}
3217
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003218int MDPComp::setPartialUpdatePref(hwc_context_t *ctx, bool enable) {
3219 Locker::Autolock _l(ctx->mDrawLock);
3220 const int fbNum = Overlay::getFbForDpy(Overlay::DPY_PRIMARY);
3221 char path[MAX_SYSFS_FILE_PATH];
3222 snprintf (path, sizeof(path), "sys/class/graphics/fb%d/dyn_pu", fbNum);
3223 int fd = open(path, O_WRONLY);
3224 if(fd < 0) {
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -08003225 ALOGE("%s: Failed to open sysfd node: %s", __FUNCTION__, path);
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003226 return -1;
3227 }
3228 char value[4];
3229 snprintf(value, sizeof(value), "%d", (int)enable);
3230 ssize_t ret = write(fd, value, strlen(value));
3231 if(ret <= 0) {
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -08003232 ALOGE("%s: Failed to write to sysfd nodes: %s", __FUNCTION__, path);
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003233 close(fd);
3234 return -1;
3235 }
3236 close(fd);
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003237 return 0;
3238}
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08003239
3240bool MDPComp::loadPerfLib() {
3241 char perfLibPath[PROPERTY_VALUE_MAX] = {0};
3242 bool success = false;
3243 if((property_get("ro.vendor.extension_library", perfLibPath, NULL) <= 0)) {
3244 ALOGE("vendor library not set in ro.vendor.extension_library");
3245 return false;
3246 }
3247
3248 sLibPerfHint = dlopen(perfLibPath, RTLD_NOW);
3249 if(sLibPerfHint) {
3250 *(void **)&sPerfLockAcquire = dlsym(sLibPerfHint, "perf_lock_acq");
3251 *(void **)&sPerfLockRelease = dlsym(sLibPerfHint, "perf_lock_rel");
3252 if (!sPerfLockAcquire || !sPerfLockRelease) {
3253 ALOGE("Failed to load symbols for perfLock");
3254 dlclose(sLibPerfHint);
3255 sLibPerfHint = NULL;
3256 return false;
3257 }
3258 success = true;
3259 ALOGI("Successfully Loaded perf hint API's");
3260 } else {
3261 ALOGE("Failed to open %s : %s", perfLibPath, dlerror());
3262 }
3263 return success;
3264}
3265
3266void MDPComp::setPerfHint(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
3267 if ((sPerfHintWindow < 0) || mDpy || !sLibPerfHint) {
3268 return;
3269 }
3270 static int count = sPerfHintWindow;
3271 static int perflockFlag = 0;
3272
3273 /* Send hint to mpctl when single layer is updated
3274 * for a successful number of windows. Hint release
3275 * happens immediately upon multiple layer update.
3276 */
3277 if (onlyVideosUpdating(ctx, list)) {
3278 if(count) {
3279 count--;
3280 }
3281 } else {
3282 if (perflockFlag) {
3283 perflockFlag = 0;
3284 sPerfLockRelease(sPerfLockHandle);
3285 }
3286 count = sPerfHintWindow;
3287 }
3288 if (count == 0 && !perflockFlag) {
3289 int perfHint = 0x4501; // 45-display layer hint, 01-Enable
3290 sPerfLockHandle = sPerfLockAcquire(0 /*handle*/, 0/*duration*/,
3291 &perfHint, sizeof(perfHint)/sizeof(int));
Arun Kumar K.R8b927022015-02-24 12:34:21 -08003292 if(sPerfLockHandle > 0) {
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08003293 perflockFlag = 1;
3294 }
3295 }
3296}
3297
Naseer Ahmed7c958d42012-07-31 18:57:03 -07003298}; //namespace
3299