blob: e2c4677891cc4f56abd540125a6de28d82a4d2cd [file] [log] [blame]
Naseer Ahmed7c958d42012-07-31 18:57:03 -07001/*
Tatenda Chipeperekwa95675a72014-12-15 17:06:43 -08002 * Copyright (C) 2012-2015, The Linux Foundation. All rights reserved.
Naseer Ahmed7c958d42012-07-31 18:57:03 -07003 * Not a Contribution, Apache license notifications and license are retained
4 * for attribution purposes only.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
Saurabh Shah4fdde762013-04-30 18:47:33 -070019#include <math.h>
Naseer Ahmed7c958d42012-07-31 18:57:03 -070020#include "hwc_mdpcomp.h"
Arun Kumar K.R299bcda2014-12-18 19:36:40 -080021#include <dlfcn.h>
Tatenda Chipeperekwaaf2c0042014-09-17 12:55:01 -070022#include "hdmi.h"
Ramkumar Radhakrishnan47573e22012-11-07 11:36:41 -080023#include "qdMetaData.h"
Ramkumar Radhakrishnan288f8c72013-01-15 11:37:54 -080024#include "mdp_version.h"
Saurabh Shah2a4eb1b2013-07-22 16:33:23 -070025#include "hwc_fbupdate.h"
Saurabh Shaha9da08f2013-07-03 13:27:53 -070026#include "hwc_ad.h"
Saurabh Shahacf10202013-02-26 10:15:15 -080027#include <overlayRotator.h>
Arun Kumar K.R00b84792015-03-27 11:28:36 -070028#include <overlayCursor.h>
Sushil Chauhandefd3522014-05-13 18:17:12 -070029#include "hwc_copybit.h"
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -070030#include "qd_utils.h"
Saurabh Shahacf10202013-02-26 10:15:15 -080031
Saurabh Shah85234ec2013-04-12 17:09:00 -070032using namespace overlay;
Saurabh Shahbd2d0832013-04-04 14:33:08 -070033using namespace qdutils;
Saurabh Shahacf10202013-02-26 10:15:15 -080034using namespace overlay::utils;
35namespace ovutils = overlay::utils;
Naseer Ahmed7c958d42012-07-31 18:57:03 -070036
Naseer Ahmed7c958d42012-07-31 18:57:03 -070037namespace qhwc {
38
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -080039//==============MDPComp========================================================
40
Saurabh Shah59562ff2014-09-30 16:13:12 -070041IdleInvalidator *MDPComp::sIdleInvalidator = NULL;
Naseer Ahmed7c958d42012-07-31 18:57:03 -070042bool MDPComp::sIdleFallBack = false;
43bool MDPComp::sDebugLogs = false;
Naseer Ahmed54821fe2012-11-28 18:44:38 -050044bool MDPComp::sEnabled = false;
Jeykumar Sankaran24c199d2013-05-24 09:40:36 -070045bool MDPComp::sEnableMixedMode = true;
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -070046int MDPComp::sSimulationFlags = 0;
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -070047int MDPComp::sMaxPipesPerMixer = 0;
Raj Kamal389d6e32014-08-04 14:43:24 +053048bool MDPComp::sEnableYUVsplit = false;
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -070049bool MDPComp::sSrcSplitEnabled = false;
Saurabh Shahacec8e42014-11-25 11:07:04 -080050int MDPComp::sMaxSecLayers = 1;
Dileep Kumar Reddi4070e932014-09-30 09:00:57 +053051bool MDPComp::enablePartialUpdateForMDP3 = false;
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -070052bool MDPComp::sIsPartialUpdateActive = true;
Arun Kumar K.R299bcda2014-12-18 19:36:40 -080053void *MDPComp::sLibPerfHint = NULL;
54int MDPComp::sPerfLockHandle = 0;
55int (*MDPComp::sPerfLockAcquire)(int, int, int*, int) = NULL;
56int (*MDPComp::sPerfLockRelease)(int value) = NULL;
57int MDPComp::sPerfHintWindow = -1;
radhakrishna35e33072015-04-08 17:20:43 +053058float MDPComp::sDownscaleThreshold = 1.0;
Arun Kumar K.R299bcda2014-12-18 19:36:40 -080059
Saurabh Shah8cc77712015-03-31 10:48:51 -070060enum AllocOrder { FORMAT_YUV, FORMAT_RGB, FORMAT_MAX };
61
Saurabh Shah88e4d272013-09-03 13:31:29 -070062MDPComp* MDPComp::getObject(hwc_context_t *ctx, const int& dpy) {
Saurabh Shah60e8bde2014-04-30 14:46:03 -070063 if(qdutils::MDPVersion::getInstance().isSrcSplit()) {
64 sSrcSplitEnabled = true;
65 return new MDPCompSrcSplit(dpy);
66 } else if(isDisplaySplit(ctx, dpy)) {
Saurabh Shah88e4d272013-09-03 13:31:29 -070067 return new MDPCompSplit(dpy);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -080068 }
Saurabh Shah88e4d272013-09-03 13:31:29 -070069 return new MDPCompNonSplit(dpy);
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -080070}
71
Jeykumar Sankaran85977e32013-02-25 17:06:08 -080072MDPComp::MDPComp(int dpy):mDpy(dpy){};
73
Jeykumar Sankaran6850ac62014-05-27 10:07:26 -070074void MDPComp::dump(android::String8& buf, hwc_context_t *ctx)
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -080075{
Jeykumar Sankaran3c6bb042013-08-15 14:01:04 -070076 if(mCurrentFrame.layerCount > MAX_NUM_APP_LAYERS)
77 return;
78
Jeykumar Sankaran85977e32013-02-25 17:06:08 -080079 dumpsys_log(buf,"HWC Map for Dpy: %s \n",
Jeykumar Sankaran27dee262013-08-01 17:09:54 -070080 (mDpy == 0) ? "\"PRIMARY\"" :
81 (mDpy == 1) ? "\"EXTERNAL\"" : "\"VIRTUAL\"");
Saurabh Shahe9bc60f2013-08-29 12:58:06 -070082 dumpsys_log(buf,"CURR_FRAME: layerCount:%2d mdpCount:%2d "
Arun Kumar K.R00b84792015-03-27 11:28:36 -070083 "fbCount:%2d dropCount:%2d\n", mCurrentFrame.layerCount,
84 mCurrentFrame.mdpCount, mCurrentFrame.fbCount, mCurrentFrame.dropCount);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -080085 dumpsys_log(buf,"needsFBRedraw:%3s pipesUsed:%2d MaxPipesPerMixer: %d \n",
86 (mCurrentFrame.needsRedraw? "YES" : "NO"),
87 mCurrentFrame.mdpCount, sMaxPipesPerMixer);
Jeykumar Sankaran6850ac62014-05-27 10:07:26 -070088 if(isDisplaySplit(ctx, mDpy)) {
89 dumpsys_log(buf, "Programmed ROI's: Left: [%d, %d, %d, %d] "
90 "Right: [%d, %d, %d, %d] \n",
91 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
92 ctx->listStats[mDpy].lRoi.right,
93 ctx->listStats[mDpy].lRoi.bottom,
94 ctx->listStats[mDpy].rRoi.left,ctx->listStats[mDpy].rRoi.top,
95 ctx->listStats[mDpy].rRoi.right,
96 ctx->listStats[mDpy].rRoi.bottom);
97 } else {
98 dumpsys_log(buf, "Programmed ROI: [%d, %d, %d, %d] \n",
99 ctx->listStats[mDpy].lRoi.left,ctx->listStats[mDpy].lRoi.top,
100 ctx->listStats[mDpy].lRoi.right,
101 ctx->listStats[mDpy].lRoi.bottom);
102 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800103 dumpsys_log(buf," --------------------------------------------- \n");
104 dumpsys_log(buf," listIdx | cached? | mdpIndex | comptype | Z \n");
105 dumpsys_log(buf," --------------------------------------------- \n");
106 for(int index = 0; index < mCurrentFrame.layerCount; index++ )
107 dumpsys_log(buf," %7d | %7s | %8d | %9s | %2d \n",
108 index,
109 (mCurrentFrame.isFBComposed[index] ? "YES" : "NO"),
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700110 mCurrentFrame.layerToMDP[index],
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800111 (mCurrentFrame.isFBComposed[index] ?
Arun Kumar K.R00b84792015-03-27 11:28:36 -0700112 (mCurrentFrame.drop[index] ?
113 ((mCurrentFrame.hwCursorIndex == index) ? "CURSOR": "DROP"):
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700114 (mCurrentFrame.needsRedraw ? "GLES" : "CACHE")) : "MDP"),
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800115 (mCurrentFrame.isFBComposed[index] ? mCurrentFrame.fbZ :
116 mCurrentFrame.mdpToLayer[mCurrentFrame.layerToMDP[index]].pipeInfo->zOrder));
117 dumpsys_log(buf,"\n");
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800118}
119
120bool MDPComp::init(hwc_context_t *ctx) {
121
122 if(!ctx) {
123 ALOGE("%s: Invalid hwc context!!",__FUNCTION__);
124 return false;
125 }
126
Saurabh Shah59562ff2014-09-30 16:13:12 -0700127 char property[PROPERTY_VALUE_MAX] = {0};
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800128
129 sEnabled = false;
Dileep Kumar Reddid8e601d2014-10-28 18:20:43 +0530130 if((ctx->mMDP.version >= qdutils::MDP_V4_0) &&
131 (property_get("persist.hwc.mdpcomp.enable", property, NULL) > 0) &&
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800132 (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
133 (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800134 sEnabled = true;
135 }
136
Jeykumar Sankaran24c199d2013-05-24 09:40:36 -0700137 sEnableMixedMode = true;
138 if((property_get("debug.mdpcomp.mixedmode.disable", property, NULL) > 0) &&
139 (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
140 (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
141 sEnableMixedMode = false;
142 }
143
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700144 qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
145
Saurabh Shah2fd8a252014-12-05 13:49:53 -0800146 sMaxPipesPerMixer = (int)mdpVersion.getBlendStages();
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700147 if(property_get("persist.hwc.mdpcomp.maxpermixer", property, "-1") > 0) {
Saurabh Shah85234ec2013-04-12 17:09:00 -0700148 int val = atoi(property);
149 if(val >= 0)
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700150 sMaxPipesPerMixer = min(val, sMaxPipesPerMixer);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800151 }
152
Saurabh Shahacec8e42014-11-25 11:07:04 -0800153 /* Maximum layers allowed to use MDP on secondary panels. If property
154 * doesn't exist, default to 1. Using the property it can be set to 0 or
155 * more.
156 */
157 if(property_get("persist.hwc.maxseclayers", property, "1") > 0) {
158 int val = atoi(property);
159 sMaxSecLayers = (val >= 0) ? val : 1;
160 sMaxSecLayers = min(sMaxSecLayers, sMaxPipesPerMixer);
161 }
162
Naseer Ahmedf40f2c82013-08-14 16:42:40 -0400163 if(ctx->mMDP.panel != MIPI_CMD_PANEL) {
Saurabh Shah59562ff2014-09-30 16:13:12 -0700164 sIdleInvalidator = IdleInvalidator::getInstance();
165 if(sIdleInvalidator->init(timeout_handler, ctx) < 0) {
166 delete sIdleInvalidator;
167 sIdleInvalidator = NULL;
Naseer Ahmedf40f2c82013-08-14 16:42:40 -0400168 }
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800169 }
radhakrishnac9a67412013-09-25 17:40:42 +0530170
Saurabh Shah7c727642014-06-02 15:47:14 -0700171 if(!qdutils::MDPVersion::getInstance().isSrcSplit() &&
Saurabh Shahc46cf9d2014-07-02 15:22:34 -0700172 !qdutils::MDPVersion::getInstance().isRotDownscaleEnabled() &&
Saurabh Shah7c727642014-06-02 15:47:14 -0700173 property_get("persist.mdpcomp.4k2kSplit", property, "0") > 0 &&
174 (!strncmp(property, "1", PROPERTY_VALUE_MAX) ||
175 !strncasecmp(property,"true", PROPERTY_VALUE_MAX))) {
Raj Kamal389d6e32014-08-04 14:43:24 +0530176 sEnableYUVsplit = true;
radhakrishnac9a67412013-09-25 17:40:42 +0530177 }
Sushil Chauhandefd3522014-05-13 18:17:12 -0700178
Dileep Kumar Reddic6ef3472014-09-24 19:07:08 +0530179 bool defaultPTOR = false;
180 //Enable PTOR when "persist.hwc.ptor.enable" is not defined for
Prabhanjan Kandulafc541b32015-03-30 20:56:16 +0530181 //Bear family targets by default
Dileep Kumar Reddic6ef3472014-09-24 19:07:08 +0530182 if((property_get("persist.hwc.ptor.enable", property, NULL) <= 0) &&
183 (qdutils::MDPVersion::getInstance().is8x16() ||
Prabhanjan Kandulafc541b32015-03-30 20:56:16 +0530184 qdutils::MDPVersion::getInstance().is8x39() ||
185 qdutils::MDPVersion::getInstance().is8x52())) {
Dileep Kumar Reddic6ef3472014-09-24 19:07:08 +0530186 defaultPTOR = true;
187 }
188
189 if (defaultPTOR || (!strncasecmp(property, "true", PROPERTY_VALUE_MAX)) ||
190 (!strncmp(property, "1", PROPERTY_VALUE_MAX ))) {
Sushil Chauhandefd3522014-05-13 18:17:12 -0700191 ctx->mCopyBit[HWC_DISPLAY_PRIMARY] = new CopyBit(ctx,
192 HWC_DISPLAY_PRIMARY);
193 }
194
Dileep Kumar Reddi4070e932014-09-30 09:00:57 +0530195 if((property_get("persist.mdp3.partialUpdate", property, NULL) <= 0) &&
196 (ctx->mMDP.version == qdutils::MDP_V3_0_5)) {
197 enablePartialUpdateForMDP3 = true;
198 }
199
200 if(!enablePartialUpdateForMDP3 &&
201 (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
202 (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
203 enablePartialUpdateForMDP3 = true;
204 }
205
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -0800206 sIsPartialUpdateActive = getPartialUpdatePref(ctx);
207
Arun Kumar K.R299bcda2014-12-18 19:36:40 -0800208 if(property_get("persist.mdpcomp_perfhint", property, "-1") > 0) {
209 int val = atoi(property);
210 if(val > 0 && loadPerfLib()) {
211 sPerfHintWindow = val;
212 ALOGI("PerfHintWindow = %d", sPerfHintWindow);
213 }
214 }
215
radhakrishna35e33072015-04-08 17:20:43 +0530216 if(property_get("persist.hwc.downscale_threshold", property, "1.0") > 0) {
217 sDownscaleThreshold = (float)atof(property);
218 }
219
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700220 return true;
221}
222
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800223void MDPComp::reset(hwc_context_t *ctx) {
224 const int numLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shah2a4eb1b2013-07-22 16:33:23 -0700225 mCurrentFrame.reset(numLayers);
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800226 ctx->mOverlay->clear(mDpy);
227 ctx->mLayerRotMap[mDpy]->clear();
Saurabh Shah2a4eb1b2013-07-22 16:33:23 -0700228}
229
Raj Kamal4393eaa2014-06-06 13:45:20 +0530230void MDPComp::reset() {
Raj Kamalfdfdddf2015-03-16 21:59:25 +0530231 mPrevModeOn = mModeOn;
Raj Kamal4393eaa2014-06-06 13:45:20 +0530232 mModeOn = false;
233}
234
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700235void MDPComp::timeout_handler(void *udata) {
236 struct hwc_context_t* ctx = (struct hwc_context_t*)(udata);
Raj Kamalfdfdddf2015-03-16 21:59:25 +0530237 bool handleTimeout = false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700238
239 if(!ctx) {
240 ALOGE("%s: received empty data in timer callback", __FUNCTION__);
241 return;
242 }
Raj Kamal58b31a02014-12-16 15:53:53 +0530243
244 ctx->mDrawLock.lock();
Raj Kamalfdfdddf2015-03-16 21:59:25 +0530245
246 /* Handle timeout event only if the previous composition
247 on any display is MDP or MIXED*/
248 for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
249 if(ctx->mMDPComp[i])
250 handleTimeout =
251 ctx->mMDPComp[i]->isMDPComp() || handleTimeout;
252 }
253
254 if(!handleTimeout) {
Ramkumar Radhakrishnan92abb4f2014-02-06 21:31:29 -0800255 ALOGD_IF(isDebug(), "%s:Do not handle this timeout", __FUNCTION__);
Raj Kamal58b31a02014-12-16 15:53:53 +0530256 ctx->mDrawLock.unlock();
Ramkumar Radhakrishnan92abb4f2014-02-06 21:31:29 -0800257 return;
258 }
Jesse Hall3be78d92012-08-21 15:12:23 -0700259 if(!ctx->proc) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700260 ALOGE("%s: HWC proc not registered", __FUNCTION__);
Raj Kamal58b31a02014-12-16 15:53:53 +0530261 ctx->mDrawLock.unlock();
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700262 return;
263 }
264 sIdleFallBack = true;
Raj Kamal58b31a02014-12-16 15:53:53 +0530265 ctx->mDrawLock.unlock();
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700266 /* Trigger SF to redraw the current frame */
Jesse Hall3be78d92012-08-21 15:12:23 -0700267 ctx->proc->invalidate(ctx->proc);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700268}
269
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700270void MDPComp::setMaxPipesPerMixer(const uint32_t value) {
271 qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
Saurabh Shah2fd8a252014-12-05 13:49:53 -0800272 uint32_t maxSupported = (int)mdpVersion.getBlendStages();
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700273 if(value > maxSupported) {
274 ALOGW("%s: Input exceeds max value supported. Setting to"
275 "max value: %d", __FUNCTION__, maxSupported);
276 }
277 sMaxPipesPerMixer = min(value, maxSupported);
278}
279
Saurabh Shah59562ff2014-09-30 16:13:12 -0700280void MDPComp::setIdleTimeout(const uint32_t& timeout) {
281 enum { ONE_REFRESH_PERIOD_MS = 17, ONE_BILLION_MS = 1000000000 };
282
283 if(sIdleInvalidator) {
284 if(timeout <= ONE_REFRESH_PERIOD_MS) {
285 //If the specified timeout is < 1 draw cycle worth, "virtually"
286 //disable idle timeout. The ideal way for clients to disable
287 //timeout is to set it to 0
288 sIdleInvalidator->setIdleTimeout(ONE_BILLION_MS);
289 ALOGI("Disabled idle timeout");
290 return;
291 }
292 sIdleInvalidator->setIdleTimeout(timeout);
293 ALOGI("Idle timeout set to %u", timeout);
294 } else {
295 ALOGW("Cannot set idle timeout, IdleInvalidator not enabled");
296 }
297}
298
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800299void MDPComp::setMDPCompLayerFlags(hwc_context_t *ctx,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800300 hwc_display_contents_1_t* list) {
301 LayerProp *layerProp = ctx->layerProp[mDpy];
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800302
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800303 for(int index = 0; index < ctx->listStats[mDpy].numAppLayers; index++) {
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800304 hwc_layer_1_t* layer = &(list->hwLayers[index]);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800305 if(!mCurrentFrame.isFBComposed[index]) {
306 layerProp[index].mFlags |= HWC_MDPCOMP;
307 layer->compositionType = HWC_OVERLAY;
308 layer->hints |= HWC_HINT_CLEAR_FB;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800309 } else {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700310 /* Drop the layer when its already present in FB OR when it lies
311 * outside frame's ROI */
312 if(!mCurrentFrame.needsRedraw || mCurrentFrame.drop[index]) {
Arun Kumar K.R00b84792015-03-27 11:28:36 -0700313 if(index == mCurrentFrame.hwCursorIndex) {
314 layer->compositionType = HWC_CURSOR_OVERLAY;
315 } else {
316 layer->compositionType = HWC_OVERLAY;
317 }
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700318 }
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800319 }
320 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700321}
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500322
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800323void MDPComp::setRedraw(hwc_context_t *ctx,
324 hwc_display_contents_1_t* list) {
325 mCurrentFrame.needsRedraw = false;
326 if(!mCachedFrame.isSameFrame(mCurrentFrame, list) ||
327 (list->flags & HWC_GEOMETRY_CHANGED) ||
328 isSkipPresent(ctx, mDpy)) {
329 mCurrentFrame.needsRedraw = true;
330 }
331}
332
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800333MDPComp::FrameInfo::FrameInfo() {
Saurabh Shahf7fad542014-08-14 10:11:36 -0700334 memset(&mdpToLayer, 0, sizeof(mdpToLayer));
Saurabh Shahaa236822013-04-24 18:07:26 -0700335 reset(0);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800336}
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800337
Saurabh Shahaa236822013-04-24 18:07:26 -0700338void MDPComp::FrameInfo::reset(const int& numLayers) {
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700339 for(int i = 0 ; i < MAX_NUM_BLEND_STAGES; i++ ) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800340 if(mdpToLayer[i].pipeInfo) {
341 delete mdpToLayer[i].pipeInfo;
342 mdpToLayer[i].pipeInfo = NULL;
343 //We dont own the rotator
344 mdpToLayer[i].rot = NULL;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800345 }
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800346 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800347
348 memset(&mdpToLayer, 0, sizeof(mdpToLayer));
349 memset(&layerToMDP, -1, sizeof(layerToMDP));
Saurabh Shahaa236822013-04-24 18:07:26 -0700350 memset(&isFBComposed, 1, sizeof(isFBComposed));
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800351
Saurabh Shahaa236822013-04-24 18:07:26 -0700352 layerCount = numLayers;
353 fbCount = numLayers;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800354 mdpCount = 0;
Saurabh Shah2f3895f2013-05-02 10:13:31 -0700355 needsRedraw = true;
Saurabh Shahd53bc5f2014-02-05 10:17:43 -0800356 fbZ = -1;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800357}
358
Saurabh Shahaa236822013-04-24 18:07:26 -0700359void MDPComp::FrameInfo::map() {
360 // populate layer and MDP maps
361 int mdpIdx = 0;
362 for(int idx = 0; idx < layerCount; idx++) {
363 if(!isFBComposed[idx]) {
364 mdpToLayer[mdpIdx].listIndex = idx;
365 layerToMDP[idx] = mdpIdx++;
366 }
367 }
368}
369
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800370MDPComp::LayerCache::LayerCache() {
371 reset();
372}
373
374void MDPComp::LayerCache::reset() {
Saurabh Shahaa236822013-04-24 18:07:26 -0700375 memset(&hnd, 0, sizeof(hnd));
Prabhanjan Kandula2243aa62013-10-24 12:58:55 +0530376 memset(&isFBComposed, true, sizeof(isFBComposed));
377 memset(&drop, false, sizeof(drop));
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800378 layerCount = 0;
Saurabh Shahaa236822013-04-24 18:07:26 -0700379}
380
381void MDPComp::LayerCache::cacheAll(hwc_display_contents_1_t* list) {
Praveena Pachipulusud9443c72014-02-17 10:42:28 +0530382 const int numAppLayers = (int)list->numHwLayers - 1;
Saurabh Shahaa236822013-04-24 18:07:26 -0700383 for(int i = 0; i < numAppLayers; i++) {
384 hnd[i] = list->hwLayers[i].handle;
385 }
386}
387
388void MDPComp::LayerCache::updateCounts(const FrameInfo& curFrame) {
Saurabh Shahaa236822013-04-24 18:07:26 -0700389 layerCount = curFrame.layerCount;
Prabhanjan Kandula2243aa62013-10-24 12:58:55 +0530390 memcpy(&isFBComposed, &curFrame.isFBComposed, sizeof(isFBComposed));
391 memcpy(&drop, &curFrame.drop, sizeof(drop));
392}
393
Jeykumar Sankaran988d3682013-11-15 11:57:16 -0800394bool MDPComp::LayerCache::isSameFrame(const FrameInfo& curFrame,
395 hwc_display_contents_1_t* list) {
Prabhanjan Kandula2243aa62013-10-24 12:58:55 +0530396 if(layerCount != curFrame.layerCount)
397 return false;
398 for(int i = 0; i < curFrame.layerCount; i++) {
399 if((curFrame.isFBComposed[i] != isFBComposed[i]) ||
400 (curFrame.drop[i] != drop[i])) {
401 return false;
402 }
Jeykumar Sankaran988d3682013-11-15 11:57:16 -0800403 if(curFrame.isFBComposed[i] &&
404 (hnd[i] != list->hwLayers[i].handle)){
405 return false;
406 }
Prabhanjan Kandula2243aa62013-10-24 12:58:55 +0530407 }
408 return true;
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800409}
410
Raj Kamalfdfdddf2015-03-16 21:59:25 +0530411bool MDPComp::LayerCache::isSameFrame(hwc_context_t *ctx, int dpy,
412 hwc_display_contents_1_t* list) {
413
414 if(layerCount != ctx->listStats[dpy].numAppLayers)
415 return false;
416
417 if((list->flags & HWC_GEOMETRY_CHANGED) ||
418 isSkipPresent(ctx, dpy)) {
419 return false;
420 }
421
422 for(int i = 0; i < layerCount; i++) {
423 if(hnd[i] != list->hwLayers[i].handle)
424 return false;
425 }
426
427 return true;
428}
429
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700430bool MDPComp::isSupportedForMDPComp(hwc_context_t *ctx, hwc_layer_1_t* layer) {
431 private_handle_t *hnd = (private_handle_t *)layer->handle;
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800432 if((has90Transform(layer) and (not isRotationDoable(ctx, hnd))) ||
Raj Kamal1179d9c2014-10-28 15:31:35 +0530433 (not isValidDimension(ctx,layer)) ||
434 isSkipLayer(layer)) {
435 //More conditions here, sRGB+Blend etc
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700436 return false;
437 }
radhakrishna35e33072015-04-08 17:20:43 +0530438
439 //In targets with fewer pipes, frequent composition switch between MDP/GPU
440 //can happen for a layer due to lack of pipes. When this switch happens
441 //continuously for RGB downscaled layer with downscale greater than
442 //threshold, it appears as flicker as output
443 //of MDP and GPU are different as they use different filters for downscale.
444 //To avoid this flicker, punt RGB downscaled layer with downscale greater
445 //than threshold value to GPU always.
446 if((sDownscaleThreshold > 1.0)) {
447 if(((not isYuvBuffer(hnd))
448 and (not isDownscaleWithinThreshold(layer,
449 sDownscaleThreshold)))) {
450 ALOGD_IF(isDebug(), "%s: required downscale is greater than \
451 threshold %f", __FUNCTION__, sDownscaleThreshold);
452 return false;
453 }
454 }
455
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700456 return true;
457}
458
Sravan Kumar D.V.Nad5d9292013-04-24 14:23:04 +0530459bool MDPComp::isValidDimension(hwc_context_t *ctx, hwc_layer_1_t *layer) {
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800460 private_handle_t *hnd = (private_handle_t *)layer->handle;
461
462 if(!hnd) {
Sushil Chauhan897a9c32013-07-18 11:09:55 -0700463 if (layer->flags & HWC_COLOR_FILL) {
464 // Color layer
465 return true;
466 }
Ramkumar Radhakrishnan0cabf212014-09-08 20:07:49 -0700467 ALOGD_IF(isDebug(), "%s: layer handle is NULL", __FUNCTION__);
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800468 return false;
469 }
470
Naseer Ahmede850a802013-09-06 13:12:52 -0400471 //XXX: Investigate doing this with pixel phase on MDSS
Naseer Ahmede77f8082013-10-10 13:42:48 -0400472 if(!isSecureBuffer(hnd) && isNonIntegralSourceCrop(layer->sourceCropf))
Naseer Ahmede850a802013-09-06 13:12:52 -0400473 return false;
474
Saurabh Shah62e1d732013-09-17 10:44:05 -0700475 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
Saurabh Shah4fdde762013-04-30 18:47:33 -0700476 hwc_rect_t dst = layer->displayFrame;
Saurabh Shahb6810df2014-06-17 16:00:22 -0700477 bool rotated90 = (bool)(layer->transform & HAL_TRANSFORM_ROT_90);
Saurabh Shahe28a4022014-06-13 11:41:13 -0700478 int crop_w = rotated90 ? crop.bottom - crop.top : crop.right - crop.left;
479 int crop_h = rotated90 ? crop.right - crop.left : crop.bottom - crop.top;
Saurabh Shah4fdde762013-04-30 18:47:33 -0700480 int dst_w = dst.right - dst.left;
481 int dst_h = dst.bottom - dst.top;
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800482 float w_scale = ((float)crop_w / (float)dst_w);
483 float h_scale = ((float)crop_h / (float)dst_h);
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530484 MDPVersion& mdpHw = MDPVersion::getInstance();
Saurabh Shah4fdde762013-04-30 18:47:33 -0700485
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800486 /* Workaround for MDP HW limitation in DSI command mode panels where
487 * FPS will not go beyond 30 if buffers on RGB pipes are of width or height
488 * less than 5 pixels
Sravan Kumar D.V.Nad5d9292013-04-24 14:23:04 +0530489 * There also is a HW limilation in MDP, minimum block size is 2x2
490 * Fallback to GPU if height is less than 2.
491 */
Saurabh Shah189f23d2014-09-26 17:21:00 -0700492 if(mdpHw.hasMinCropWidthLimitation() and (crop_w < 5 or crop_h < 5))
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800493 return false;
494
Ramkumar Radhakrishnan1a763e92015-03-19 16:46:46 -0700495 /* crop_w and crop_h should be even for yuv layer, so fallback to GPU for
496 * those cases
497 */
498 if(isYuvBuffer(hnd) && (crop_w < 2 || crop_h < 2)) {
499 return false;
500 }
501
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800502 if((w_scale > 1.0f) || (h_scale > 1.0f)) {
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530503 const uint32_t maxMDPDownscale = mdpHw.getMaxMDPDownscale();
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800504 const float w_dscale = w_scale;
505 const float h_dscale = h_scale;
506
Jeykumar Sankaran1706a772013-11-27 12:55:19 -0800507 if(ctx->mMDP.version >= qdutils::MDSS_V5) {
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700508
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530509 if(!mdpHw.supportsDecimation()) {
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700510 /* On targets that doesnt support Decimation (eg.,8x26)
511 * maximum downscale support is overlay pipe downscale.
512 */
Jeykumar Sankaran39305802014-12-12 17:55:57 -0800513 if(crop_w > (int) mdpHw.getMaxPipeWidth() ||
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530514 w_dscale > maxMDPDownscale ||
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700515 h_dscale > maxMDPDownscale)
Jeykumar Sankaran1706a772013-11-27 12:55:19 -0800516 return false;
517 } else {
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700518 // Decimation on macrotile format layers is not supported.
519 if(isTileRendered(hnd)) {
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530520 /* Bail out if
521 * 1. Src crop > Mixer limit on nonsplit MDPComp
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700522 * 2. exceeds maximum downscale limit
523 */
Jeykumar Sankaran39305802014-12-12 17:55:57 -0800524 if(((crop_w > (int) mdpHw.getMaxPipeWidth()) &&
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530525 !sSrcSplitEnabled) ||
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700526 w_dscale > maxMDPDownscale ||
527 h_dscale > maxMDPDownscale) {
528 return false;
529 }
530 } else if(w_dscale > 64 || h_dscale > 64)
Jeykumar Sankaran1706a772013-11-27 12:55:19 -0800531 return false;
532 }
533 } else { //A-family
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700534 if(w_dscale > maxMDPDownscale || h_dscale > maxMDPDownscale)
Saurabh Shah4fdde762013-04-30 18:47:33 -0700535 return false;
536 }
Saurabh Shah4fdde762013-04-30 18:47:33 -0700537 }
538
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800539 if((w_scale < 1.0f) || (h_scale < 1.0f)) {
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530540 const uint32_t upscale = mdpHw.getMaxMDPUpscale();
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800541 const float w_uscale = 1.0f / w_scale;
542 const float h_uscale = 1.0f / h_scale;
543
544 if(w_uscale > upscale || h_uscale > upscale)
545 return false;
546 }
547
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800548 return true;
549}
550
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800551bool MDPComp::isFrameDoable(hwc_context_t *ctx) {
Saurabh Shahaa236822013-04-24 18:07:26 -0700552 bool ret = true;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800553
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800554 if(!isEnabled()) {
555 ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
Saurabh Shahaa236822013-04-24 18:07:26 -0700556 ret = false;
Saurabh Shah19740d02015-04-10 10:05:42 -0700557 } else if(ctx->mVideoTransFlag && isSecondaryConnected(ctx)) {
Saurabh Shahd4e65852013-06-17 11:33:53 -0700558 //1 Padding round to shift pipes across mixers
559 ALOGD_IF(isDebug(),"%s: MDP Comp. video transition padding round",
560 __FUNCTION__);
561 ret = false;
Raj Kamalc0d34242015-03-17 20:53:14 +0530562 } else if((qdutils::MDPVersion::getInstance().is8x26() ||
563 qdutils::MDPVersion::getInstance().is8x16() ||
Prabhanjan Kandulafc541b32015-03-30 20:56:16 +0530564 qdutils::MDPVersion::getInstance().is8x39() ||
565 qdutils::MDPVersion::getInstance().is8x52()) &&
Raj Kamalc0d34242015-03-17 20:53:14 +0530566 !mDpy && isSecondaryAnimating(ctx) &&
567 isYuvPresent(ctx,HWC_DISPLAY_VIRTUAL)) {
568 ALOGD_IF(isDebug(),"%s: Display animation in progress",
569 __FUNCTION__);
570 ret = false;
Ramkumar Radhakrishnanf26fe9e2014-09-09 13:47:54 -0700571 } else if(qdutils::MDPVersion::getInstance().getTotalPipes() < 8) {
572 /* TODO: freeing up all the resources only for the targets having total
573 number of pipes < 8. Need to analyze number of VIG pipes used
574 for primary in previous draw cycle and accordingly decide
575 whether to fall back to full GPU comp or video only comp
576 */
577 if(isSecondaryConfiguring(ctx)) {
578 ALOGD_IF( isDebug(),"%s: External Display connection is pending",
579 __FUNCTION__);
580 ret = false;
581 } else if(ctx->isPaddingRound) {
582 ALOGD_IF(isDebug(), "%s: padding round invoked for dpy %d",
583 __FUNCTION__,mDpy);
584 ret = false;
585 }
Tatenda Chipeperekwadc8d7082014-11-04 16:41:50 -0800586 } else if (ctx->isDMAStateChanging) {
587 // Bail out if a padding round has been invoked in order to switch DMA
588 // state to block mode. We need this to cater for the case when a layer
589 // requires rotation in the current frame.
590 ALOGD_IF(isDebug(), "%s: padding round invoked to switch DMA state",
591 __FUNCTION__);
592 return false;
Saurabh Shah0ceeb6a2013-04-23 10:46:07 -0700593 }
Tatenda Chipeperekwadc8d7082014-11-04 16:41:50 -0800594
Saurabh Shahaa236822013-04-24 18:07:26 -0700595 return ret;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800596}
597
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800598void MDPCompNonSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect &crop,
599 hwc_rect &dst) {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800600 hwc_rect_t roi = ctx->listStats[mDpy].lRoi;
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800601 dst = getIntersection(dst, roi);
602 crop = dst;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800603}
604
605/* 1) Identify layers that are not visible or lying outside the updating ROI and
606 * drop them from composition.
607 * 2) If we have a scaling layer which needs cropping against generated
608 * ROI, reset ROI to full resolution. */
609bool MDPCompNonSplit::validateAndApplyROI(hwc_context_t *ctx,
610 hwc_display_contents_1_t* list) {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700611 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800612 hwc_rect_t visibleRect = ctx->listStats[mDpy].lRoi;
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800613
614 for(int i = numAppLayers - 1; i >= 0; i--){
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800615 if(!isValidRect(visibleRect)) {
616 mCurrentFrame.drop[i] = true;
617 mCurrentFrame.dropCount++;
Jeykumar Sankaran0b961452014-01-21 17:26:12 -0800618 continue;
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800619 }
620
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700621 const hwc_layer_1_t* layer = &list->hwLayers[i];
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700622 hwc_rect_t dstRect = layer->displayFrame;
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800623 hwc_rect_t res = getIntersection(visibleRect, dstRect);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700624
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700625 if(!isValidRect(res)) {
626 mCurrentFrame.drop[i] = true;
627 mCurrentFrame.dropCount++;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800628 } else {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700629 /* Reset frame ROI when any layer which needs scaling also needs ROI
630 * cropping */
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800631 if(!isSameRect(res, dstRect) && needsScaling (layer)) {
Arpita Banerjeed8965982013-11-08 17:27:33 -0800632 ALOGI("%s: Resetting ROI due to scaling", __FUNCTION__);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700633 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
634 mCurrentFrame.dropCount = 0;
635 return false;
636 }
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800637
Jeykumar Sankaran0b961452014-01-21 17:26:12 -0800638 /* deduct any opaque region from visibleRect */
radhakrishna4efbdd62014-11-03 13:19:27 +0530639 if (layer->blending == HWC_BLENDING_NONE &&
640 layer->planeAlpha == 0xFF)
Jeykumar Sankaran0b961452014-01-21 17:26:12 -0800641 visibleRect = deductRect(visibleRect, res);
642 }
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700643 }
644 return true;
645}
646
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800647/* Calculate ROI for the frame by accounting all the layer's dispalyFrame which
648 * are updating. If DirtyRegion is applicable, calculate it by accounting all
649 * the changing layer's dirtyRegion. */
650void MDPCompNonSplit::generateROI(hwc_context_t *ctx,
651 hwc_display_contents_1_t* list) {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700652 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800653 if(!canPartialUpdate(ctx, list))
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700654 return;
655
656 struct hwc_rect roi = (struct hwc_rect){0, 0, 0, 0};
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800657 hwc_rect fullFrame = (struct hwc_rect) {0, 0,(int)ctx->dpyAttr[mDpy].xres,
658 (int)ctx->dpyAttr[mDpy].yres};
659
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700660 for(int index = 0; index < numAppLayers; index++ ) {
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800661 hwc_layer_1_t* layer = &list->hwLayers[index];
662 if ((mCachedFrame.hnd[index] != layer->handle) ||
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800663 isYuvBuffer((private_handle_t *)layer->handle)) {
Jeykumar Sankaran455678c2014-05-30 10:22:38 -0700664 hwc_rect_t dst = layer->displayFrame;
665 hwc_rect_t updatingRect = dst;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800666
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800667#ifdef QCOM_BSP
Dileep Kumar Reddi7399d5c2014-12-31 18:01:19 +0530668 if(!needsScaling(layer) && !layer->transform &&
669 (!isYuvBuffer((private_handle_t *)layer->handle)))
Jeykumar Sankaran455678c2014-05-30 10:22:38 -0700670 {
671 hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
672 int x_off = dst.left - src.left;
673 int y_off = dst.top - src.top;
674 updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
675 }
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800676#endif
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800677
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800678 roi = getUnion(roi, updatingRect);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700679 }
680 }
681
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800682 /* No layer is updating. Still SF wants a refresh.*/
683 if(!isValidRect(roi))
684 return;
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800685
686 // Align ROI coordinates to panel restrictions
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800687 roi = getSanitizeROI(roi, fullFrame);
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800688
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800689 ctx->listStats[mDpy].lRoi = roi;
690 if(!validateAndApplyROI(ctx, list))
691 resetROI(ctx, mDpy);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700692
693 ALOGD_IF(isDebug(),"%s: generated ROI: [%d, %d, %d, %d]", __FUNCTION__,
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800694 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
695 ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom);
696}
697
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800698void MDPCompSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect &crop,
699 hwc_rect &dst) {
700 hwc_rect roi = getUnion(ctx->listStats[mDpy].lRoi,
701 ctx->listStats[mDpy].rRoi);
702 hwc_rect tmpDst = getIntersection(dst, roi);
703 if(!isSameRect(dst, tmpDst)) {
704 crop.left = crop.left + (tmpDst.left - dst.left);
705 crop.top = crop.top + (tmpDst.top - dst.top);
706 crop.right = crop.left + (tmpDst.right - tmpDst.left);
707 crop.bottom = crop.top + (tmpDst.bottom - tmpDst.top);
708 dst = tmpDst;
709 }
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800710}
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800711
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800712/* 1) Identify layers that are not visible or lying outside BOTH the updating
713 * ROI's and drop them from composition. If a layer is spanning across both
714 * the halves of the screen but needed by only ROI, the non-contributing
715 * half will not be programmed for MDP.
716 * 2) If we have a scaling layer which needs cropping against generated
717 * ROI, reset ROI to full resolution. */
718bool MDPCompSplit::validateAndApplyROI(hwc_context_t *ctx,
719 hwc_display_contents_1_t* list) {
720
721 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
722
723 hwc_rect_t visibleRectL = ctx->listStats[mDpy].lRoi;
724 hwc_rect_t visibleRectR = ctx->listStats[mDpy].rRoi;
725
726 for(int i = numAppLayers - 1; i >= 0; i--){
727 if(!isValidRect(visibleRectL) && !isValidRect(visibleRectR))
728 {
729 mCurrentFrame.drop[i] = true;
730 mCurrentFrame.dropCount++;
731 continue;
732 }
733
734 const hwc_layer_1_t* layer = &list->hwLayers[i];
735 hwc_rect_t dstRect = layer->displayFrame;
736
737 hwc_rect_t l_res = getIntersection(visibleRectL, dstRect);
738 hwc_rect_t r_res = getIntersection(visibleRectR, dstRect);
739 hwc_rect_t res = getUnion(l_res, r_res);
740
741 if(!isValidRect(l_res) && !isValidRect(r_res)) {
742 mCurrentFrame.drop[i] = true;
743 mCurrentFrame.dropCount++;
744 } else {
745 /* Reset frame ROI when any layer which needs scaling also needs ROI
746 * cropping */
747 if(!isSameRect(res, dstRect) && needsScaling (layer)) {
748 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
749 mCurrentFrame.dropCount = 0;
750 return false;
751 }
752
radhakrishna4efbdd62014-11-03 13:19:27 +0530753 if (layer->blending == HWC_BLENDING_NONE &&
754 layer->planeAlpha == 0xFF) {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800755 visibleRectL = deductRect(visibleRectL, l_res);
756 visibleRectR = deductRect(visibleRectR, r_res);
757 }
758 }
759 }
760 return true;
761}
762/* Calculate ROI for the frame by accounting all the layer's dispalyFrame which
763 * are updating. If DirtyRegion is applicable, calculate it by accounting all
764 * the changing layer's dirtyRegion. */
765void MDPCompSplit::generateROI(hwc_context_t *ctx,
766 hwc_display_contents_1_t* list) {
767 if(!canPartialUpdate(ctx, list))
768 return;
769
770 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
771 int lSplit = getLeftSplit(ctx, mDpy);
772
773 int hw_h = (int)ctx->dpyAttr[mDpy].yres;
774 int hw_w = (int)ctx->dpyAttr[mDpy].xres;
775
776 struct hwc_rect l_frame = (struct hwc_rect){0, 0, lSplit, hw_h};
777 struct hwc_rect r_frame = (struct hwc_rect){lSplit, 0, hw_w, hw_h};
778
779 struct hwc_rect l_roi = (struct hwc_rect){0, 0, 0, 0};
780 struct hwc_rect r_roi = (struct hwc_rect){0, 0, 0, 0};
781
782 for(int index = 0; index < numAppLayers; index++ ) {
783 hwc_layer_1_t* layer = &list->hwLayers[index];
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800784 private_handle_t *hnd = (private_handle_t *)layer->handle;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800785 if ((mCachedFrame.hnd[index] != layer->handle) ||
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800786 isYuvBuffer(hnd)) {
Jeykumar Sankaran71e597c2014-05-07 16:23:14 -0700787 hwc_rect_t dst = layer->displayFrame;
788 hwc_rect_t updatingRect = dst;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800789
790#ifdef QCOM_BSP
791 if(!needsScaling(layer) && !layer->transform)
Jeykumar Sankaran71e597c2014-05-07 16:23:14 -0700792 {
793 hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
794 int x_off = dst.left - src.left;
795 int y_off = dst.top - src.top;
796 updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
797 }
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800798#endif
799
800 hwc_rect_t l_dst = getIntersection(l_frame, updatingRect);
801 if(isValidRect(l_dst))
802 l_roi = getUnion(l_roi, l_dst);
803
804 hwc_rect_t r_dst = getIntersection(r_frame, updatingRect);
805 if(isValidRect(r_dst))
806 r_roi = getUnion(r_roi, r_dst);
807 }
808 }
809
Jeykumar Sankarana40a9342014-04-25 09:37:10 -0700810 /* For panels that cannot accept commands in both the interfaces, we cannot
811 * send two ROI's (for each half). We merge them into single ROI and split
812 * them across lSplit for MDP mixer use. The ROI's will be merged again
813 * finally before udpating the panel in the driver. */
814 if(qdutils::MDPVersion::getInstance().needsROIMerge()) {
815 hwc_rect_t temp_roi = getUnion(l_roi, r_roi);
816 l_roi = getIntersection(temp_roi, l_frame);
817 r_roi = getIntersection(temp_roi, r_frame);
818 }
819
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800820 /* No layer is updating. Still SF wants a refresh. */
821 if(!isValidRect(l_roi) && !isValidRect(r_roi))
822 return;
823
824 l_roi = getSanitizeROI(l_roi, l_frame);
825 r_roi = getSanitizeROI(r_roi, r_frame);
826
827 ctx->listStats[mDpy].lRoi = l_roi;
828 ctx->listStats[mDpy].rRoi = r_roi;
829
830 if(!validateAndApplyROI(ctx, list))
831 resetROI(ctx, mDpy);
832
833 ALOGD_IF(isDebug(),"%s: generated L_ROI: [%d, %d, %d, %d]"
834 "R_ROI: [%d, %d, %d, %d]", __FUNCTION__,
835 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
836 ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom,
837 ctx->listStats[mDpy].rRoi.left, ctx->listStats[mDpy].rRoi.top,
838 ctx->listStats[mDpy].rRoi.right, ctx->listStats[mDpy].rRoi.bottom);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700839}
840
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800841/* Checks for conditions where all the layers marked for MDP comp cannot be
842 * bypassed. On such conditions we try to bypass atleast YUV layers */
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800843bool MDPComp::tryFullFrame(hwc_context_t *ctx,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800844 hwc_display_contents_1_t* list){
845
Saurabh Shahaa236822013-04-24 18:07:26 -0700846 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800847
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -0700848 // Fall back to video only composition, if AIV video mode is enabled
849 if(ctx->listStats[mDpy].mAIVVideoMode) {
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -0700850 ALOGD_IF(isDebug(), "%s: AIV Video Mode enabled dpy %d",
851 __FUNCTION__, mDpy);
852 return false;
853 }
854
Praveena Pachipulusu47346c22014-12-04 11:06:41 +0530855 /* No Idle fall back if secure display or secure RGB layers are present
856 * or if there is only a single layer being composed */
857 if(sIdleFallBack && !ctx->listStats[mDpy].secureUI &&
858 !ctx->listStats[mDpy].secureRGBCount &&
859 (ctx->listStats[mDpy].numAppLayers > 1)) {
Saurabh Shah2d998a92013-05-14 17:55:58 -0700860 ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
861 return false;
862 }
863
Raj Kamalc0d34242015-03-17 20:53:14 +0530864 if(!mDpy && isSecondaryAnimating(ctx) &&
865 (isYuvPresent(ctx,HWC_DISPLAY_EXTERNAL) ||
866 isYuvPresent(ctx,HWC_DISPLAY_VIRTUAL)) ) {
867 ALOGD_IF(isDebug(),"%s: Display animation in progress",
868 __FUNCTION__);
869 return false;
870 }
871
Ramkumar Radhakrishnanf26fe9e2014-09-09 13:47:54 -0700872 // if secondary is configuring or Padding round, fall back to video only
873 // composition and release all assigned non VIG pipes from primary.
874 if(isSecondaryConfiguring(ctx)) {
875 ALOGD_IF( isDebug(),"%s: External Display connection is pending",
876 __FUNCTION__);
877 return false;
878 } else if(ctx->isPaddingRound) {
879 ALOGD_IF(isDebug(), "%s: padding round invoked for dpy %d",
880 __FUNCTION__,mDpy);
881 return false;
882 }
883
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -0500884 // No MDP composition for 3D
885 if(needs3DComposition(ctx, mDpy))
886 return false;
887
Tatenda Chipeperekwacb2a2432014-08-06 17:45:58 -0700888 // check for action safe flag and MDP scaling mode which requires scaling.
Ramkumar Radhakrishnan4af1ef02013-12-12 11:53:08 -0800889 if(ctx->dpyAttr[mDpy].mActionSafePresent
Tatenda Chipeperekwacb2a2432014-08-06 17:45:58 -0700890 || ctx->dpyAttr[mDpy].mMDPScalingMode) {
Ramkumar Radhakrishnan4af1ef02013-12-12 11:53:08 -0800891 ALOGD_IF(isDebug(), "%s: Scaling needed for this frame",__FUNCTION__);
892 return false;
893 }
894
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800895 for(int i = 0; i < numAppLayers; ++i) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800896 hwc_layer_1_t* layer = &list->hwLayers[i];
897 private_handle_t *hnd = (private_handle_t *)layer->handle;
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -0800898
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800899 if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700900 if(!canUseRotator(ctx, mDpy)) {
901 ALOGD_IF(isDebug(), "%s: Can't use rotator for dpy %d",
902 __FUNCTION__, mDpy);
Amara Venkata Mastan Manoj Kumar9d373c02013-08-20 14:30:09 -0700903 return false;
904 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800905 }
Prabhanjan Kandula9fb032a2013-06-18 17:37:22 +0530906
907 //For 8x26 with panel width>1k, if RGB layer needs HFLIP fail mdp comp
908 // may not need it if Gfx pre-rotation can handle all flips & rotations
Saurabh Shahcad57772014-12-01 14:19:51 -0800909 MDPVersion& mdpHw = MDPVersion::getInstance();
Sushil Chauhanfda00fc2014-03-20 11:08:41 -0700910 int transform = (layer->flags & HWC_COLOR_FILL) ? 0 : layer->transform;
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530911 if( mdpHw.is8x26() && (ctx->dpyAttr[mDpy].xres > 1024) &&
912 (transform & HWC_TRANSFORM_FLIP_H) && (!isYuvBuffer(hnd)))
913 return false;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800914 }
Saurabh Shahaa236822013-04-24 18:07:26 -0700915
Saurabh Shaha9da08f2013-07-03 13:27:53 -0700916 if(ctx->mAD->isDoable()) {
917 return false;
918 }
919
Saurabh Shahaa236822013-04-24 18:07:26 -0700920 //If all above hard conditions are met we can do full or partial MDP comp.
921 bool ret = false;
922 if(fullMDPComp(ctx, list)) {
923 ret = true;
Sushil Chauhandefd3522014-05-13 18:17:12 -0700924 } else if(fullMDPCompWithPTOR(ctx, list)) {
925 ret = true;
Jeykumar Sankaran24c199d2013-05-24 09:40:36 -0700926 } else if(partialMDPComp(ctx, list)) {
Saurabh Shahaa236822013-04-24 18:07:26 -0700927 ret = true;
928 }
Prabhanjan Kandula21918db2013-11-26 15:51:58 +0530929
Saurabh Shahaa236822013-04-24 18:07:26 -0700930 return ret;
931}
932
933bool MDPComp::fullMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -0700934
935 if(sSimulationFlags & MDPCOMP_AVOID_FULL_MDP)
936 return false;
937
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700938 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
939 for(int i = 0; i < numAppLayers; i++) {
940 hwc_layer_1_t* layer = &list->hwLayers[i];
Jeykumar Sankaran880da832014-04-18 10:22:35 -0700941 if(not mCurrentFrame.drop[i] and
942 not isSupportedForMDPComp(ctx, layer)) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700943 ALOGD_IF(isDebug(), "%s: Unsupported layer in list",__FUNCTION__);
944 return false;
945 }
946 }
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800947
Raj Kamalb5f0b4a2015-04-08 15:10:37 +0530948 if(!mDpy && isSecondaryConnected(ctx) &&
949 (qdutils::MDPVersion::getInstance().is8x16() ||
950 qdutils::MDPVersion::getInstance().is8x26() ||
951 qdutils::MDPVersion::getInstance().is8x39()) &&
952 isYuvPresent(ctx, HWC_DISPLAY_VIRTUAL)) {
953 ALOGD_IF(isDebug(), "%s: YUV layer present on secondary", __FUNCTION__);
954 return false;
955 }
956
Saurabh Shahaa236822013-04-24 18:07:26 -0700957 mCurrentFrame.fbCount = 0;
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700958 memcpy(&mCurrentFrame.isFBComposed, &mCurrentFrame.drop,
959 sizeof(mCurrentFrame.isFBComposed));
960 mCurrentFrame.mdpCount = mCurrentFrame.layerCount - mCurrentFrame.fbCount -
961 mCurrentFrame.dropCount;
Saurabh Shahaa236822013-04-24 18:07:26 -0700962
Raj Kamal389d6e32014-08-04 14:43:24 +0530963 if(sEnableYUVsplit){
Saurabh Shah3d4b8042013-12-10 15:19:17 -0800964 adjustForSourceSplit(ctx, list);
radhakrishnac9a67412013-09-25 17:40:42 +0530965 }
966
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800967 if(!postHeuristicsHandling(ctx, list)) {
968 ALOGD_IF(isDebug(), "post heuristic handling failed");
969 reset(ctx);
Saurabh Shah8c5c8522013-08-29 17:32:49 -0700970 return false;
971 }
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -0700972 ALOGD_IF(sSimulationFlags,"%s: FULL_MDP_COMP SUCCEEDED",
973 __FUNCTION__);
Saurabh Shahaa236822013-04-24 18:07:26 -0700974 return true;
975}
976
Sushil Chauhandefd3522014-05-13 18:17:12 -0700977/* Full MDP Composition with Peripheral Tiny Overlap Removal.
978 * MDP bandwidth limitations can be avoided, if the overlap region
979 * covered by the smallest layer at a higher z-order, gets composed
980 * by Copybit on a render buffer, which can be queued to MDP.
981 */
982bool MDPComp::fullMDPCompWithPTOR(hwc_context_t *ctx,
983 hwc_display_contents_1_t* list) {
984
985 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Arun Kumar K.R00b84792015-03-27 11:28:36 -0700986 // PTOR does not qualify when there are layers dropped, but if
987 // dropped layer is only a cursor, PTOR could qualify
988 const int numNonCursorLayers = numAppLayers - mCurrentFrame.dropCount;
Sushil Chauhandefd3522014-05-13 18:17:12 -0700989 const int stagesForMDP = min(sMaxPipesPerMixer,
990 ctx->mOverlay->availablePipes(mDpy, Overlay::MIXER_DEFAULT));
991
992 // Hard checks where we cannot use this mode
Sushil Chauhanbfc2de02014-07-24 11:52:58 -0700993 if (mDpy || !ctx->mCopyBit[mDpy]) {
Sushil Chauhandefd3522014-05-13 18:17:12 -0700994 ALOGD_IF(isDebug(), "%s: Feature not supported!", __FUNCTION__);
995 return false;
996 }
997
Arun Kumar K.R00b84792015-03-27 11:28:36 -0700998 // Frame level checks - consider PTOR in case of dropCount only if the cursor
999 // layer is dropped, otherwise bail out of PTOR
Sushil Chauhandefd3522014-05-13 18:17:12 -07001000 if ((numAppLayers > stagesForMDP) || isSkipPresent(ctx, mDpy) ||
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001001 isYuvPresent(ctx, mDpy) || isSecurePresent(ctx, mDpy) ||
1002 (mCurrentFrame.dropCount - (int)isCursorPresent(ctx, mDpy))) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001003 ALOGD_IF(isDebug(), "%s: Frame not supported!", __FUNCTION__);
1004 return false;
1005 }
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001006 // MDP comp checks
1007 for(int i = 0; i < numAppLayers; i++) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001008 hwc_layer_1_t* layer = &list->hwLayers[i];
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001009 if(not isSupportedForMDPComp(ctx, layer)) {
1010 ALOGD_IF(isDebug(), "%s: Unsupported layer in list",__FUNCTION__);
1011 return false;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001012 }
1013 }
1014
Raj Kamalb5f0b4a2015-04-08 15:10:37 +05301015 if(!mDpy && isSecondaryConnected(ctx) &&
1016 (qdutils::MDPVersion::getInstance().is8x16() ||
1017 qdutils::MDPVersion::getInstance().is8x26() ||
1018 qdutils::MDPVersion::getInstance().is8x39()) &&
1019 isYuvPresent(ctx, HWC_DISPLAY_VIRTUAL)) {
1020 ALOGD_IF(isDebug(), "%s: YUV layer present on secondary", __FUNCTION__);
1021 return false;
1022 }
1023
Sushil Chauhandefd3522014-05-13 18:17:12 -07001024 /* We cannot use this composition mode, if:
1025 1. A below layer needs scaling.
1026 2. Overlap is not peripheral to display.
1027 3. Overlap or a below layer has 90 degree transform.
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001028 4. Overlap area > (1/3 * FrameBuffer) area, based on Perf inputs.
Sushil Chauhandefd3522014-05-13 18:17:12 -07001029 */
1030
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001031 int minLayerIndex[MAX_PTOR_LAYERS] = { -1, -1};
1032 hwc_rect_t overlapRect[MAX_PTOR_LAYERS];
1033 memset(overlapRect, 0, sizeof(overlapRect));
1034 int layerPixelCount, minPixelCount = 0;
1035 int numPTORLayersFound = 0;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001036 for (int i = numNonCursorLayers - 1; (i >= 0 &&
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001037 numPTORLayersFound < MAX_PTOR_LAYERS); i--) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001038 hwc_layer_1_t* layer = &list->hwLayers[i];
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001039 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
Sushil Chauhandefd3522014-05-13 18:17:12 -07001040 hwc_rect_t dispFrame = layer->displayFrame;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001041 layerPixelCount = (crop.right - crop.left) * (crop.bottom - crop.top);
1042 // PTOR layer should be peripheral and cannot have transform
1043 if (!isPeripheral(dispFrame, ctx->mViewFrame[mDpy]) ||
1044 has90Transform(layer)) {
1045 continue;
1046 }
1047 if((3 * (layerPixelCount + minPixelCount)) >
1048 ((int)ctx->dpyAttr[mDpy].xres * (int)ctx->dpyAttr[mDpy].yres)) {
1049 // Overlap area > (1/3 * FrameBuffer) area, based on Perf inputs.
1050 continue;
1051 }
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001052 bool found = false;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001053 for (int j = i-1; j >= 0; j--) {
1054 // Check if the layers below this layer qualifies for PTOR comp
1055 hwc_layer_1_t* layer = &list->hwLayers[j];
1056 hwc_rect_t disFrame = layer->displayFrame;
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001057 // Layer below PTOR is intersecting and has 90 degree transform or
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001058 // needs scaling cannot be supported.
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001059 if (isValidRect(getIntersection(dispFrame, disFrame))) {
1060 if (has90Transform(layer) || needsScaling(layer)) {
1061 found = false;
1062 break;
1063 }
1064 found = true;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001065 }
1066 }
1067 // Store the minLayer Index
1068 if(found) {
1069 minLayerIndex[numPTORLayersFound] = i;
1070 overlapRect[numPTORLayersFound] = list->hwLayers[i].displayFrame;
1071 minPixelCount += layerPixelCount;
1072 numPTORLayersFound++;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001073 }
1074 }
1075
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001076 // No overlap layers
1077 if (!numPTORLayersFound)
1078 return false;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001079
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001080 // Store the displayFrame and the sourceCrops of the layers
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001081 hwc_rect_t displayFrame[numNonCursorLayers];
1082 hwc_rect_t sourceCrop[numNonCursorLayers];
1083 for(int i = 0; i < numNonCursorLayers; i++) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001084 hwc_layer_1_t* layer = &list->hwLayers[i];
1085 displayFrame[i] = layer->displayFrame;
1086 sourceCrop[i] = integerizeSourceCrop(layer->sourceCropf);
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001087 }
Sushil Chauhandefd3522014-05-13 18:17:12 -07001088
Prabhanjan Kandula9889a202014-09-04 21:50:35 +05301089 /**
1090 * It's possible that 2 PTOR layers might have overlapping.
1091 * In such case, remove the intersection(again if peripheral)
1092 * from the lower PTOR layer to avoid overlapping.
1093 * If intersection is not on peripheral then compromise
1094 * by reducing number of PTOR layers.
1095 **/
1096 hwc_rect_t commonRect = getIntersection(overlapRect[0], overlapRect[1]);
1097 if(isValidRect(commonRect)) {
1098 overlapRect[1] = deductRect(overlapRect[1], commonRect);
1099 list->hwLayers[minLayerIndex[1]].displayFrame = overlapRect[1];
1100 }
1101
1102 ctx->mPtorInfo.count = numPTORLayersFound;
1103 for(int i = 0; i < MAX_PTOR_LAYERS; i++) {
1104 ctx->mPtorInfo.layerIndex[i] = minLayerIndex[i];
1105 }
1106
1107 if (!ctx->mCopyBit[mDpy]->prepareOverlap(ctx, list)) {
1108 // reset PTOR
1109 ctx->mPtorInfo.count = 0;
1110 if(isValidRect(commonRect)) {
1111 // If PTORs are intersecting restore displayframe of PTOR[1]
1112 // before returning, as we have modified it above.
1113 list->hwLayers[minLayerIndex[1]].displayFrame =
1114 displayFrame[minLayerIndex[1]];
1115 }
1116 return false;
1117 }
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001118 private_handle_t *renderBuf = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
1119 Whf layerWhf[numPTORLayersFound]; // To store w,h,f of PTOR layers
1120
Xu Yangcda012c2014-07-30 21:57:21 +08001121 // Store the blending mode, planeAlpha, and transform of PTOR layers
1122 int32_t blending[numPTORLayersFound];
1123 uint8_t planeAlpha[numPTORLayersFound];
1124 uint32_t transform[numPTORLayersFound];
1125
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001126 for(int j = 0; j < numPTORLayersFound; j++) {
1127 int index = ctx->mPtorInfo.layerIndex[j];
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001128
1129 // Update src crop of PTOR layer
1130 hwc_layer_1_t* layer = &list->hwLayers[index];
1131 layer->sourceCropf.left = (float)ctx->mPtorInfo.displayFrame[j].left;
1132 layer->sourceCropf.top = (float)ctx->mPtorInfo.displayFrame[j].top;
1133 layer->sourceCropf.right = (float)ctx->mPtorInfo.displayFrame[j].right;
1134 layer->sourceCropf.bottom =(float)ctx->mPtorInfo.displayFrame[j].bottom;
1135
1136 // Store & update w, h, format of PTOR layer
1137 private_handle_t *hnd = (private_handle_t *)layer->handle;
1138 Whf whf(hnd->width, hnd->height, hnd->format, hnd->size);
1139 layerWhf[j] = whf;
1140 hnd->width = renderBuf->width;
1141 hnd->height = renderBuf->height;
1142 hnd->format = renderBuf->format;
1143
Xu Yangcda012c2014-07-30 21:57:21 +08001144 // Store & update blending mode, planeAlpha and transform of PTOR layer
1145 blending[j] = layer->blending;
1146 planeAlpha[j] = layer->planeAlpha;
1147 transform[j] = layer->transform;
1148 layer->blending = HWC_BLENDING_NONE;
1149 layer->planeAlpha = 0xFF;
1150 layer->transform = 0;
1151
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001152 // Remove overlap from crop & displayFrame of below layers
1153 for (int i = 0; i < index && index !=-1; i++) {
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001154 layer = &list->hwLayers[i];
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001155 if(!isValidRect(getIntersection(layer->displayFrame,
1156 overlapRect[j]))) {
1157 continue;
1158 }
1159 // Update layer attributes
1160 hwc_rect_t srcCrop = integerizeSourceCrop(layer->sourceCropf);
1161 hwc_rect_t destRect = deductRect(layer->displayFrame,
Dileep Kumar Reddi72058b82014-11-11 16:03:03 +05301162 getIntersection(layer->displayFrame, overlapRect[j]));
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001163 qhwc::calculate_crop_rects(srcCrop, layer->displayFrame, destRect,
1164 layer->transform);
1165 layer->sourceCropf.left = (float)srcCrop.left;
1166 layer->sourceCropf.top = (float)srcCrop.top;
1167 layer->sourceCropf.right = (float)srcCrop.right;
1168 layer->sourceCropf.bottom = (float)srcCrop.bottom;
1169 }
Sushil Chauhandefd3522014-05-13 18:17:12 -07001170 }
1171
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001172 mCurrentFrame.mdpCount = numNonCursorLayers;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001173 mCurrentFrame.fbCount = 0;
1174 mCurrentFrame.fbZ = -1;
1175
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001176 for (int j = 0; j < numNonCursorLayers; j++) {
Dileep Kumar Reddi72058b82014-11-11 16:03:03 +05301177 if(isValidRect(list->hwLayers[j].displayFrame)) {
1178 mCurrentFrame.isFBComposed[j] = false;
1179 } else {
1180 mCurrentFrame.mdpCount--;
1181 mCurrentFrame.drop[j] = true;
1182 }
1183 }
Sushil Chauhandefd3522014-05-13 18:17:12 -07001184
1185 bool result = postHeuristicsHandling(ctx, list);
1186
1187 // Restore layer attributes
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001188 for(int i = 0; i < numNonCursorLayers; i++) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001189 hwc_layer_1_t* layer = &list->hwLayers[i];
1190 layer->displayFrame = displayFrame[i];
1191 layer->sourceCropf.left = (float)sourceCrop[i].left;
1192 layer->sourceCropf.top = (float)sourceCrop[i].top;
1193 layer->sourceCropf.right = (float)sourceCrop[i].right;
1194 layer->sourceCropf.bottom = (float)sourceCrop[i].bottom;
1195 }
1196
Xu Yangcda012c2014-07-30 21:57:21 +08001197 // Restore w,h,f, blending attributes, and transform of PTOR layers
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001198 for (int i = 0; i < numPTORLayersFound; i++) {
1199 int idx = ctx->mPtorInfo.layerIndex[i];
Xu Yangcda012c2014-07-30 21:57:21 +08001200 hwc_layer_1_t* layer = &list->hwLayers[idx];
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001201 private_handle_t *hnd = (private_handle_t *)list->hwLayers[idx].handle;
1202 hnd->width = layerWhf[i].w;
1203 hnd->height = layerWhf[i].h;
1204 hnd->format = layerWhf[i].format;
Xu Yangcda012c2014-07-30 21:57:21 +08001205 layer->blending = blending[i];
1206 layer->planeAlpha = planeAlpha[i];
1207 layer->transform = transform[i];
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001208 }
1209
Sushil Chauhandefd3522014-05-13 18:17:12 -07001210 if (!result) {
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001211 // reset PTOR
1212 ctx->mPtorInfo.count = 0;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001213 reset(ctx);
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001214 } else {
1215 ALOGD_IF(isDebug(), "%s: PTOR Indexes: %d and %d", __FUNCTION__,
1216 ctx->mPtorInfo.layerIndex[0], ctx->mPtorInfo.layerIndex[1]);
Sushil Chauhandefd3522014-05-13 18:17:12 -07001217 }
1218
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001219 ALOGD_IF(isDebug(), "%s: Postheuristics %s!", __FUNCTION__,
1220 (result ? "successful" : "failed"));
Sushil Chauhandefd3522014-05-13 18:17:12 -07001221 return result;
1222}
1223
Saurabh Shahaa236822013-04-24 18:07:26 -07001224bool MDPComp::partialMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list)
1225{
radhakrishnac3198ff2015-03-10 17:10:02 +05301226 if(!sEnableMixedMode || !isAlphaPresentinFB(ctx, mDpy)) {
1227 //Mixed mode is disabled/can't be used. No need to even try caching.
Jeykumar Sankaran24c199d2013-05-24 09:40:36 -07001228 return false;
1229 }
1230
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001231 bool ret = false;
Raj Kamal1179d9c2014-10-28 15:31:35 +05301232 if(isSkipPresent(ctx, mDpy) or list->flags & HWC_GEOMETRY_CHANGED) {
1233 //Try load based first
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001234 ret = loadBasedComp(ctx, list) or
Saurabh Shahf2de00f2013-12-11 17:52:53 -08001235 cacheBasedComp(ctx, list);
1236 } else {
1237 ret = cacheBasedComp(ctx, list) or
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001238 loadBasedComp(ctx, list);
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001239 }
1240
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001241 return ret;
1242}
1243
1244bool MDPComp::cacheBasedComp(hwc_context_t *ctx,
1245 hwc_display_contents_1_t* list) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001246 if(sSimulationFlags & MDPCOMP_AVOID_CACHE_MDP)
1247 return false;
1248
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001249 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shahaa236822013-04-24 18:07:26 -07001250 mCurrentFrame.reset(numAppLayers);
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001251 updateLayerCache(ctx, list, mCurrentFrame);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001252
1253 //If an MDP marked layer is unsupported cannot do partial MDP Comp
1254 for(int i = 0; i < numAppLayers; i++) {
1255 if(!mCurrentFrame.isFBComposed[i]) {
1256 hwc_layer_1_t* layer = &list->hwLayers[i];
1257 if(not isSupportedForMDPComp(ctx, layer)) {
1258 ALOGD_IF(isDebug(), "%s: Unsupported layer in list",
1259 __FUNCTION__);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001260 reset(ctx);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001261 return false;
1262 }
1263 }
1264 }
1265
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001266 updateYUV(ctx, list, false /*secure only*/, mCurrentFrame);
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001267 /* mark secure RGB layers for MDP comp */
1268 updateSecureRGB(ctx, list);
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301269 bool ret = markLayersForCaching(ctx, list); //sets up fbZ also
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001270 if(!ret) {
1271 ALOGD_IF(isDebug(),"%s: batching failed, dpy %d",__FUNCTION__, mDpy);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001272 reset(ctx);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001273 return false;
1274 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001275
1276 int mdpCount = mCurrentFrame.mdpCount;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001277
Raj Kamal389d6e32014-08-04 14:43:24 +05301278 if(sEnableYUVsplit){
Saurabh Shah3d4b8042013-12-10 15:19:17 -08001279 adjustForSourceSplit(ctx, list);
radhakrishnac9a67412013-09-25 17:40:42 +05301280 }
1281
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001282 if(!postHeuristicsHandling(ctx, list)) {
1283 ALOGD_IF(isDebug(), "post heuristic handling failed");
1284 reset(ctx);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07001285 return false;
1286 }
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001287 ALOGD_IF(sSimulationFlags,"%s: CACHE_MDP_COMP SUCCEEDED",
1288 __FUNCTION__);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07001289
Saurabh Shahaa236822013-04-24 18:07:26 -07001290 return true;
1291}
1292
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001293bool MDPComp::loadBasedComp(hwc_context_t *ctx,
Saurabh Shahb772ae32013-11-18 15:40:02 -08001294 hwc_display_contents_1_t* list) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001295 if(sSimulationFlags & MDPCOMP_AVOID_LOAD_MDP)
1296 return false;
1297
Arun Kumar K.R2aa44c62014-01-21 23:08:28 -08001298 if(not isLoadBasedCompDoable(ctx)) {
Saurabh Shahf2de00f2013-12-11 17:52:53 -08001299 return false;
1300 }
1301
Saurabh Shahb772ae32013-11-18 15:40:02 -08001302 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001303 const int numNonDroppedLayers = numAppLayers - mCurrentFrame.dropCount;
1304 const int stagesForMDP = min(sMaxPipesPerMixer,
1305 ctx->mOverlay->availablePipes(mDpy, Overlay::MIXER_DEFAULT));
Saurabh Shahf2de00f2013-12-11 17:52:53 -08001306
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001307 int mdpBatchSize = stagesForMDP - 1; //1 stage for FB
1308 int fbBatchSize = numNonDroppedLayers - mdpBatchSize;
1309 int lastMDPSupportedIndex = numAppLayers;
1310 int dropCount = 0;
Saurabh Shahb772ae32013-11-18 15:40:02 -08001311
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001312 //Find the minimum MDP batch size
1313 for(int i = 0; i < numAppLayers;i++) {
1314 if(mCurrentFrame.drop[i]) {
1315 dropCount++;
Jeykumar Sankaran846e2792014-01-23 21:59:58 -08001316 continue;
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001317 }
1318 hwc_layer_1_t* layer = &list->hwLayers[i];
1319 if(not isSupportedForMDPComp(ctx, layer)) {
1320 lastMDPSupportedIndex = i;
1321 mdpBatchSize = min(i - dropCount, stagesForMDP - 1);
1322 fbBatchSize = numNonDroppedLayers - mdpBatchSize;
Jeykumar Sankaran846e2792014-01-23 21:59:58 -08001323 break;
Saurabh Shahb772ae32013-11-18 15:40:02 -08001324 }
Saurabh Shahb772ae32013-11-18 15:40:02 -08001325 }
1326
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001327 ALOGD_IF(isDebug(), "%s:Before optimizing fbBatch, mdpbatch %d, fbbatch %d "
1328 "dropped %d", __FUNCTION__, mdpBatchSize, fbBatchSize,
1329 mCurrentFrame.dropCount);
1330
1331 //Start at a point where the fb batch should at least have 2 layers, for
1332 //this mode to be justified.
1333 while(fbBatchSize < 2) {
1334 ++fbBatchSize;
1335 --mdpBatchSize;
Jeykumar Sankaran846e2792014-01-23 21:59:58 -08001336 }
Saurabh Shahb772ae32013-11-18 15:40:02 -08001337
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001338 //If there are no layers for MDP, this mode doesnt make sense.
1339 if(mdpBatchSize < 1) {
1340 ALOGD_IF(isDebug(), "%s: No MDP layers after optimizing for fbBatch",
1341 __FUNCTION__);
Saurabh Shahb772ae32013-11-18 15:40:02 -08001342 return false;
1343 }
1344
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001345 mCurrentFrame.reset(numAppLayers);
1346
1347 //Try with successively smaller mdp batch sizes until we succeed or reach 1
1348 while(mdpBatchSize > 0) {
1349 //Mark layers for MDP comp
1350 int mdpBatchLeft = mdpBatchSize;
1351 for(int i = 0; i < lastMDPSupportedIndex and mdpBatchLeft; i++) {
1352 if(mCurrentFrame.drop[i]) {
1353 continue;
1354 }
1355 mCurrentFrame.isFBComposed[i] = false;
1356 --mdpBatchLeft;
1357 }
1358
1359 mCurrentFrame.fbZ = mdpBatchSize;
1360 mCurrentFrame.fbCount = fbBatchSize;
1361 mCurrentFrame.mdpCount = mdpBatchSize;
1362
1363 ALOGD_IF(isDebug(), "%s:Trying with: mdpbatch %d fbbatch %d dropped %d",
1364 __FUNCTION__, mdpBatchSize, fbBatchSize,
1365 mCurrentFrame.dropCount);
1366
1367 if(postHeuristicsHandling(ctx, list)) {
1368 ALOGD_IF(isDebug(), "%s: Postheuristics handling succeeded",
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001369 __FUNCTION__);
1370 ALOGD_IF(sSimulationFlags,"%s: LOAD_MDP_COMP SUCCEEDED",
1371 __FUNCTION__);
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001372 return true;
1373 }
1374
1375 reset(ctx);
1376 --mdpBatchSize;
1377 ++fbBatchSize;
1378 }
1379
1380 return false;
Saurabh Shahb772ae32013-11-18 15:40:02 -08001381}
1382
Arun Kumar K.R2aa44c62014-01-21 23:08:28 -08001383bool MDPComp::isLoadBasedCompDoable(hwc_context_t *ctx) {
Prabhanjan Kandula3dbbd882013-12-11 14:43:46 +05301384 if(mDpy or isSecurePresent(ctx, mDpy) or
1385 isYuvPresent(ctx, mDpy)) {
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001386 return false;
1387 }
1388 return true;
1389}
1390
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001391bool MDPComp::canPartialUpdate(hwc_context_t *ctx,
1392 hwc_display_contents_1_t* list){
1393 if(!qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() ||
1394 isSkipPresent(ctx, mDpy) || (list->flags & HWC_GEOMETRY_CHANGED) ||
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001395 isCursorPresent(ctx, mDpy) || !sIsPartialUpdateActive || mDpy) {
1396 // On Async position update, the ROI becomes invalid, hence disable PU
1397 // when cursor is present
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001398 return false;
1399 }
Jeykumar Sankaran4dd10ab2014-07-02 12:23:09 -07001400 if(ctx->listStats[mDpy].secureUI)
1401 return false;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001402 return true;
1403}
1404
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001405bool MDPComp::tryVideoOnly(hwc_context_t *ctx,
1406 hwc_display_contents_1_t* list) {
1407 const bool secureOnly = true;
1408 return videoOnlyComp(ctx, list, not secureOnly) or
1409 videoOnlyComp(ctx, list, secureOnly);
1410}
1411
1412bool MDPComp::videoOnlyComp(hwc_context_t *ctx,
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001413 hwc_display_contents_1_t* list, bool secureOnly) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001414 if(sSimulationFlags & MDPCOMP_AVOID_VIDEO_ONLY)
1415 return false;
Praveena Pachipulusu47346c22014-12-04 11:06:41 +05301416
Saurabh Shahaa236822013-04-24 18:07:26 -07001417 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Praveena Pachipulusu47346c22014-12-04 11:06:41 +05301418 if(!isSecurePresent(ctx, mDpy)) {
1419 /* Bail out if we are processing only secured video layers
1420 * and we dont have any */
1421 if(secureOnly) {
1422 ALOGD_IF(isDebug(),"%s: No Secure Video Layers", __FUNCTION__);
1423 return false;
1424 }
1425 /* No Idle fall back for secure video layers and if there is only
1426 * single layer being composed. */
1427 if(sIdleFallBack && (ctx->listStats[mDpy].numAppLayers > 1)) {
1428 ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
1429 return false;
1430 }
1431 }
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001432
Saurabh Shahaa236822013-04-24 18:07:26 -07001433 mCurrentFrame.reset(numAppLayers);
Jeykumar Sankaraneb3a5e22014-04-08 16:07:55 -07001434 mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001435 updateYUV(ctx, list, secureOnly, mCurrentFrame);
Saurabh Shah4fdde762013-04-30 18:47:33 -07001436 int mdpCount = mCurrentFrame.mdpCount;
Saurabh Shahaa236822013-04-24 18:07:26 -07001437
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001438 if(!isYuvPresent(ctx, mDpy) or (mdpCount == 0)) {
1439 reset(ctx);
Saurabh Shahaa236822013-04-24 18:07:26 -07001440 return false;
1441 }
1442
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001443 if(mCurrentFrame.fbCount)
1444 mCurrentFrame.fbZ = mCurrentFrame.mdpCount;
Saurabh Shah4fdde762013-04-30 18:47:33 -07001445
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05001446 if(sEnableYUVsplit || needs3DComposition(ctx, mDpy)){
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001447 adjustForSourceSplit(ctx, list);
1448 }
1449
1450 if(!postHeuristicsHandling(ctx, list)) {
1451 ALOGD_IF(isDebug(), "post heuristic handling failed");
Justin Philip37ab9a82015-01-06 11:55:12 +05301452 if(errno == ENOBUFS) {
1453 ALOGD_IF(isDebug(), "SMP Allocation failed");
1454 //On SMP allocation failure in video only comp add padding round
1455 ctx->isPaddingRound = true;
1456 }
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001457 reset(ctx);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07001458 return false;
1459 }
1460
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001461 ALOGD_IF(sSimulationFlags,"%s: VIDEO_ONLY_COMP SUCCEEDED",
1462 __FUNCTION__);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001463 return true;
1464}
1465
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001466/* if tryFullFrame fails, try to push all video and secure RGB layers to MDP */
1467bool MDPComp::tryMDPOnlyLayers(hwc_context_t *ctx,
1468 hwc_display_contents_1_t* list) {
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001469 // Fall back to video only composition, if AIV video mode is enabled
1470 if(ctx->listStats[mDpy].mAIVVideoMode) {
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07001471 ALOGD_IF(isDebug(), "%s: AIV Video Mode enabled dpy %d",
1472 __FUNCTION__, mDpy);
1473 return false;
1474 }
1475
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05001476 // No MDP composition for 3D
1477 if(needs3DComposition(ctx,mDpy))
1478 return false;
1479
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001480 const bool secureOnly = true;
1481 return mdpOnlyLayersComp(ctx, list, not secureOnly) or
1482 mdpOnlyLayersComp(ctx, list, secureOnly);
1483
1484}
1485
1486bool MDPComp::mdpOnlyLayersComp(hwc_context_t *ctx,
1487 hwc_display_contents_1_t* list, bool secureOnly) {
1488
1489 if(sSimulationFlags & MDPCOMP_AVOID_MDP_ONLY_LAYERS)
1490 return false;
1491
Praveena Pachipulusu47346c22014-12-04 11:06:41 +05301492 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
1493 if(!isSecurePresent(ctx, mDpy) && !ctx->listStats[mDpy].secureUI) {
1494 /* Bail out if we are processing only secured video/ui layers
1495 * and we dont have any */
1496 if(secureOnly) {
1497 ALOGD_IF(isDebug(), "%s: No secure video/ui layers");
1498 return false;
1499 }
1500 /* No Idle fall back for secure video/ui layers and if there is only
1501 * single layer being composed. */
1502 if(sIdleFallBack && (ctx->listStats[mDpy].numAppLayers > 1)) {
1503 ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
1504 return false;
1505 }
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001506 }
1507
Tatenda Chipeperekwa95675a72014-12-15 17:06:43 -08001508 /* Bail out if we dont have any secure RGB layers */
1509 if (!ctx->listStats[mDpy].secureRGBCount) {
1510 reset(ctx);
1511 return false;
1512 }
1513
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001514 mCurrentFrame.reset(numAppLayers);
1515 mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
1516
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001517 updateYUV(ctx, list, secureOnly, mCurrentFrame);
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001518 /* mark secure RGB layers for MDP comp */
1519 updateSecureRGB(ctx, list);
1520
1521 if(mCurrentFrame.mdpCount == 0) {
1522 reset(ctx);
1523 return false;
1524 }
1525
1526 /* find the maximum batch of layers to be marked for framebuffer */
1527 bool ret = markLayersForCaching(ctx, list); //sets up fbZ also
1528 if(!ret) {
1529 ALOGD_IF(isDebug(),"%s: batching failed, dpy %d",__FUNCTION__, mDpy);
1530 reset(ctx);
1531 return false;
1532 }
1533
1534 if(sEnableYUVsplit){
1535 adjustForSourceSplit(ctx, list);
1536 }
1537
1538 if(!postHeuristicsHandling(ctx, list)) {
1539 ALOGD_IF(isDebug(), "post heuristic handling failed");
1540 reset(ctx);
1541 return false;
1542 }
1543
1544 ALOGD_IF(sSimulationFlags,"%s: MDP_ONLY_LAYERS_COMP SUCCEEDED",
1545 __FUNCTION__);
1546 return true;
1547}
1548
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001549/* Checks for conditions where YUV layers cannot be bypassed */
1550bool MDPComp::isYUVDoable(hwc_context_t* ctx, hwc_layer_1_t* layer) {
Ramkumar Radhakrishnana70981a2013-08-28 11:33:53 -07001551 if(isSkipLayer(layer)) {
Saurabh Shahe2474082013-05-15 16:32:13 -07001552 ALOGD_IF(isDebug(), "%s: Video marked SKIP dpy %d", __FUNCTION__, mDpy);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001553 return false;
1554 }
1555
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08001556 if(has90Transform(layer) && !canUseRotator(ctx, mDpy)) {
Amara Venkata Mastan Manoj Kumar9d373c02013-08-20 14:30:09 -07001557 ALOGD_IF(isDebug(), "%s: no free DMA pipe",__FUNCTION__);
1558 return false;
1559 }
1560
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001561 if(isSecuring(ctx, layer)) {
1562 ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
1563 return false;
1564 }
1565
Saurabh Shah4fdde762013-04-30 18:47:33 -07001566 if(!isValidDimension(ctx, layer)) {
1567 ALOGD_IF(isDebug(), "%s: Buffer is of invalid width",
1568 __FUNCTION__);
1569 return false;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001570 }
Saurabh Shah4fdde762013-04-30 18:47:33 -07001571
Naseer Ahmeddc61a972013-07-10 17:50:54 -04001572 if(layer->planeAlpha < 0xFF) {
1573 ALOGD_IF(isDebug(), "%s: Cannot handle YUV layer with plane alpha\
1574 in video only mode",
1575 __FUNCTION__);
1576 return false;
1577 }
1578
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001579 return true;
1580}
1581
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001582/* Checks for conditions where Secure RGB layers cannot be bypassed */
1583bool MDPComp::isSecureRGBDoable(hwc_context_t* ctx, hwc_layer_1_t* layer) {
1584 if(isSkipLayer(layer)) {
1585 ALOGD_IF(isDebug(), "%s: Secure RGB layer marked SKIP dpy %d",
1586 __FUNCTION__, mDpy);
1587 return false;
1588 }
1589
1590 if(isSecuring(ctx, layer)) {
1591 ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
1592 return false;
1593 }
1594
1595 if(not isSupportedForMDPComp(ctx, layer)) {
1596 ALOGD_IF(isDebug(), "%s: Unsupported secure RGB layer",
1597 __FUNCTION__);
1598 return false;
1599 }
1600 return true;
1601}
1602
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301603/* starts at fromIndex and check for each layer to find
1604 * if it it has overlapping with any Updating layer above it in zorder
1605 * till the end of the batch. returns true if it finds any intersection */
1606bool MDPComp::canPushBatchToTop(const hwc_display_contents_1_t* list,
1607 int fromIndex, int toIndex) {
1608 for(int i = fromIndex; i < toIndex; i++) {
1609 if(mCurrentFrame.isFBComposed[i] && !mCurrentFrame.drop[i]) {
1610 if(intersectingUpdatingLayers(list, i+1, toIndex, i)) {
1611 return false;
1612 }
1613 }
1614 }
1615 return true;
1616}
1617
1618/* Checks if given layer at targetLayerIndex has any
1619 * intersection with all the updating layers in beween
1620 * fromIndex and toIndex. Returns true if it finds intersectiion */
1621bool MDPComp::intersectingUpdatingLayers(const hwc_display_contents_1_t* list,
1622 int fromIndex, int toIndex, int targetLayerIndex) {
1623 for(int i = fromIndex; i <= toIndex; i++) {
1624 if(!mCurrentFrame.isFBComposed[i]) {
1625 if(areLayersIntersecting(&list->hwLayers[i],
1626 &list->hwLayers[targetLayerIndex])) {
1627 return true;
1628 }
1629 }
1630 }
1631 return false;
1632}
1633
1634int MDPComp::getBatch(hwc_display_contents_1_t* list,
1635 int& maxBatchStart, int& maxBatchEnd,
1636 int& maxBatchCount) {
1637 int i = 0;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301638 int fbZOrder =-1;
Jeykumar Sankaran9502f352014-01-20 12:25:32 -08001639 int droppedLayerCt = 0;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301640 while (i < mCurrentFrame.layerCount) {
1641 int batchCount = 0;
1642 int batchStart = i;
1643 int batchEnd = i;
Jeykumar Sankaran9502f352014-01-20 12:25:32 -08001644 /* Adjust batch Z order with the dropped layers so far */
1645 int fbZ = batchStart - droppedLayerCt;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301646 int firstZReverseIndex = -1;
Prabhanjan Kandula0ed2cc92013-12-06 12:39:04 +05301647 int updatingLayersAbove = 0;//Updating layer count in middle of batch
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301648 while(i < mCurrentFrame.layerCount) {
1649 if(!mCurrentFrame.isFBComposed[i]) {
1650 if(!batchCount) {
1651 i++;
1652 break;
1653 }
1654 updatingLayersAbove++;
1655 i++;
1656 continue;
1657 } else {
1658 if(mCurrentFrame.drop[i]) {
1659 i++;
Jeykumar Sankaran9502f352014-01-20 12:25:32 -08001660 droppedLayerCt++;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301661 continue;
1662 } else if(updatingLayersAbove <= 0) {
1663 batchCount++;
1664 batchEnd = i;
1665 i++;
1666 continue;
1667 } else { //Layer is FBComposed, not a drop & updatingLayer > 0
1668
1669 // We have a valid updating layer already. If layer-i not
1670 // have overlapping with all updating layers in between
1671 // batch-start and i, then we can add layer i to batch.
1672 if(!intersectingUpdatingLayers(list, batchStart, i-1, i)) {
1673 batchCount++;
1674 batchEnd = i;
1675 i++;
1676 continue;
1677 } else if(canPushBatchToTop(list, batchStart, i)) {
1678 //If All the non-updating layers with in this batch
1679 //does not have intersection with the updating layers
1680 //above in z-order, then we can safely move the batch to
1681 //higher z-order. Increment fbZ as it is moving up.
1682 if( firstZReverseIndex < 0) {
1683 firstZReverseIndex = i;
1684 }
1685 batchCount++;
1686 batchEnd = i;
1687 fbZ += updatingLayersAbove;
1688 i++;
1689 updatingLayersAbove = 0;
1690 continue;
1691 } else {
1692 //both failed.start the loop again from here.
1693 if(firstZReverseIndex >= 0) {
1694 i = firstZReverseIndex;
1695 }
1696 break;
1697 }
1698 }
1699 }
1700 }
1701 if(batchCount > maxBatchCount) {
1702 maxBatchCount = batchCount;
1703 maxBatchStart = batchStart;
1704 maxBatchEnd = batchEnd;
1705 fbZOrder = fbZ;
1706 }
1707 }
1708 return fbZOrder;
1709}
1710
1711bool MDPComp::markLayersForCaching(hwc_context_t* ctx,
1712 hwc_display_contents_1_t* list) {
1713 /* Idea is to keep as many non-updating(cached) layers in FB and
1714 * send rest of them through MDP. This is done in 2 steps.
1715 * 1. Find the maximum contiguous batch of non-updating layers.
1716 * 2. See if we can improve this batch size for caching by adding
1717 * opaque layers around the batch, if they don't have
1718 * any overlapping with the updating layers in between.
1719 * NEVER mark an updating layer for caching.
1720 * But cached ones can be marked for MDP */
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001721
1722 int maxBatchStart = -1;
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001723 int maxBatchEnd = -1;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001724 int maxBatchCount = 0;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301725 int fbZ = -1;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001726
Saurabh Shahd53bc5f2014-02-05 10:17:43 -08001727 /* Nothing is cached. No batching needed */
1728 if(mCurrentFrame.fbCount == 0) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001729 return true;
Saurabh Shahaa236822013-04-24 18:07:26 -07001730 }
Saurabh Shahd53bc5f2014-02-05 10:17:43 -08001731
1732 /* No MDP comp layers, try to use other comp modes */
1733 if(mCurrentFrame.mdpCount == 0) {
1734 return false;
Saurabh Shahaa236822013-04-24 18:07:26 -07001735 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001736
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301737 fbZ = getBatch(list, maxBatchStart, maxBatchEnd, maxBatchCount);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001738
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301739 /* reset rest of the layers lying inside ROI for MDP comp */
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001740 for(int i = 0; i < mCurrentFrame.layerCount; i++) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001741 hwc_layer_1_t* layer = &list->hwLayers[i];
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001742 if((i < maxBatchStart || i > maxBatchEnd) &&
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301743 mCurrentFrame.isFBComposed[i]){
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001744 if(!mCurrentFrame.drop[i]){
1745 //If an unsupported layer is being attempted to
1746 //be pulled out we should fail
1747 if(not isSupportedForMDPComp(ctx, layer)) {
1748 return false;
1749 }
1750 mCurrentFrame.isFBComposed[i] = false;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001751 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001752 }
1753 }
1754
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301755 // update the frame data
1756 mCurrentFrame.fbZ = fbZ;
1757 mCurrentFrame.fbCount = maxBatchCount;
Saurabh Shahaa236822013-04-24 18:07:26 -07001758 mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001759 mCurrentFrame.fbCount - mCurrentFrame.dropCount;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001760
1761 ALOGD_IF(isDebug(),"%s: cached count: %d",__FUNCTION__,
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301762 mCurrentFrame.fbCount);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001763
1764 return true;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001765}
Saurabh Shah85234ec2013-04-12 17:09:00 -07001766
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001767void MDPComp::updateLayerCache(hwc_context_t* ctx,
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001768 hwc_display_contents_1_t* list, FrameInfo& frame) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001769 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001770 int fbCount = 0;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001771
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001772 for(int i = 0; i < numAppLayers; i++) {
1773 if (mCachedFrame.hnd[i] == list->hwLayers[i].handle) {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001774 if(!frame.drop[i])
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001775 fbCount++;
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001776 frame.isFBComposed[i] = true;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001777 } else {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001778 frame.isFBComposed[i] = false;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001779 }
1780 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001781
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001782 frame.fbCount = fbCount;
1783 frame.mdpCount = frame.layerCount - frame.fbCount
1784 - frame.dropCount;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001785
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001786 ALOGD_IF(isDebug(),"%s: MDP count: %d FB count %d drop count: %d",
1787 __FUNCTION__, frame.mdpCount, frame.fbCount, frame.dropCount);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001788}
1789
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001790// drop other non-AIV layers from external display list.
1791void MDPComp::dropNonAIVLayers(hwc_context_t* ctx,
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07001792 hwc_display_contents_1_t* list) {
1793 for (size_t i = 0; i < (size_t)ctx->listStats[mDpy].numAppLayers; i++) {
1794 hwc_layer_1_t * layer = &list->hwLayers[i];
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001795 if(!(isAIVVideoLayer(layer) || isAIVCCLayer(layer))) {
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07001796 mCurrentFrame.dropCount++;
1797 mCurrentFrame.drop[i] = true;
1798 }
1799 }
1800 mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
1801 mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
1802 mCurrentFrame.fbCount - mCurrentFrame.dropCount;
1803 ALOGD_IF(isDebug(),"%s: fb count: %d mdp count %d drop count %d",
1804 __FUNCTION__, mCurrentFrame.fbCount, mCurrentFrame.mdpCount,
1805 mCurrentFrame.dropCount);
1806}
1807
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001808void MDPComp::updateYUV(hwc_context_t* ctx, hwc_display_contents_1_t* list,
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001809 bool secureOnly, FrameInfo& frame) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001810 int nYuvCount = ctx->listStats[mDpy].yuvCount;
1811 for(int index = 0;index < nYuvCount; index++){
1812 int nYuvIndex = ctx->listStats[mDpy].yuvIndices[index];
1813 hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
1814
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001815 if(mCurrentFrame.drop[nYuvIndex]) {
1816 continue;
1817 }
1818
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001819 if(!isYUVDoable(ctx, layer)) {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001820 if(!frame.isFBComposed[nYuvIndex]) {
1821 frame.isFBComposed[nYuvIndex] = true;
1822 frame.fbCount++;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001823 }
1824 } else {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001825 if(frame.isFBComposed[nYuvIndex]) {
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001826 private_handle_t *hnd = (private_handle_t *)layer->handle;
1827 if(!secureOnly || isSecureBuffer(hnd)) {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001828 frame.isFBComposed[nYuvIndex] = false;
1829 frame.fbCount--;
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001830 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001831 }
1832 }
1833 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001834
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001835 frame.mdpCount = frame.layerCount - frame.fbCount - frame.dropCount;
1836 ALOGD_IF(isDebug(),"%s: fb count: %d",__FUNCTION__, frame.fbCount);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001837}
1838
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001839void MDPComp::updateSecureRGB(hwc_context_t* ctx,
1840 hwc_display_contents_1_t* list) {
1841 int nSecureRGBCount = ctx->listStats[mDpy].secureRGBCount;
1842 for(int index = 0;index < nSecureRGBCount; index++){
1843 int nSecureRGBIndex = ctx->listStats[mDpy].secureRGBIndices[index];
1844 hwc_layer_1_t* layer = &list->hwLayers[nSecureRGBIndex];
1845
1846 if(!isSecureRGBDoable(ctx, layer)) {
1847 if(!mCurrentFrame.isFBComposed[nSecureRGBIndex]) {
1848 mCurrentFrame.isFBComposed[nSecureRGBIndex] = true;
1849 mCurrentFrame.fbCount++;
1850 }
1851 } else {
1852 if(mCurrentFrame.isFBComposed[nSecureRGBIndex]) {
1853 mCurrentFrame.isFBComposed[nSecureRGBIndex] = false;
1854 mCurrentFrame.fbCount--;
1855 }
1856 }
1857 }
1858
1859 mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
1860 mCurrentFrame.fbCount - mCurrentFrame.dropCount;
1861 ALOGD_IF(isDebug(),"%s: fb count: %d",__FUNCTION__,
1862 mCurrentFrame.fbCount);
1863}
1864
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001865hwc_rect_t MDPComp::getUpdatingFBRect(hwc_context_t *ctx,
1866 hwc_display_contents_1_t* list){
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001867 hwc_rect_t fbRect = (struct hwc_rect){0, 0, 0, 0};
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001868
1869 /* Update only the region of FB needed for composition */
1870 for(int i = 0; i < mCurrentFrame.layerCount; i++ ) {
1871 if(mCurrentFrame.isFBComposed[i] && !mCurrentFrame.drop[i]) {
1872 hwc_layer_1_t* layer = &list->hwLayers[i];
1873 hwc_rect_t dst = layer->displayFrame;
1874 fbRect = getUnion(fbRect, dst);
1875 }
1876 }
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08001877 trimAgainstROI(ctx, fbRect, fbRect);
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001878 return fbRect;
1879}
1880
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001881bool MDPComp::postHeuristicsHandling(hwc_context_t *ctx,
1882 hwc_display_contents_1_t* list) {
1883
1884 //Capability checks
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08001885 if(!resourceCheck(ctx, list)) {
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001886 ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
1887 return false;
1888 }
1889
1890 //Limitations checks
1891 if(!hwLimitationsCheck(ctx, list)) {
1892 ALOGD_IF(isDebug(), "%s: HW limitations",__FUNCTION__);
1893 return false;
1894 }
1895
Saurabh Shah3d4b8042013-12-10 15:19:17 -08001896 //Configure framebuffer first if applicable
1897 if(mCurrentFrame.fbZ >= 0) {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001898 hwc_rect_t fbRect = getUpdatingFBRect(ctx, list);
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001899 if(!ctx->mFBUpdate[mDpy]->prepare(ctx, list, fbRect, mCurrentFrame.fbZ))
1900 {
Saurabh Shah3d4b8042013-12-10 15:19:17 -08001901 ALOGD_IF(isDebug(), "%s configure framebuffer failed",
1902 __FUNCTION__);
1903 return false;
1904 }
1905 }
1906
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001907 mCurrentFrame.map();
1908
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001909 if(!allocLayerPipes(ctx, list)) {
1910 ALOGD_IF(isDebug(), "%s: Unable to allocate MDP pipes", __FUNCTION__);
Saurabh Shahaa236822013-04-24 18:07:26 -07001911 return false;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001912 }
1913
1914 for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
Saurabh Shahaa236822013-04-24 18:07:26 -07001915 index++) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001916 if(!mCurrentFrame.isFBComposed[index]) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001917 int mdpIndex = mCurrentFrame.layerToMDP[index];
1918 hwc_layer_1_t* layer = &list->hwLayers[index];
1919
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301920 //Leave fbZ for framebuffer. CACHE/GLES layers go here.
1921 if(mdpNextZOrder == mCurrentFrame.fbZ) {
1922 mdpNextZOrder++;
1923 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001924 MdpPipeInfo* cur_pipe = mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
1925 cur_pipe->zOrder = mdpNextZOrder++;
1926
radhakrishnac9a67412013-09-25 17:40:42 +05301927 private_handle_t *hnd = (private_handle_t *)layer->handle;
Raj Kamal389d6e32014-08-04 14:43:24 +05301928 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
radhakrishnac9a67412013-09-25 17:40:42 +05301929 if(configure4k2kYuv(ctx, layer,
1930 mCurrentFrame.mdpToLayer[mdpIndex])
1931 != 0 ){
1932 ALOGD_IF(isDebug(), "%s: Failed to configure split pipes \
1933 for layer %d",__FUNCTION__, index);
1934 return false;
1935 }
1936 else{
1937 mdpNextZOrder++;
1938 }
1939 continue;
1940 }
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05001941 if(needs3DComposition(ctx,mDpy) && get3DFormat(hnd) != HAL_NO_3D) {
1942 mdpNextZOrder++;
1943 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001944 if(configure(ctx, layer, mCurrentFrame.mdpToLayer[mdpIndex]) != 0 ){
1945 ALOGD_IF(isDebug(), "%s: Failed to configure overlay for \
radhakrishnac9a67412013-09-25 17:40:42 +05301946 layer %d",__FUNCTION__, index);
Saurabh Shahaa236822013-04-24 18:07:26 -07001947 return false;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001948 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001949 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001950 }
1951
Saurabh Shaha36be922013-12-16 18:18:39 -08001952 if(!ctx->mOverlay->validateAndSet(mDpy, ctx->dpyAttr[mDpy].fd)) {
1953 ALOGD_IF(isDebug(), "%s: Failed to validate and set overlay for dpy %d"
1954 ,__FUNCTION__, mDpy);
1955 return false;
1956 }
1957
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001958 setRedraw(ctx, list);
Saurabh Shahaa236822013-04-24 18:07:26 -07001959 return true;
1960}
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001961
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08001962bool MDPComp::resourceCheck(hwc_context_t* ctx,
1963 hwc_display_contents_1_t* list) {
Saurabh Shah173f4242013-11-20 09:50:12 -08001964 const bool fbUsed = mCurrentFrame.fbCount;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001965 int cursorInUse = 0;
1966 if(mDpy == HWC_DISPLAY_PRIMARY) {
1967 // check if cursor is in use for primary
1968 cursorInUse = HWCursor::getInstance()->isCursorSet();
1969 }
1970 int maxStages = qdutils::MDPVersion::getInstance().getBlendStages();
1971 // HW Cursor needs one blending stage, account for that in the check below
1972 // On high end targets(8994) has 8 blending stages, HAL is configured to use < 8.
1973 // Make use of the remaining stages for HW Cursor so that the composition
1974 // strategy would not fail due to this limitation.
1975 if (maxStages > sMaxPipesPerMixer) {
1976 cursorInUse = 0;
1977 }
1978 if(mCurrentFrame.mdpCount > (sMaxPipesPerMixer - fbUsed - cursorInUse)) {
Saurabh Shah173f4242013-11-20 09:50:12 -08001979 ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
1980 return false;
1981 }
Saurabh Shahacec8e42014-11-25 11:07:04 -08001982
1983 //Will benefit cases where a video has non-updating background.
1984 if((mDpy > HWC_DISPLAY_PRIMARY) and
1985 (mCurrentFrame.mdpCount > sMaxSecLayers)) {
1986 ALOGD_IF(isDebug(), "%s: Exceeds max secondary pipes",__FUNCTION__);
1987 return false;
1988 }
1989
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08001990 // Init rotCount to number of rotate sessions used by other displays
1991 int rotCount = ctx->mRotMgr->getNumActiveSessions();
1992 // Count the number of rotator sessions required for current display
1993 for (int index = 0; index < mCurrentFrame.layerCount; index++) {
1994 if(!mCurrentFrame.isFBComposed[index]) {
1995 hwc_layer_1_t* layer = &list->hwLayers[index];
1996 private_handle_t *hnd = (private_handle_t *)layer->handle;
1997 if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
1998 rotCount++;
1999 }
2000 }
2001 }
2002 // if number of layers to rotate exceeds max rotator sessions, bail out.
2003 if(rotCount > RotMgr::MAX_ROT_SESS) {
2004 ALOGD_IF(isDebug(), "%s: Exceeds max rotator sessions %d",
2005 __FUNCTION__, mDpy);
2006 return false;
2007 }
Saurabh Shah173f4242013-11-20 09:50:12 -08002008 return true;
2009}
2010
Prabhanjan Kandula21918db2013-11-26 15:51:58 +05302011bool MDPComp::hwLimitationsCheck(hwc_context_t* ctx,
2012 hwc_display_contents_1_t* list) {
2013
2014 //A-family hw limitation:
2015 //If a layer need alpha scaling, MDP can not support.
2016 if(ctx->mMDP.version < qdutils::MDSS_V5) {
2017 for(int i = 0; i < mCurrentFrame.layerCount; ++i) {
2018 if(!mCurrentFrame.isFBComposed[i] &&
2019 isAlphaScaled( &list->hwLayers[i])) {
2020 ALOGD_IF(isDebug(), "%s:frame needs alphaScaling",__FUNCTION__);
2021 return false;
2022 }
2023 }
2024 }
2025
2026 // On 8x26 & 8974 hw, we have a limitation of downscaling+blending.
2027 //If multiple layers requires downscaling and also they are overlapping
2028 //fall back to GPU since MDSS can not handle it.
2029 if(qdutils::MDPVersion::getInstance().is8x74v2() ||
2030 qdutils::MDPVersion::getInstance().is8x26()) {
2031 for(int i = 0; i < mCurrentFrame.layerCount-1; ++i) {
2032 hwc_layer_1_t* botLayer = &list->hwLayers[i];
2033 if(!mCurrentFrame.isFBComposed[i] &&
2034 isDownscaleRequired(botLayer)) {
2035 //if layer-i is marked for MDP and needs downscaling
2036 //check if any MDP layer on top of i & overlaps with layer-i
2037 for(int j = i+1; j < mCurrentFrame.layerCount; ++j) {
2038 hwc_layer_1_t* topLayer = &list->hwLayers[j];
2039 if(!mCurrentFrame.isFBComposed[j] &&
2040 isDownscaleRequired(topLayer)) {
2041 hwc_rect_t r = getIntersection(botLayer->displayFrame,
2042 topLayer->displayFrame);
2043 if(isValidRect(r))
2044 return false;
2045 }
2046 }
2047 }
2048 }
2049 }
2050 return true;
2051}
2052
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002053static bool validForCursor(hwc_context_t* ctx, int dpy, hwc_layer_1_t* layer) {
2054 private_handle_t *hnd = (private_handle_t *)layer->handle;
2055 hwc_rect dst = layer->displayFrame;
2056 hwc_rect src = integerizeSourceCrop(layer->sourceCropf);
2057 int srcW = src.right - src.left;
2058 int srcH = src.bottom - src.top;
2059 int dstW = dst.right - dst.left;
2060 int dstH = dst.bottom - dst.top;
2061 qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
2062 uint32_t maxCursorSize = mdpVersion.getMaxCursorSize();
2063 uint32_t numHwCursors = mdpVersion.getCursorPipes();
2064 bool primarySplit = isDisplaySplit(ctx, HWC_DISPLAY_PRIMARY);
2065 uint32_t cursorPipesNeeded = 1; // One cursor pipe needed(default)
2066 bool ret = false;
2067
2068 if(dpy > HWC_DISPLAY_PRIMARY) {
2069 // Cursor not supported on secondary displays, as it involves scaling
2070 // in most of the cases
2071 return false;
2072 } else if (isSkipLayer(layer)) {
2073 return false;
2074 // Checks for HW limitation
2075 } else if (numHwCursors == 0 || maxCursorSize <= 0) {
2076 return false;
2077 } else if (needsScaling(layer)) {
2078 return false;
2079 } else if (layer->transform != 0) {
2080 return false;
2081 } else if (hnd->format != HAL_PIXEL_FORMAT_RGBA_8888) {
2082 return false;
2083 } else if (srcW > (int)maxCursorSize || srcH > (int)maxCursorSize) {
2084 return false;
2085 }
2086
2087 if (isDisplaySplit(ctx, dpy) && !mdpVersion.isSrcSplit()) {
2088 // In case of split display with no srcSplit, the driver allocates two
2089 // pipes to support async position update across mixers, hence
2090 // need to account for that here.
2091 cursorPipesNeeded = 2;
2092 }
2093 if (cursorPipesNeeded <= numHwCursors) {
2094 ret = true;
2095 }
2096 return ret;
2097}
2098
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08002099// Checks only if videos or single layer(RGB) is updating
2100// which is used for setting dynamic fps or perf hint for single
2101// layer video playback
2102bool MDPComp::onlyVideosUpdating(hwc_context_t *ctx,
2103 hwc_display_contents_1_t* list) {
2104 bool support = false;
2105 FrameInfo frame;
2106 frame.reset(mCurrentFrame.layerCount);
2107 memset(&frame.drop, 0, sizeof(frame.drop));
2108 frame.dropCount = 0;
2109 ALOGD_IF(isDebug(), "%s: Update Cache and YUVInfo", __FUNCTION__);
2110 updateLayerCache(ctx, list, frame);
2111 updateYUV(ctx, list, false /*secure only*/, frame);
2112 // There are only updating YUV layers or there is single RGB
2113 // Layer(Youtube)
2114 if((ctx->listStats[mDpy].yuvCount == frame.mdpCount) ||
2115 (frame.layerCount == 1)) {
2116 support = true;
2117 }
2118 return support;
2119}
2120
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302121void MDPComp::setDynRefreshRate(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
2122 //For primary display, set the dynamic refreshrate
2123 if(!mDpy && qdutils::MDPVersion::getInstance().isDynFpsSupported() &&
2124 ctx->mUseMetaDataRefreshRate) {
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302125 uint32_t refreshRate = ctx->dpyAttr[mDpy].refreshRate;
2126 MDPVersion& mdpHw = MDPVersion::getInstance();
2127 if(sIdleFallBack) {
2128 //Set minimum panel refresh rate during idle timeout
2129 refreshRate = mdpHw.getMinFpsSupported();
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08002130 } else if(onlyVideosUpdating(ctx, list)) {
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302131 //Set the new fresh rate, if there is only one updating YUV layer
2132 //or there is one single RGB layer with this request
2133 refreshRate = ctx->listStats[mDpy].refreshRateRequest;
2134 }
2135 setRefreshRate(ctx, mDpy, refreshRate);
2136 }
2137}
2138
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002139int MDPComp::prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002140 int ret = 0;
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07002141 char property[PROPERTY_VALUE_MAX];
2142
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002143 if(!list) {
2144 ALOGE("%s: Invalid list", __FUNCTION__);
Raj Kamal4393eaa2014-06-06 13:45:20 +05302145 mCachedFrame.reset();
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002146 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Raj Kamal4393eaa2014-06-06 13:45:20 +05302147 return -1;
2148 }
2149
2150 const int numLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shah286cf122014-09-08 14:13:08 -07002151 if(mDpy == HWC_DISPLAY_PRIMARY) {
2152 sSimulationFlags = 0;
2153 if(property_get("debug.hwc.simulate", property, NULL) > 0) {
2154 int currentFlags = atoi(property);
2155 if(currentFlags != sSimulationFlags) {
2156 sSimulationFlags = currentFlags;
2157 ALOGI("%s: Simulation Flag read: 0x%x (%d)", __FUNCTION__,
2158 sSimulationFlags, sSimulationFlags);
2159 }
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07002160 }
2161 }
Ramkumar Radhakrishnanc5893f12013-06-06 19:43:53 -07002162
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302163 //reset old data
2164 mCurrentFrame.reset(numLayers);
2165 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
2166 mCurrentFrame.dropCount = 0;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002167 mCurrentFrame.hwCursorIndex = -1;
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302168
Raj Kamal9ed3d6b2014-02-07 16:15:17 +05302169 //Do not cache the information for next draw cycle.
2170 if(numLayers > MAX_NUM_APP_LAYERS or (!numLayers)) {
2171 ALOGI("%s: Unsupported layer count for mdp composition",
2172 __FUNCTION__);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002173 mCachedFrame.reset();
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302174#ifdef DYNAMIC_FPS
2175 setDynRefreshRate(ctx, list);
2176#endif
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002177 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002178 return -1;
2179 }
2180
Ramkumar Radhakrishnana70981a2013-08-28 11:33:53 -07002181 // Detect the start of animation and fall back to GPU only once to cache
2182 // all the layers in FB and display FB content untill animation completes.
2183 if(ctx->listStats[mDpy].isDisplayAnimating) {
2184 mCurrentFrame.needsRedraw = false;
2185 if(ctx->mAnimationState[mDpy] == ANIMATION_STOPPED) {
2186 mCurrentFrame.needsRedraw = true;
2187 ctx->mAnimationState[mDpy] = ANIMATION_STARTED;
2188 }
2189 setMDPCompLayerFlags(ctx, list);
2190 mCachedFrame.updateCounts(mCurrentFrame);
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302191#ifdef DYNAMIC_FPS
2192 setDynRefreshRate(ctx, list);
2193#endif
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002194 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Ramkumar Radhakrishnana70981a2013-08-28 11:33:53 -07002195 ret = -1;
2196 return ret;
2197 } else {
2198 ctx->mAnimationState[mDpy] = ANIMATION_STOPPED;
2199 }
2200
Raj Kamalfdfdddf2015-03-16 21:59:25 +05302201 if(!mDpy and !isSecondaryConnected(ctx) and !mPrevModeOn and
2202 mCachedFrame.isSameFrame(ctx,mDpy,list)) {
2203
2204 ALOGD_IF(isDebug(),"%s: Avoid new composition",__FUNCTION__);
2205 mCurrentFrame.needsRedraw = false;
2206 setMDPCompLayerFlags(ctx, list);
2207 mCachedFrame.updateCounts(mCurrentFrame);
2208#ifdef DYNAMIC_FPS
2209 setDynRefreshRate(ctx, list);
2210#endif
2211 return -1;
2212
2213 }
2214
Saurabh Shahb39f8152013-08-22 10:21:44 -07002215 //Hard conditions, if not met, cannot do MDP comp
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002216 if(isFrameDoable(ctx)) {
2217 generateROI(ctx, list);
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07002218 // if AIV Video mode is enabled, drop all non AIV layers from the
2219 // external display list.
2220 if(ctx->listStats[mDpy].mAIVVideoMode) {
2221 dropNonAIVLayers(ctx, list);
2222 }
Saurabh Shahb39f8152013-08-22 10:21:44 -07002223
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002224 // Configure the cursor if present
2225 int topIndex = ctx->listStats[mDpy].numAppLayers - 1;
2226 if(ctx->listStats[mDpy].cursorLayerPresent &&
2227 validForCursor(ctx, mDpy, &(list->hwLayers[topIndex]))) {
2228 if(configHwCursor(ctx->dpyAttr[mDpy].fd, mDpy,
2229 &(list->hwLayers[topIndex]))) {
2230 // As cursor is configured, mark that layer as dropped, so that
2231 // it wont be considered for composition by other strategies.
2232 mCurrentFrame.hwCursorIndex = topIndex;
2233 mCurrentFrame.drop[topIndex] = true;
2234 mCurrentFrame.dropCount++;
2235 }
2236 } else {
2237 // Release the hw cursor
2238 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
2239 }
2240
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07002241 // if tryFullFrame fails, try to push all video and secure RGB layers
2242 // to MDP for composition.
2243 mModeOn = tryFullFrame(ctx, list) || tryMDPOnlyLayers(ctx, list) ||
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07002244 tryVideoOnly(ctx, list);
Raj Kamal4393eaa2014-06-06 13:45:20 +05302245 if(mModeOn) {
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002246 setMDPCompLayerFlags(ctx, list);
2247 } else {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08002248 resetROI(ctx, mDpy);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002249 reset(ctx);
2250 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
2251 mCurrentFrame.dropCount = 0;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002252 // Check if cursor is in use for primary and mark accordingly
2253 if(!mDpy && HWCursor::getInstance()->isCursorSet()) {
2254 int topIndex = ctx->listStats[mDpy].numAppLayers - 1;
2255 hwc_layer_1_t *layer = &(list->hwLayers[topIndex]);
2256 layer->compositionType = HWC_CURSOR_OVERLAY;
2257 }
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002258 ret = -1;
Saurabh Shah286cf122014-09-08 14:13:08 -07002259 ALOGE_IF(sSimulationFlags && (mDpy == HWC_DISPLAY_PRIMARY),
2260 "MDP Composition Strategies Failed");
Saurabh Shahb39f8152013-08-22 10:21:44 -07002261 }
2262 } else {
Dileep Kumar Reddi4070e932014-09-30 09:00:57 +05302263 if ((ctx->mMDP.version == qdutils::MDP_V3_0_5) && ctx->mCopyBit[mDpy] &&
2264 enablePartialUpdateForMDP3) {
2265 generateROI(ctx, list);
2266 for(int i = 0; i < ctx->listStats[mDpy].numAppLayers; i++) {
2267 ctx->copybitDrop[i] = mCurrentFrame.drop[i];
2268 }
2269 }
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002270 ALOGD_IF( isDebug(),"%s: MDP Comp not possible for this frame",
2271 __FUNCTION__);
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002272 // Release the hw cursor
2273 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002274 ret = -1;
Saurabh Shahb39f8152013-08-22 10:21:44 -07002275 }
Saurabh Shahb39f8152013-08-22 10:21:44 -07002276
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002277 if(isDebug()) {
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002278 ALOGD("GEOMETRY change: %d",
2279 (list->flags & HWC_GEOMETRY_CHANGED));
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002280 android::String8 sDump("");
Jeykumar Sankaran6850ac62014-05-27 10:07:26 -07002281 dump(sDump, ctx);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002282 ALOGD("%s",sDump.string());
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002283 }
2284
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07002285#ifdef DYNAMIC_FPS
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302286 setDynRefreshRate(ctx, list);
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07002287#endif
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08002288 setPerfHint(ctx, list);
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07002289
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002290 mCachedFrame.cacheAll(list);
2291 mCachedFrame.updateCounts(mCurrentFrame);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002292 return ret;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002293}
2294
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002295bool MDPComp::allocSplitVGPipes(hwc_context_t *ctx, int index) {
radhakrishnac9a67412013-09-25 17:40:42 +05302296
2297 bool bRet = true;
radhakrishnac9a67412013-09-25 17:40:42 +05302298 int mdpIndex = mCurrentFrame.layerToMDP[index];
2299 PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
2300 info.pipeInfo = new MdpYUVPipeInfo;
2301 info.rot = NULL;
2302 MdpYUVPipeInfo& pipe_info = *(MdpYUVPipeInfo*)info.pipeInfo;
radhakrishnac9a67412013-09-25 17:40:42 +05302303
2304 pipe_info.lIndex = ovutils::OV_INVALID;
2305 pipe_info.rIndex = ovutils::OV_INVALID;
2306
Saurabh Shahc62f3982014-03-05 14:28:26 -08002307 Overlay::PipeSpecs pipeSpecs;
2308 pipeSpecs.formatClass = Overlay::FORMAT_YUV;
2309 pipeSpecs.needsScaling = true;
2310 pipeSpecs.dpy = mDpy;
2311 pipeSpecs.fb = false;
2312
2313 pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
radhakrishnac9a67412013-09-25 17:40:42 +05302314 if(pipe_info.lIndex == ovutils::OV_INVALID){
2315 bRet = false;
2316 ALOGD_IF(isDebug(),"%s: allocating first VG pipe failed",
2317 __FUNCTION__);
2318 }
Saurabh Shahc62f3982014-03-05 14:28:26 -08002319 pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
radhakrishnac9a67412013-09-25 17:40:42 +05302320 if(pipe_info.rIndex == ovutils::OV_INVALID){
2321 bRet = false;
2322 ALOGD_IF(isDebug(),"%s: allocating second VG pipe failed",
2323 __FUNCTION__);
2324 }
2325 return bRet;
2326}
Sushil Chauhandefd3522014-05-13 18:17:12 -07002327
2328int MDPComp::drawOverlap(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
2329 int fd = -1;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002330 if (ctx->mPtorInfo.isActive()) {
2331 fd = ctx->mCopyBit[mDpy]->drawOverlap(ctx, list);
Sushil Chauhandefd3522014-05-13 18:17:12 -07002332 if (fd < 0) {
2333 ALOGD_IF(isDebug(),"%s: failed", __FUNCTION__);
Sushil Chauhandefd3522014-05-13 18:17:12 -07002334 }
2335 }
2336 return fd;
2337}
Arun Kumar K.R2aa44c62014-01-21 23:08:28 -08002338//=============MDPCompNonSplit==================================================
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002339
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002340void MDPCompNonSplit::adjustForSourceSplit(hwc_context_t *ctx,
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302341 hwc_display_contents_1_t* list) {
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002342 //If 4k2k Yuv layer split is possible, and if
2343 //fbz is above 4k2k layer, increment fb zorder by 1
2344 //as we split 4k2k layer and increment zorder for right half
2345 //of the layer
Shalaj Jaina70b4352014-06-15 13:47:47 -07002346 if(!ctx)
2347 return;
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002348 if(mCurrentFrame.fbZ >= 0) {
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302349 for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
2350 index++) {
2351 if(!mCurrentFrame.isFBComposed[index]) {
2352 if(mdpNextZOrder == mCurrentFrame.fbZ) {
2353 mdpNextZOrder++;
2354 }
2355 mdpNextZOrder++;
2356 hwc_layer_1_t* layer = &list->hwLayers[index];
2357 private_handle_t *hnd = (private_handle_t *)layer->handle;
Raj Kamal389d6e32014-08-04 14:43:24 +05302358 if(isYUVSplitNeeded(hnd)) {
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302359 if(mdpNextZOrder <= mCurrentFrame.fbZ)
2360 mCurrentFrame.fbZ += 1;
2361 mdpNextZOrder++;
2362 //As we split 4kx2k yuv layer and program to 2 VG pipes
2363 //(if available) increase mdpcount by 1.
2364 mCurrentFrame.mdpCount++;
2365 }
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002366 }
2367 }
2368 }
radhakrishnac9a67412013-09-25 17:40:42 +05302369}
2370
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002371/*
2372 * Configures pipe(s) for MDP composition
2373 */
Saurabh Shah88e4d272013-09-03 13:31:29 -07002374int MDPCompNonSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002375 PipeLayerPair& PipeLayerPair) {
Saurabh Shah88e4d272013-09-03 13:31:29 -07002376 MdpPipeInfoNonSplit& mdp_info =
2377 *(static_cast<MdpPipeInfoNonSplit*>(PipeLayerPair.pipeInfo));
Justin Philipd6166602014-08-12 13:42:21 +05302378 eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shahacf10202013-02-26 10:15:15 -08002379 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Saurabh Shahacf10202013-02-26 10:15:15 -08002380 eDest dest = mdp_info.index;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002381
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002382 ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipe: %d",
2383 __FUNCTION__, layer, zOrder, dest);
2384
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002385 return configureNonSplit(ctx, layer, mDpy, mdpFlags, zOrder, dest,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002386 &PipeLayerPair.rot);
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002387}
2388
Saurabh Shah88e4d272013-09-03 13:31:29 -07002389bool MDPCompNonSplit::allocLayerPipes(hwc_context_t *ctx,
Saurabh Shahe51f8ca2013-05-06 17:26:16 -07002390 hwc_display_contents_1_t* list) {
Saurabh Shah8cc77712015-03-31 10:48:51 -07002391 for(uint32_t formatType = FORMAT_YUV; formatType < FORMAT_MAX;
2392 formatType++) {
2393 for(int index = 0; index < mCurrentFrame.layerCount; index++) {
2394 if(mCurrentFrame.isFBComposed[index]) continue;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002395
Saurabh Shah8cc77712015-03-31 10:48:51 -07002396 hwc_layer_1_t* layer = &list->hwLayers[index];
2397 private_handle_t *hnd = (private_handle_t *)layer->handle;
2398 if(formatType == FORMAT_YUV && !isYuvBuffer(hnd))
radhakrishnac9a67412013-09-25 17:40:42 +05302399 continue;
Saurabh Shah8cc77712015-03-31 10:48:51 -07002400 if(formatType == FORMAT_RGB && isYuvBuffer(hnd))
2401 continue;
2402
2403 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
2404 if(allocSplitVGPipes(ctx, index)){
2405 continue;
2406 }
radhakrishnac9a67412013-09-25 17:40:42 +05302407 }
radhakrishnac9a67412013-09-25 17:40:42 +05302408
Saurabh Shah8cc77712015-03-31 10:48:51 -07002409 int mdpIndex = mCurrentFrame.layerToMDP[index];
2410 PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
2411 info.pipeInfo = new MdpPipeInfoNonSplit;
2412 info.rot = NULL;
2413 MdpPipeInfoNonSplit& pipe_info =
2414 *(MdpPipeInfoNonSplit*)info.pipeInfo;
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -08002415
Saurabh Shah8cc77712015-03-31 10:48:51 -07002416 Overlay::PipeSpecs pipeSpecs;
2417 pipeSpecs.formatClass = isYuvBuffer(hnd) ?
2418 Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
2419 pipeSpecs.needsScaling = qhwc::needsScaling(layer) or
2420 (qdutils::MDPVersion::getInstance().is8x26() and
2421 ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres > 1024);
2422 pipeSpecs.dpy = mDpy;
2423 pipeSpecs.fb = false;
2424 pipeSpecs.numActiveDisplays = ctx->numActiveDisplays;
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -08002425
Saurabh Shah8cc77712015-03-31 10:48:51 -07002426 pipe_info.index = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahc62f3982014-03-05 14:28:26 -08002427
Saurabh Shah8cc77712015-03-31 10:48:51 -07002428 if(pipe_info.index == ovutils::OV_INVALID) {
2429 ALOGD_IF(isDebug(), "%s: Unable to get pipe for layer %d of "\
2430 "format type %d", __FUNCTION__, index, formatType);
2431 return false;
2432 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002433 }
2434 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002435 return true;
2436}
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002437
radhakrishnac9a67412013-09-25 17:40:42 +05302438int MDPCompNonSplit::configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
2439 PipeLayerPair& PipeLayerPair) {
2440 MdpYUVPipeInfo& mdp_info =
2441 *(static_cast<MdpYUVPipeInfo*>(PipeLayerPair.pipeInfo));
2442 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Justin Philipd6166602014-08-12 13:42:21 +05302443 eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
radhakrishnac9a67412013-09-25 17:40:42 +05302444 eDest lDest = mdp_info.lIndex;
2445 eDest rDest = mdp_info.rIndex;
2446
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002447 return configureSourceSplit(ctx, layer, mDpy, mdpFlagsL, zOrder,
radhakrishnac9a67412013-09-25 17:40:42 +05302448 lDest, rDest, &PipeLayerPair.rot);
2449}
2450
Saurabh Shah88e4d272013-09-03 13:31:29 -07002451bool MDPCompNonSplit::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002452
Raj Kamal4393eaa2014-06-06 13:45:20 +05302453 if(!isEnabled() or !mModeOn) {
2454 ALOGD_IF(isDebug(),"%s: MDP Comp not enabled/configured", __FUNCTION__);
Prabhanjan Kandula08222fc2013-07-10 17:20:59 +05302455 return true;
2456 }
2457
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002458 overlay::Overlay& ov = *ctx->mOverlay;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002459 LayerProp *layerProp = ctx->layerProp[mDpy];
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002460
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002461 int numHwLayers = ctx->listStats[mDpy].numAppLayers;
2462 for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ )
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002463 {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002464 if(mCurrentFrame.isFBComposed[i]) continue;
2465
Naseer Ahmed5b6708a2012-08-02 13:46:08 -07002466 hwc_layer_1_t *layer = &list->hwLayers[i];
Saurabh Shahacf10202013-02-26 10:15:15 -08002467 private_handle_t *hnd = (private_handle_t *)layer->handle;
2468 if(!hnd) {
Sushil Chauhan897a9c32013-07-18 11:09:55 -07002469 if (!(layer->flags & HWC_COLOR_FILL)) {
2470 ALOGE("%s handle null", __FUNCTION__);
2471 return false;
2472 }
2473 // No PLAY for Color layer
2474 layerProp[i].mFlags &= ~HWC_MDPCOMP;
2475 continue;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002476 }
2477
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002478 int mdpIndex = mCurrentFrame.layerToMDP[i];
2479
Raj Kamal389d6e32014-08-04 14:43:24 +05302480 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit)
radhakrishnac9a67412013-09-25 17:40:42 +05302481 {
2482 MdpYUVPipeInfo& pipe_info =
2483 *(MdpYUVPipeInfo*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
2484 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
2485 ovutils::eDest indexL = pipe_info.lIndex;
2486 ovutils::eDest indexR = pipe_info.rIndex;
2487 int fd = hnd->fd;
Praveena Pachipulusud9443c72014-02-17 10:42:28 +05302488 uint32_t offset = (uint32_t)hnd->offset;
radhakrishnac9a67412013-09-25 17:40:42 +05302489 if(rot) {
2490 rot->queueBuffer(fd, offset);
2491 fd = rot->getDstMemId();
2492 offset = rot->getDstOffset();
2493 }
2494 if(indexL != ovutils::OV_INVALID) {
2495 ovutils::eDest destL = (ovutils::eDest)indexL;
2496 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2497 using pipe: %d", __FUNCTION__, layer, hnd, indexL );
2498 if (!ov.queueBuffer(fd, offset, destL)) {
2499 ALOGE("%s: queueBuffer failed for display:%d",
2500 __FUNCTION__, mDpy);
2501 return false;
2502 }
2503 }
2504
2505 if(indexR != ovutils::OV_INVALID) {
2506 ovutils::eDest destR = (ovutils::eDest)indexR;
2507 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2508 using pipe: %d", __FUNCTION__, layer, hnd, indexR );
2509 if (!ov.queueBuffer(fd, offset, destR)) {
2510 ALOGE("%s: queueBuffer failed for display:%d",
2511 __FUNCTION__, mDpy);
2512 return false;
2513 }
2514 }
2515 }
2516 else{
2517 MdpPipeInfoNonSplit& pipe_info =
Saurabh Shah88e4d272013-09-03 13:31:29 -07002518 *(MdpPipeInfoNonSplit*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
radhakrishnac9a67412013-09-25 17:40:42 +05302519 ovutils::eDest dest = pipe_info.index;
2520 if(dest == ovutils::OV_INVALID) {
2521 ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, dest);
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002522 return false;
radhakrishnac9a67412013-09-25 17:40:42 +05302523 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002524
radhakrishnac9a67412013-09-25 17:40:42 +05302525 if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
2526 continue;
2527 }
2528
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002529 int fd = hnd->fd;
2530 uint32_t offset = (uint32_t)hnd->offset;
2531 int index = ctx->mPtorInfo.getPTORArrayIndex(i);
2532 if (!mDpy && (index != -1)) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07002533 hnd = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002534 fd = hnd->fd;
Sushil Chauhan875a92e2014-07-25 12:20:23 -07002535 offset = 0;
Sushil Chauhandefd3522014-05-13 18:17:12 -07002536 }
2537
radhakrishnac9a67412013-09-25 17:40:42 +05302538 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2539 using pipe: %d", __FUNCTION__, layer,
2540 hnd, dest );
2541
radhakrishnac9a67412013-09-25 17:40:42 +05302542 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
2543 if(rot) {
2544 if(!rot->queueBuffer(fd, offset))
2545 return false;
2546 fd = rot->getDstMemId();
2547 offset = rot->getDstOffset();
2548 }
2549
2550 if (!ov.queueBuffer(fd, offset, dest)) {
2551 ALOGE("%s: queueBuffer failed for display:%d ",
2552 __FUNCTION__, mDpy);
2553 return false;
2554 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002555 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002556
2557 layerProp[i].mFlags &= ~HWC_MDPCOMP;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002558 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002559 return true;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002560}
2561
Saurabh Shah88e4d272013-09-03 13:31:29 -07002562//=============MDPCompSplit===================================================
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002563
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002564void MDPCompSplit::adjustForSourceSplit(hwc_context_t *ctx,
radhakrishnac9a67412013-09-25 17:40:42 +05302565 hwc_display_contents_1_t* list){
2566 //if 4kx2k yuv layer is totally present in either in left half
2567 //or right half then try splitting the yuv layer to avoid decimation
radhakrishnac9a67412013-09-25 17:40:42 +05302568 const int lSplit = getLeftSplit(ctx, mDpy);
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302569 if(mCurrentFrame.fbZ >= 0) {
2570 for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
2571 index++) {
2572 if(!mCurrentFrame.isFBComposed[index]) {
2573 if(mdpNextZOrder == mCurrentFrame.fbZ) {
2574 mdpNextZOrder++;
2575 }
2576 mdpNextZOrder++;
2577 hwc_layer_1_t* layer = &list->hwLayers[index];
2578 private_handle_t *hnd = (private_handle_t *)layer->handle;
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002579 if(isYUVSplitNeeded(hnd) ||
2580 (needs3DComposition(ctx,mDpy) &&
2581 get3DFormat(hnd) != HAL_NO_3D)) {
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302582 hwc_rect_t dst = layer->displayFrame;
2583 if((dst.left > lSplit) || (dst.right < lSplit)) {
2584 mCurrentFrame.mdpCount += 1;
2585 }
2586 if(mdpNextZOrder <= mCurrentFrame.fbZ)
2587 mCurrentFrame.fbZ += 1;
2588 mdpNextZOrder++;
2589 }
2590 }
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002591 }
radhakrishnac9a67412013-09-25 17:40:42 +05302592 }
2593}
2594
Saurabh Shah88e4d272013-09-03 13:31:29 -07002595bool MDPCompSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
Saurabh Shahc62f3982014-03-05 14:28:26 -08002596 MdpPipeInfoSplit& pipe_info) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002597
Saurabh Shahc62f3982014-03-05 14:28:26 -08002598 const int lSplit = getLeftSplit(ctx, mDpy);
2599 private_handle_t *hnd = (private_handle_t *)layer->handle;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002600 hwc_rect_t dst = layer->displayFrame;
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002601 pipe_info.lIndex = ovutils::OV_INVALID;
2602 pipe_info.rIndex = ovutils::OV_INVALID;
2603
Saurabh Shahc62f3982014-03-05 14:28:26 -08002604 Overlay::PipeSpecs pipeSpecs;
2605 pipeSpecs.formatClass = isYuvBuffer(hnd) ?
2606 Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
2607 pipeSpecs.needsScaling = qhwc::needsScalingWithSplit(ctx, layer, mDpy);
2608 pipeSpecs.dpy = mDpy;
2609 pipeSpecs.mixer = Overlay::MIXER_LEFT;
2610 pipeSpecs.fb = false;
2611
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08002612 // Acquire pipe only for the updating half
2613 hwc_rect_t l_roi = ctx->listStats[mDpy].lRoi;
2614 hwc_rect_t r_roi = ctx->listStats[mDpy].rRoi;
2615
2616 if (dst.left < lSplit && isValidRect(getIntersection(dst, l_roi))) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002617 pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002618 if(pipe_info.lIndex == ovutils::OV_INVALID)
2619 return false;
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002620 }
2621
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08002622 if(dst.right > lSplit && isValidRect(getIntersection(dst, r_roi))) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002623 pipeSpecs.mixer = Overlay::MIXER_RIGHT;
2624 pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002625 if(pipe_info.rIndex == ovutils::OV_INVALID)
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002626 return false;
2627 }
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002628
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002629 return true;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002630}
2631
Saurabh Shah88e4d272013-09-03 13:31:29 -07002632bool MDPCompSplit::allocLayerPipes(hwc_context_t *ctx,
Saurabh Shahe51f8ca2013-05-06 17:26:16 -07002633 hwc_display_contents_1_t* list) {
Saurabh Shah8cc77712015-03-31 10:48:51 -07002634 for(uint32_t formatType = FORMAT_YUV; formatType < FORMAT_MAX;
2635 formatType++) {
2636 for(int index = 0 ; index < mCurrentFrame.layerCount; index++) {
2637 if(mCurrentFrame.isFBComposed[index]) continue;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002638
Saurabh Shah8cc77712015-03-31 10:48:51 -07002639 hwc_layer_1_t* layer = &list->hwLayers[index];
2640 private_handle_t *hnd = (private_handle_t *)layer->handle;
2641 if(formatType == FORMAT_YUV && !isYuvBuffer(hnd))
2642 continue;
2643 if(formatType == FORMAT_RGB && isYuvBuffer(hnd))
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002644 continue;
2645
Saurabh Shah8cc77712015-03-31 10:48:51 -07002646 hwc_rect_t dst = layer->displayFrame;
2647 const int lSplit = getLeftSplit(ctx, mDpy);
2648 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
2649 if((dst.left > lSplit)||(dst.right < lSplit)){
2650 if(allocSplitVGPipes(ctx, index)){
2651 continue;
2652 }
2653 }
2654 }
2655 //XXX: Check for forced 2D composition
2656 if(needs3DComposition(ctx, mDpy) && get3DFormat(hnd) != HAL_NO_3D)
2657 if(allocSplitVGPipes(ctx,index))
2658 continue;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002659
Saurabh Shah8cc77712015-03-31 10:48:51 -07002660 int mdpIndex = mCurrentFrame.layerToMDP[index];
2661 PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
2662 info.pipeInfo = new MdpPipeInfoSplit;
2663 info.rot = NULL;
2664 MdpPipeInfoSplit& pipe_info = *(MdpPipeInfoSplit*)info.pipeInfo;
2665
2666 if(!acquireMDPPipes(ctx, layer, pipe_info)) {
2667 ALOGD_IF(isDebug(), "%s: Unable to get pipe for layer %d of "\
2668 "format type %d", __FUNCTION__, index, formatType);
2669 return false;
2670 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002671 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002672 }
2673 return true;
2674}
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002675
radhakrishnac9a67412013-09-25 17:40:42 +05302676int MDPCompSplit::configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
2677 PipeLayerPair& PipeLayerPair) {
2678 const int lSplit = getLeftSplit(ctx, mDpy);
2679 hwc_rect_t dst = layer->displayFrame;
2680 if((dst.left > lSplit)||(dst.right < lSplit)){
2681 MdpYUVPipeInfo& mdp_info =
2682 *(static_cast<MdpYUVPipeInfo*>(PipeLayerPair.pipeInfo));
2683 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Justin Philipd6166602014-08-12 13:42:21 +05302684 eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
radhakrishnac9a67412013-09-25 17:40:42 +05302685 eDest lDest = mdp_info.lIndex;
2686 eDest rDest = mdp_info.rIndex;
2687
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002688 return configureSourceSplit(ctx, layer, mDpy, mdpFlagsL, zOrder,
radhakrishnac9a67412013-09-25 17:40:42 +05302689 lDest, rDest, &PipeLayerPair.rot);
2690 }
2691 else{
2692 return configure(ctx, layer, PipeLayerPair);
2693 }
2694}
2695
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002696/*
2697 * Configures pipe(s) for MDP composition
2698 */
Saurabh Shah88e4d272013-09-03 13:31:29 -07002699int MDPCompSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
Saurabh Shah67a38c32013-06-10 16:23:15 -07002700 PipeLayerPair& PipeLayerPair) {
Saurabh Shah88e4d272013-09-03 13:31:29 -07002701 MdpPipeInfoSplit& mdp_info =
2702 *(static_cast<MdpPipeInfoSplit*>(PipeLayerPair.pipeInfo));
Saurabh Shahacf10202013-02-26 10:15:15 -08002703 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Justin Philipd6166602014-08-12 13:42:21 +05302704 eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shahacf10202013-02-26 10:15:15 -08002705 eDest lDest = mdp_info.lIndex;
2706 eDest rDest = mdp_info.rIndex;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002707
2708 ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
Jeykumar Sankaran39305802014-12-12 17:55:57 -08002709 "dest_pipeR: %d",__FUNCTION__, layer, zOrder, lDest, rDest);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002710
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002711 return configureSplit(ctx, layer, mDpy, mdpFlagsL, zOrder, lDest,
Jeykumar Sankaran39305802014-12-12 17:55:57 -08002712 rDest, &PipeLayerPair.rot);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002713}
2714
Saurabh Shah88e4d272013-09-03 13:31:29 -07002715bool MDPCompSplit::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002716
Raj Kamal4393eaa2014-06-06 13:45:20 +05302717 if(!isEnabled() or !mModeOn) {
2718 ALOGD_IF(isDebug(),"%s: MDP Comp not enabled/configured", __FUNCTION__);
Prabhanjan Kandula08222fc2013-07-10 17:20:59 +05302719 return true;
2720 }
2721
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002722 overlay::Overlay& ov = *ctx->mOverlay;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002723 LayerProp *layerProp = ctx->layerProp[mDpy];
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002724
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002725 int numHwLayers = ctx->listStats[mDpy].numAppLayers;
2726 for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ )
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002727 {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002728 if(mCurrentFrame.isFBComposed[i]) continue;
2729
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002730 hwc_layer_1_t *layer = &list->hwLayers[i];
Saurabh Shahacf10202013-02-26 10:15:15 -08002731 private_handle_t *hnd = (private_handle_t *)layer->handle;
2732 if(!hnd) {
2733 ALOGE("%s handle null", __FUNCTION__);
2734 return false;
2735 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002736
2737 if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
2738 continue;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002739 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002740
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002741 int mdpIndex = mCurrentFrame.layerToMDP[i];
2742
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002743 if((isYUVSplitNeeded(hnd) && sEnableYUVsplit) ||
2744 (needs3DComposition(ctx, mDpy) && get3DFormat(hnd) != HAL_NO_3D))
radhakrishnac9a67412013-09-25 17:40:42 +05302745 {
2746 MdpYUVPipeInfo& pipe_info =
2747 *(MdpYUVPipeInfo*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
2748 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
2749 ovutils::eDest indexL = pipe_info.lIndex;
2750 ovutils::eDest indexR = pipe_info.rIndex;
2751 int fd = hnd->fd;
Praveena Pachipulusud9443c72014-02-17 10:42:28 +05302752 uint32_t offset = (uint32_t)hnd->offset;
radhakrishnac9a67412013-09-25 17:40:42 +05302753 if(rot) {
2754 rot->queueBuffer(fd, offset);
2755 fd = rot->getDstMemId();
2756 offset = rot->getDstOffset();
2757 }
2758 if(indexL != ovutils::OV_INVALID) {
2759 ovutils::eDest destL = (ovutils::eDest)indexL;
2760 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2761 using pipe: %d", __FUNCTION__, layer, hnd, indexL );
2762 if (!ov.queueBuffer(fd, offset, destL)) {
2763 ALOGE("%s: queueBuffer failed for display:%d",
2764 __FUNCTION__, mDpy);
2765 return false;
2766 }
2767 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002768
radhakrishnac9a67412013-09-25 17:40:42 +05302769 if(indexR != ovutils::OV_INVALID) {
2770 ovutils::eDest destR = (ovutils::eDest)indexR;
2771 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2772 using pipe: %d", __FUNCTION__, layer, hnd, indexR );
2773 if (!ov.queueBuffer(fd, offset, destR)) {
2774 ALOGE("%s: queueBuffer failed for display:%d",
2775 __FUNCTION__, mDpy);
2776 return false;
2777 }
Saurabh Shaha9da08f2013-07-03 13:27:53 -07002778 }
2779 }
radhakrishnac9a67412013-09-25 17:40:42 +05302780 else{
2781 MdpPipeInfoSplit& pipe_info =
2782 *(MdpPipeInfoSplit*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
2783 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
Saurabh Shaha9da08f2013-07-03 13:27:53 -07002784
radhakrishnac9a67412013-09-25 17:40:42 +05302785 ovutils::eDest indexL = pipe_info.lIndex;
2786 ovutils::eDest indexR = pipe_info.rIndex;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002787
radhakrishnac9a67412013-09-25 17:40:42 +05302788 int fd = hnd->fd;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002789 uint32_t offset = (uint32_t)hnd->offset;
2790 int index = ctx->mPtorInfo.getPTORArrayIndex(i);
2791 if (!mDpy && (index != -1)) {
2792 hnd = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
2793 fd = hnd->fd;
Sushil Chauhan875a92e2014-07-25 12:20:23 -07002794 offset = 0;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002795 }
radhakrishnac9a67412013-09-25 17:40:42 +05302796
Tatenda Chipeperekwa88fe6352014-04-14 10:36:06 -07002797 if(ctx->mAD->draw(ctx, fd, offset)) {
2798 fd = ctx->mAD->getDstFd();
2799 offset = ctx->mAD->getDstOffset();
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002800 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002801
radhakrishnac9a67412013-09-25 17:40:42 +05302802 if(rot) {
2803 rot->queueBuffer(fd, offset);
2804 fd = rot->getDstMemId();
2805 offset = rot->getDstOffset();
2806 }
2807
2808 //************* play left mixer **********
2809 if(indexL != ovutils::OV_INVALID) {
2810 ovutils::eDest destL = (ovutils::eDest)indexL;
2811 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2812 using pipe: %d", __FUNCTION__, layer, hnd, indexL );
2813 if (!ov.queueBuffer(fd, offset, destL)) {
2814 ALOGE("%s: queueBuffer failed for left mixer",
2815 __FUNCTION__);
2816 return false;
2817 }
2818 }
2819
2820 //************* play right mixer **********
2821 if(indexR != ovutils::OV_INVALID) {
2822 ovutils::eDest destR = (ovutils::eDest)indexR;
2823 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2824 using pipe: %d", __FUNCTION__, layer, hnd, indexR );
2825 if (!ov.queueBuffer(fd, offset, destR)) {
2826 ALOGE("%s: queueBuffer failed for right mixer",
2827 __FUNCTION__);
2828 return false;
2829 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002830 }
2831 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002832
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002833 layerProp[i].mFlags &= ~HWC_MDPCOMP;
2834 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002835
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002836 return true;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002837}
Saurabh Shahab47c692014-02-12 18:45:57 -08002838
2839//================MDPCompSrcSplit==============================================
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08002840
2841bool MDPCompSrcSplit::validateAndApplyROI(hwc_context_t *ctx,
2842 hwc_display_contents_1_t* list) {
2843 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
2844 hwc_rect_t visibleRect = ctx->listStats[mDpy].lRoi;
2845
2846 for(int i = numAppLayers - 1; i >= 0; i--) {
2847 if(!isValidRect(visibleRect)) {
2848 mCurrentFrame.drop[i] = true;
2849 mCurrentFrame.dropCount++;
2850 continue;
2851 }
2852
2853 const hwc_layer_1_t* layer = &list->hwLayers[i];
2854 hwc_rect_t dstRect = layer->displayFrame;
2855 hwc_rect_t res = getIntersection(visibleRect, dstRect);
2856
2857 if(!isValidRect(res)) {
2858 mCurrentFrame.drop[i] = true;
2859 mCurrentFrame.dropCount++;
2860 } else {
2861 /* Reset frame ROI when any layer which needs scaling also needs ROI
2862 * cropping */
2863 if(!isSameRect(res, dstRect) && needsScaling (layer)) {
2864 ALOGI("%s: Resetting ROI due to scaling", __FUNCTION__);
2865 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
2866 mCurrentFrame.dropCount = 0;
2867 return false;
2868 }
2869
2870 /* deduct any opaque region from visibleRect */
2871 if (layer->blending == HWC_BLENDING_NONE &&
2872 layer->planeAlpha == 0xFF)
2873 visibleRect = deductRect(visibleRect, res);
2874 }
2875 }
2876 return true;
2877}
2878
2879/*
2880 * HW Limitation: ping pong split can always split the ping pong output
2881 * equally across two DSI's. So the ROI programmed should be of equal width
2882 * for both the halves
2883 */
2884void MDPCompSrcSplit::generateROI(hwc_context_t *ctx,
2885 hwc_display_contents_1_t* list) {
2886 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
2887
2888
2889 if(!canPartialUpdate(ctx, list))
2890 return;
2891
2892 struct hwc_rect roi = (struct hwc_rect){0, 0, 0, 0};
2893 hwc_rect fullFrame = (struct hwc_rect) {0, 0,(int)ctx->dpyAttr[mDpy].xres,
2894 (int)ctx->dpyAttr[mDpy].yres};
2895
2896 for(int index = 0; index < numAppLayers; index++ ) {
2897 hwc_layer_1_t* layer = &list->hwLayers[index];
2898
2899 // If we have a RGB layer which needs rotation, no partial update
2900 if(!isYuvBuffer((private_handle_t *)layer->handle) && layer->transform)
2901 return;
2902
2903 if ((mCachedFrame.hnd[index] != layer->handle) ||
2904 isYuvBuffer((private_handle_t *)layer->handle)) {
2905 hwc_rect_t dst = layer->displayFrame;
2906 hwc_rect_t updatingRect = dst;
2907
2908#ifdef QCOM_BSP
2909 if(!needsScaling(layer) && !layer->transform)
2910 {
2911 hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
2912 int x_off = dst.left - src.left;
2913 int y_off = dst.top - src.top;
2914 updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
2915 }
2916#endif
2917
2918 roi = getUnion(roi, updatingRect);
2919 }
2920 }
2921
2922 /* No layer is updating. Still SF wants a refresh.*/
2923 if(!isValidRect(roi))
2924 return;
2925
2926 roi = expandROIFromMidPoint(roi, fullFrame);
2927
2928 hwc_rect lFrame = fullFrame;
2929 lFrame.right /= 2;
2930 hwc_rect lRoi = getIntersection(roi, lFrame);
2931
2932 // Align ROI coordinates to panel restrictions
2933 lRoi = getSanitizeROI(lRoi, lFrame);
2934
2935 hwc_rect rFrame = fullFrame;
2936 rFrame.left = lFrame.right;
2937 hwc_rect rRoi = getIntersection(roi, rFrame);
2938
2939 // Align ROI coordinates to panel restrictions
2940 rRoi = getSanitizeROI(rRoi, rFrame);
2941
2942 roi = getUnion(lRoi, rRoi);
2943
2944 ctx->listStats[mDpy].lRoi = roi;
2945 if(!validateAndApplyROI(ctx, list))
2946 resetROI(ctx, mDpy);
2947
2948 ALOGD_IF(isDebug(),"%s: generated ROI: [%d, %d, %d, %d] [%d, %d, %d, %d]",
2949 __FUNCTION__,
2950 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
2951 ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom,
2952 ctx->listStats[mDpy].rRoi.left, ctx->listStats[mDpy].rRoi.top,
2953 ctx->listStats[mDpy].rRoi.right, ctx->listStats[mDpy].rRoi.bottom);
2954}
2955
Saurabh Shahab47c692014-02-12 18:45:57 -08002956bool MDPCompSrcSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
Saurabh Shahc62f3982014-03-05 14:28:26 -08002957 MdpPipeInfoSplit& pipe_info) {
Saurabh Shahab47c692014-02-12 18:45:57 -08002958 private_handle_t *hnd = (private_handle_t *)layer->handle;
2959 hwc_rect_t dst = layer->displayFrame;
2960 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
2961 pipe_info.lIndex = ovutils::OV_INVALID;
2962 pipe_info.rIndex = ovutils::OV_INVALID;
2963
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08002964 if(qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() && !mDpy)
2965 trimAgainstROI(ctx,crop, dst);
2966
Saurabh Shahab47c692014-02-12 18:45:57 -08002967 //If 2 pipes are staged on a single stage of a mixer, then the left pipe
2968 //should have a higher priority than the right one. Pipe priorities are
2969 //starting with VG0, VG1 ... , RGB0 ..., DMA1
Saurabh Shahab47c692014-02-12 18:45:57 -08002970
Saurabh Shahc62f3982014-03-05 14:28:26 -08002971 Overlay::PipeSpecs pipeSpecs;
2972 pipeSpecs.formatClass = isYuvBuffer(hnd) ?
2973 Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
2974 pipeSpecs.needsScaling = qhwc::needsScaling(layer);
2975 pipeSpecs.dpy = mDpy;
2976 pipeSpecs.fb = false;
2977
Saurabh Shahab47c692014-02-12 18:45:57 -08002978 //1 pipe by default for a layer
Saurabh Shahc62f3982014-03-05 14:28:26 -08002979 pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahab47c692014-02-12 18:45:57 -08002980 if(pipe_info.lIndex == ovutils::OV_INVALID) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002981 return false;
Saurabh Shahab47c692014-02-12 18:45:57 -08002982 }
2983
Saurabh Shahea7a01d2014-05-22 17:45:36 -07002984 /* Use 2 pipes IF
2985 a) Layer's crop width is > 2048 or
2986 b) Layer's dest width > 2048 or
2987 c) On primary, driver has indicated with caps to split always. This is
2988 based on an empirically derived value of panel height. Applied only
2989 if the layer's width is > mixer's width
2990 */
2991
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +05302992 MDPVersion& mdpHw = MDPVersion::getInstance();
Saurabh Shahea7a01d2014-05-22 17:45:36 -07002993 bool primarySplitAlways = (mDpy == HWC_DISPLAY_PRIMARY) and
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +05302994 mdpHw.isSrcSplitAlways();
Saurabh Shah514759d2014-11-11 18:02:24 -08002995 const uint32_t lSplit = getLeftSplit(ctx, mDpy);
2996 const uint32_t dstWidth = dst.right - dst.left;
2997 const uint32_t dstHeight = dst.bottom - dst.top;
Saurabh Shah05f4e222015-02-05 14:36:22 -08002998 uint32_t cropWidth = has90Transform(layer) ? crop.bottom - crop.top :
Saurabh Shah189f23d2014-09-26 17:21:00 -07002999 crop.right - crop.left;
Saurabh Shah05f4e222015-02-05 14:36:22 -08003000 uint32_t cropHeight = has90Transform(layer) ? crop.right - crop.left :
Saurabh Shah514759d2014-11-11 18:02:24 -08003001 crop.bottom - crop.top;
3002 //Approximation to actual clock, ignoring the common factors in pipe and
3003 //mixer cases like line_time
3004 const uint32_t layerClock = getLayerClock(dstWidth, dstHeight, cropHeight);
3005 const uint32_t mixerClock = lSplit;
Saurabh Shahea7a01d2014-05-22 17:45:36 -07003006
Saurabh Shah05f4e222015-02-05 14:36:22 -08003007 const uint32_t downscale = getRotDownscale(ctx, layer);
3008 if(downscale) {
3009 cropWidth /= downscale;
3010 cropHeight /= downscale;
3011 }
3012
Jeykumar Sankaran39305802014-12-12 17:55:57 -08003013 if(dstWidth > mdpHw.getMaxPipeWidth() or
3014 cropWidth > mdpHw.getMaxPipeWidth() or
Saurabh Shah514759d2014-11-11 18:02:24 -08003015 (primarySplitAlways and
3016 (cropWidth > lSplit or layerClock > mixerClock))) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08003017 pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahab47c692014-02-12 18:45:57 -08003018 if(pipe_info.rIndex == ovutils::OV_INVALID) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08003019 return false;
Saurabh Shahdd8237a2014-02-28 14:29:09 -08003020 }
3021
Jeykumar Sankaran89e23ab2015-01-28 15:57:46 -08003022 if(ctx->mOverlay->needsPrioritySwap(pipe_info.lIndex,
3023 pipe_info.rIndex)) {
Saurabh Shahdd8237a2014-02-28 14:29:09 -08003024 qhwc::swap(pipe_info.lIndex, pipe_info.rIndex);
Saurabh Shahab47c692014-02-12 18:45:57 -08003025 }
3026 }
3027
3028 return true;
3029}
3030
Saurabh Shahab47c692014-02-12 18:45:57 -08003031int MDPCompSrcSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
3032 PipeLayerPair& PipeLayerPair) {
3033 private_handle_t *hnd = (private_handle_t *)layer->handle;
3034 if(!hnd) {
3035 ALOGE("%s: layer handle is NULL", __FUNCTION__);
3036 return -1;
3037 }
3038 MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
3039 MdpPipeInfoSplit& mdp_info =
3040 *(static_cast<MdpPipeInfoSplit*>(PipeLayerPair.pipeInfo));
3041 Rotator **rot = &PipeLayerPair.rot;
3042 eZorder z = static_cast<eZorder>(mdp_info.zOrder);
Saurabh Shahab47c692014-02-12 18:45:57 -08003043 eDest lDest = mdp_info.lIndex;
3044 eDest rDest = mdp_info.rIndex;
3045 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
3046 hwc_rect_t dst = layer->displayFrame;
3047 int transform = layer->transform;
3048 eTransform orient = static_cast<eTransform>(transform);
Saurabh Shahab47c692014-02-12 18:45:57 -08003049 int rotFlags = ROT_FLAGS_NONE;
Sushil Chauhan65e26302015-01-14 10:48:57 -08003050 uint32_t format = ovutils::getMdpFormat(hnd->format, hnd->flags);
Saurabh Shahab47c692014-02-12 18:45:57 -08003051 Whf whf(getWidth(hnd), getHeight(hnd), format, hnd->size);
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05003052 eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shahab47c692014-02-12 18:45:57 -08003053
3054 ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
3055 "dest_pipeR: %d",__FUNCTION__, layer, z, lDest, rDest);
3056
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08003057 if(qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() && !mDpy) {
3058 /* MDP driver crops layer coordinates against ROI in Non-Split
3059 * and Split MDP comp. But HWC needs to crop them for source split.
3060 * Reason: 1) Source split is efficient only when the final effective
3061 * load is distributed evenly across mixers.
3062 * 2) We have to know the effective width of the layer that
3063 * the ROI needs to find the no. of pipes the layer needs.
3064 */
3065 trimAgainstROI(ctx, crop, dst);
3066 }
3067
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05003068 if(needs3DComposition(ctx, mDpy) &&
3069 get3DFormat(hnd) != HAL_NO_3D){
3070 return configure3DVideo(ctx, layer, mDpy, mdpFlags, z, lDest,
3071 rDest, &PipeLayerPair.rot);
3072 }
3073
Saurabh Shahab47c692014-02-12 18:45:57 -08003074 // Handle R/B swap
3075 if (layer->flags & HWC_FORMAT_RB_SWAP) {
3076 if (hnd->format == HAL_PIXEL_FORMAT_RGBA_8888)
3077 whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRA_8888);
3078 else if (hnd->format == HAL_PIXEL_FORMAT_RGBX_8888)
3079 whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
3080 }
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07003081 // update source crop and destination position of AIV video layer.
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07003082 if(ctx->listStats[mDpy].mAIVVideoMode && isYuvBuffer(hnd)) {
3083 updateCoordinates(ctx, crop, dst, mDpy);
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07003084 }
Ramkumar Radhakrishnana5c72872014-08-28 19:04:18 -07003085 /* Calculate the external display position based on MDP downscale,
3086 ActionSafe, and extorientation features. */
3087 calcExtDisplayPosition(ctx, hnd, mDpy, crop, dst, transform, orient);
Saurabh Shahab47c692014-02-12 18:45:57 -08003088
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003089 int downscale = getRotDownscale(ctx, layer);
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003090 setMdpFlags(ctx, layer, mdpFlags, downscale, transform);
Saurabh Shahab47c692014-02-12 18:45:57 -08003091
3092 if(lDest != OV_INVALID && rDest != OV_INVALID) {
3093 //Enable overfetch
Saurabh Shah97e2d802014-04-14 18:03:54 -07003094 setMdpFlags(mdpFlags, OV_MDSS_MDP_DUAL_PIPE);
Saurabh Shahab47c692014-02-12 18:45:57 -08003095 }
3096
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003097 if((has90Transform(layer) or downscale) and isRotationDoable(ctx, hnd)) {
Saurabh Shahab47c692014-02-12 18:45:57 -08003098 (*rot) = ctx->mRotMgr->getNext();
3099 if((*rot) == NULL) return -1;
Saurabh Shah39240c92014-03-31 10:31:42 -07003100 ctx->mLayerRotMap[mDpy]->add(layer, *rot);
Saurabh Shah1bd5b6f2014-05-19 12:23:13 -07003101 //If the video is using a single pipe, enable BWC
3102 if(rDest == OV_INVALID) {
Saurabh Shahcd018352014-11-11 13:54:19 -08003103 BwcPM::setBwc(ctx, mDpy, hnd, crop, dst, transform, downscale,
3104 mdpFlags);
Saurabh Shah1bd5b6f2014-05-19 12:23:13 -07003105 }
Saurabh Shahab47c692014-02-12 18:45:57 -08003106 //Configure rotator for pre-rotation
Saurabh Shah97e2d802014-04-14 18:03:54 -07003107 if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale) < 0) {
Saurabh Shahab47c692014-02-12 18:45:57 -08003108 ALOGE("%s: configRotator failed!", __FUNCTION__);
3109 return -1;
3110 }
Saurabh Shah8ec9b5e2014-06-30 14:37:17 -07003111 updateSource(orient, whf, crop, *rot);
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003112 rotFlags |= ovutils::ROT_PREROTATED;
Saurabh Shahab47c692014-02-12 18:45:57 -08003113 }
3114
3115 //If 2 pipes being used, divide layer into half, crop and dst
3116 hwc_rect_t cropL = crop;
3117 hwc_rect_t cropR = crop;
3118 hwc_rect_t dstL = dst;
3119 hwc_rect_t dstR = dst;
3120 if(lDest != OV_INVALID && rDest != OV_INVALID) {
3121 cropL.right = (crop.right + crop.left) / 2;
3122 cropR.left = cropL.right;
3123 sanitizeSourceCrop(cropL, cropR, hnd);
3124
Saurabh Shahb729b192014-08-15 18:04:24 -07003125 bool cropSwap = false;
Saurabh Shahab47c692014-02-12 18:45:57 -08003126 //Swap crops on H flip since 2 pipes are being used
3127 if((orient & OVERLAY_TRANSFORM_FLIP_H) && (*rot) == NULL) {
3128 hwc_rect_t tmp = cropL;
3129 cropL = cropR;
3130 cropR = tmp;
Saurabh Shahb729b192014-08-15 18:04:24 -07003131 cropSwap = true;
Saurabh Shahab47c692014-02-12 18:45:57 -08003132 }
3133
Saurabh Shahb729b192014-08-15 18:04:24 -07003134 //cropSwap trick: If the src and dst widths are both odd, let us say
3135 //2507, then splitting both into half would cause left width to be 1253
3136 //and right 1254. If crop is swapped because of H flip, this will cause
3137 //left crop width to be 1254, whereas left dst width remains 1253, thus
3138 //inducing a scaling that is unaccounted for. To overcome that we add 1
3139 //to the dst width if there is a cropSwap. So if the original width was
3140 //2507, the left dst width will be 1254. Even if the original width was
3141 //even for ex: 2508, the left dst width will still remain 1254.
3142 dstL.right = (dst.right + dst.left + cropSwap) / 2;
Saurabh Shahab47c692014-02-12 18:45:57 -08003143 dstR.left = dstL.right;
3144 }
3145
3146 //For the mdp, since either we are pre-rotating or MDP does flips
3147 orient = OVERLAY_TRANSFORM_0;
3148 transform = 0;
3149
3150 //configure left pipe
3151 if(lDest != OV_INVALID) {
Saurabh Shah2c8ad052014-08-15 13:27:46 -07003152 PipeArgs pargL(mdpFlags, whf, z,
Saurabh Shahab47c692014-02-12 18:45:57 -08003153 static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
3154 (ovutils::eBlending) getBlending(layer->blending));
3155
3156 if(configMdp(ctx->mOverlay, pargL, orient,
3157 cropL, dstL, metadata, lDest) < 0) {
3158 ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
3159 return -1;
3160 }
3161 }
3162
3163 //configure right pipe
3164 if(rDest != OV_INVALID) {
Saurabh Shah2c8ad052014-08-15 13:27:46 -07003165 PipeArgs pargR(mdpFlags, whf, z,
Saurabh Shahab47c692014-02-12 18:45:57 -08003166 static_cast<eRotFlags>(rotFlags),
3167 layer->planeAlpha,
3168 (ovutils::eBlending) getBlending(layer->blending));
3169 if(configMdp(ctx->mOverlay, pargR, orient,
3170 cropR, dstR, metadata, rDest) < 0) {
3171 ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
3172 return -1;
3173 }
3174 }
3175
3176 return 0;
3177}
3178
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -08003179bool MDPComp::getPartialUpdatePref(hwc_context_t *ctx) {
3180 Locker::Autolock _l(ctx->mDrawLock);
3181 const int fbNum = Overlay::getFbForDpy(Overlay::DPY_PRIMARY);
3182 char path[MAX_SYSFS_FILE_PATH];
3183 snprintf (path, sizeof(path), "sys/class/graphics/fb%d/dyn_pu", fbNum);
3184 int fd = open(path, O_RDONLY);
3185 if(fd < 0) {
3186 ALOGE("%s: Failed to open sysfd node: %s", __FUNCTION__, path);
3187 return -1;
3188 }
3189 char value[4];
3190 ssize_t size_read = read(fd, value, sizeof(value)-1);
3191 if(size_read <= 0) {
3192 ALOGE("%s: Failed to read sysfd node: %s", __FUNCTION__, path);
3193 close(fd);
3194 return -1;
3195 }
3196 close(fd);
3197 value[size_read] = '\0';
3198 return atoi(value);
3199}
3200
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003201int MDPComp::setPartialUpdatePref(hwc_context_t *ctx, bool enable) {
3202 Locker::Autolock _l(ctx->mDrawLock);
3203 const int fbNum = Overlay::getFbForDpy(Overlay::DPY_PRIMARY);
3204 char path[MAX_SYSFS_FILE_PATH];
3205 snprintf (path, sizeof(path), "sys/class/graphics/fb%d/dyn_pu", fbNum);
3206 int fd = open(path, O_WRONLY);
3207 if(fd < 0) {
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -08003208 ALOGE("%s: Failed to open sysfd node: %s", __FUNCTION__, path);
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003209 return -1;
3210 }
3211 char value[4];
3212 snprintf(value, sizeof(value), "%d", (int)enable);
3213 ssize_t ret = write(fd, value, strlen(value));
3214 if(ret <= 0) {
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -08003215 ALOGE("%s: Failed to write to sysfd nodes: %s", __FUNCTION__, path);
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003216 close(fd);
3217 return -1;
3218 }
3219 close(fd);
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003220 return 0;
3221}
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08003222
3223bool MDPComp::loadPerfLib() {
3224 char perfLibPath[PROPERTY_VALUE_MAX] = {0};
3225 bool success = false;
3226 if((property_get("ro.vendor.extension_library", perfLibPath, NULL) <= 0)) {
3227 ALOGE("vendor library not set in ro.vendor.extension_library");
3228 return false;
3229 }
3230
3231 sLibPerfHint = dlopen(perfLibPath, RTLD_NOW);
3232 if(sLibPerfHint) {
3233 *(void **)&sPerfLockAcquire = dlsym(sLibPerfHint, "perf_lock_acq");
3234 *(void **)&sPerfLockRelease = dlsym(sLibPerfHint, "perf_lock_rel");
3235 if (!sPerfLockAcquire || !sPerfLockRelease) {
3236 ALOGE("Failed to load symbols for perfLock");
3237 dlclose(sLibPerfHint);
3238 sLibPerfHint = NULL;
3239 return false;
3240 }
3241 success = true;
3242 ALOGI("Successfully Loaded perf hint API's");
3243 } else {
3244 ALOGE("Failed to open %s : %s", perfLibPath, dlerror());
3245 }
3246 return success;
3247}
3248
3249void MDPComp::setPerfHint(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
3250 if ((sPerfHintWindow < 0) || mDpy || !sLibPerfHint) {
3251 return;
3252 }
3253 static int count = sPerfHintWindow;
3254 static int perflockFlag = 0;
3255
3256 /* Send hint to mpctl when single layer is updated
3257 * for a successful number of windows. Hint release
3258 * happens immediately upon multiple layer update.
3259 */
3260 if (onlyVideosUpdating(ctx, list)) {
3261 if(count) {
3262 count--;
3263 }
3264 } else {
3265 if (perflockFlag) {
3266 perflockFlag = 0;
3267 sPerfLockRelease(sPerfLockHandle);
3268 }
3269 count = sPerfHintWindow;
3270 }
3271 if (count == 0 && !perflockFlag) {
3272 int perfHint = 0x4501; // 45-display layer hint, 01-Enable
3273 sPerfLockHandle = sPerfLockAcquire(0 /*handle*/, 0/*duration*/,
3274 &perfHint, sizeof(perfHint)/sizeof(int));
Arun Kumar K.R8b927022015-02-24 12:34:21 -08003275 if(sPerfLockHandle > 0) {
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08003276 perflockFlag = 1;
3277 }
3278 }
3279}
3280
Naseer Ahmed7c958d42012-07-31 18:57:03 -07003281}; //namespace
3282