blob: a81913db2d9dfabfb27849d06d52215852a84cf7 [file] [log] [blame]
Naseer Ahmed7c958d42012-07-31 18:57:03 -07001/*
Tatenda Chipeperekwa95675a72014-12-15 17:06:43 -08002 * Copyright (C) 2012-2015, The Linux Foundation. All rights reserved.
Naseer Ahmed7c958d42012-07-31 18:57:03 -07003 * Not a Contribution, Apache license notifications and license are retained
4 * for attribution purposes only.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
Saurabh Shah4fdde762013-04-30 18:47:33 -070019#include <math.h>
Naseer Ahmed7c958d42012-07-31 18:57:03 -070020#include "hwc_mdpcomp.h"
Arun Kumar K.R299bcda2014-12-18 19:36:40 -080021#include <dlfcn.h>
Tatenda Chipeperekwaaf2c0042014-09-17 12:55:01 -070022#include "hdmi.h"
Ramkumar Radhakrishnan47573e22012-11-07 11:36:41 -080023#include "qdMetaData.h"
Ramkumar Radhakrishnan288f8c72013-01-15 11:37:54 -080024#include "mdp_version.h"
Saurabh Shah2a4eb1b2013-07-22 16:33:23 -070025#include "hwc_fbupdate.h"
Saurabh Shaha9da08f2013-07-03 13:27:53 -070026#include "hwc_ad.h"
Saurabh Shahacf10202013-02-26 10:15:15 -080027#include <overlayRotator.h>
Arun Kumar K.R00b84792015-03-27 11:28:36 -070028#include <overlayCursor.h>
Sushil Chauhandefd3522014-05-13 18:17:12 -070029#include "hwc_copybit.h"
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -070030#include "qd_utils.h"
Saurabh Shahacf10202013-02-26 10:15:15 -080031
Saurabh Shah85234ec2013-04-12 17:09:00 -070032using namespace overlay;
Saurabh Shahbd2d0832013-04-04 14:33:08 -070033using namespace qdutils;
Saurabh Shahacf10202013-02-26 10:15:15 -080034using namespace overlay::utils;
35namespace ovutils = overlay::utils;
Naseer Ahmed7c958d42012-07-31 18:57:03 -070036
Naseer Ahmed7c958d42012-07-31 18:57:03 -070037namespace qhwc {
38
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -080039//==============MDPComp========================================================
40
Saurabh Shah59562ff2014-09-30 16:13:12 -070041IdleInvalidator *MDPComp::sIdleInvalidator = NULL;
Naseer Ahmed7c958d42012-07-31 18:57:03 -070042bool MDPComp::sIdleFallBack = false;
43bool MDPComp::sDebugLogs = false;
Naseer Ahmed54821fe2012-11-28 18:44:38 -050044bool MDPComp::sEnabled = false;
Jeykumar Sankaran24c199d2013-05-24 09:40:36 -070045bool MDPComp::sEnableMixedMode = true;
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -070046int MDPComp::sSimulationFlags = 0;
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -070047int MDPComp::sMaxPipesPerMixer = 0;
Raj Kamal389d6e32014-08-04 14:43:24 +053048bool MDPComp::sEnableYUVsplit = false;
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -070049bool MDPComp::sSrcSplitEnabled = false;
Saurabh Shahacec8e42014-11-25 11:07:04 -080050int MDPComp::sMaxSecLayers = 1;
Dileep Kumar Reddi4070e932014-09-30 09:00:57 +053051bool MDPComp::enablePartialUpdateForMDP3 = false;
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -070052bool MDPComp::sIsPartialUpdateActive = true;
Arun Kumar K.R299bcda2014-12-18 19:36:40 -080053void *MDPComp::sLibPerfHint = NULL;
54int MDPComp::sPerfLockHandle = 0;
55int (*MDPComp::sPerfLockAcquire)(int, int, int*, int) = NULL;
56int (*MDPComp::sPerfLockRelease)(int value) = NULL;
57int MDPComp::sPerfHintWindow = -1;
radhakrishna35e33072015-04-08 17:20:43 +053058float MDPComp::sDownscaleThreshold = 1.0;
Arun Kumar K.R299bcda2014-12-18 19:36:40 -080059
Saurabh Shah8cc77712015-03-31 10:48:51 -070060enum AllocOrder { FORMAT_YUV, FORMAT_RGB, FORMAT_MAX };
61
Saurabh Shah88e4d272013-09-03 13:31:29 -070062MDPComp* MDPComp::getObject(hwc_context_t *ctx, const int& dpy) {
Saurabh Shah60e8bde2014-04-30 14:46:03 -070063 if(qdutils::MDPVersion::getInstance().isSrcSplit()) {
64 sSrcSplitEnabled = true;
65 return new MDPCompSrcSplit(dpy);
66 } else if(isDisplaySplit(ctx, dpy)) {
Saurabh Shah88e4d272013-09-03 13:31:29 -070067 return new MDPCompSplit(dpy);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -080068 }
Saurabh Shah88e4d272013-09-03 13:31:29 -070069 return new MDPCompNonSplit(dpy);
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -080070}
71
Saurabh Shahac279de2015-05-21 18:56:58 -070072MDPComp::MDPComp(int dpy) : mDpy(dpy), mModeOn(false), mPrevModeOn(false) {
73};
Jeykumar Sankaran85977e32013-02-25 17:06:08 -080074
Jeykumar Sankaran6850ac62014-05-27 10:07:26 -070075void MDPComp::dump(android::String8& buf, hwc_context_t *ctx)
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -080076{
Jeykumar Sankaran3c6bb042013-08-15 14:01:04 -070077 if(mCurrentFrame.layerCount > MAX_NUM_APP_LAYERS)
78 return;
79
Jeykumar Sankaran85977e32013-02-25 17:06:08 -080080 dumpsys_log(buf,"HWC Map for Dpy: %s \n",
Jeykumar Sankaran27dee262013-08-01 17:09:54 -070081 (mDpy == 0) ? "\"PRIMARY\"" :
82 (mDpy == 1) ? "\"EXTERNAL\"" : "\"VIRTUAL\"");
Saurabh Shahe9bc60f2013-08-29 12:58:06 -070083 dumpsys_log(buf,"CURR_FRAME: layerCount:%2d mdpCount:%2d "
Arun Kumar K.R00b84792015-03-27 11:28:36 -070084 "fbCount:%2d dropCount:%2d\n", mCurrentFrame.layerCount,
85 mCurrentFrame.mdpCount, mCurrentFrame.fbCount, mCurrentFrame.dropCount);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -080086 dumpsys_log(buf,"needsFBRedraw:%3s pipesUsed:%2d MaxPipesPerMixer: %d \n",
87 (mCurrentFrame.needsRedraw? "YES" : "NO"),
88 mCurrentFrame.mdpCount, sMaxPipesPerMixer);
Jeykumar Sankaran6850ac62014-05-27 10:07:26 -070089 if(isDisplaySplit(ctx, mDpy)) {
90 dumpsys_log(buf, "Programmed ROI's: Left: [%d, %d, %d, %d] "
91 "Right: [%d, %d, %d, %d] \n",
92 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
93 ctx->listStats[mDpy].lRoi.right,
94 ctx->listStats[mDpy].lRoi.bottom,
95 ctx->listStats[mDpy].rRoi.left,ctx->listStats[mDpy].rRoi.top,
96 ctx->listStats[mDpy].rRoi.right,
97 ctx->listStats[mDpy].rRoi.bottom);
98 } else {
99 dumpsys_log(buf, "Programmed ROI: [%d, %d, %d, %d] \n",
100 ctx->listStats[mDpy].lRoi.left,ctx->listStats[mDpy].lRoi.top,
101 ctx->listStats[mDpy].lRoi.right,
102 ctx->listStats[mDpy].lRoi.bottom);
103 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800104 dumpsys_log(buf," --------------------------------------------- \n");
105 dumpsys_log(buf," listIdx | cached? | mdpIndex | comptype | Z \n");
106 dumpsys_log(buf," --------------------------------------------- \n");
107 for(int index = 0; index < mCurrentFrame.layerCount; index++ )
108 dumpsys_log(buf," %7d | %7s | %8d | %9s | %2d \n",
109 index,
110 (mCurrentFrame.isFBComposed[index] ? "YES" : "NO"),
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700111 mCurrentFrame.layerToMDP[index],
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800112 (mCurrentFrame.isFBComposed[index] ?
Arun Kumar K.R00b84792015-03-27 11:28:36 -0700113 (mCurrentFrame.drop[index] ?
114 ((mCurrentFrame.hwCursorIndex == index) ? "CURSOR": "DROP"):
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700115 (mCurrentFrame.needsRedraw ? "GLES" : "CACHE")) : "MDP"),
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800116 (mCurrentFrame.isFBComposed[index] ? mCurrentFrame.fbZ :
117 mCurrentFrame.mdpToLayer[mCurrentFrame.layerToMDP[index]].pipeInfo->zOrder));
118 dumpsys_log(buf,"\n");
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800119}
120
121bool MDPComp::init(hwc_context_t *ctx) {
122
123 if(!ctx) {
124 ALOGE("%s: Invalid hwc context!!",__FUNCTION__);
125 return false;
126 }
127
Saurabh Shah59562ff2014-09-30 16:13:12 -0700128 char property[PROPERTY_VALUE_MAX] = {0};
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800129
130 sEnabled = false;
Dileep Kumar Reddid8e601d2014-10-28 18:20:43 +0530131 if((ctx->mMDP.version >= qdutils::MDP_V4_0) &&
132 (property_get("persist.hwc.mdpcomp.enable", property, NULL) > 0) &&
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800133 (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
134 (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800135 sEnabled = true;
136 }
137
Jeykumar Sankaran24c199d2013-05-24 09:40:36 -0700138 sEnableMixedMode = true;
139 if((property_get("debug.mdpcomp.mixedmode.disable", property, NULL) > 0) &&
140 (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
141 (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
142 sEnableMixedMode = false;
143 }
144
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700145 qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
146
Saurabh Shah2fd8a252014-12-05 13:49:53 -0800147 sMaxPipesPerMixer = (int)mdpVersion.getBlendStages();
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700148 if(property_get("persist.hwc.mdpcomp.maxpermixer", property, "-1") > 0) {
Saurabh Shah85234ec2013-04-12 17:09:00 -0700149 int val = atoi(property);
150 if(val >= 0)
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700151 sMaxPipesPerMixer = min(val, sMaxPipesPerMixer);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800152 }
153
Saurabh Shahacec8e42014-11-25 11:07:04 -0800154 /* Maximum layers allowed to use MDP on secondary panels. If property
155 * doesn't exist, default to 1. Using the property it can be set to 0 or
156 * more.
157 */
158 if(property_get("persist.hwc.maxseclayers", property, "1") > 0) {
159 int val = atoi(property);
160 sMaxSecLayers = (val >= 0) ? val : 1;
161 sMaxSecLayers = min(sMaxSecLayers, sMaxPipesPerMixer);
162 }
163
Naseer Ahmedf40f2c82013-08-14 16:42:40 -0400164 if(ctx->mMDP.panel != MIPI_CMD_PANEL) {
Saurabh Shah59562ff2014-09-30 16:13:12 -0700165 sIdleInvalidator = IdleInvalidator::getInstance();
166 if(sIdleInvalidator->init(timeout_handler, ctx) < 0) {
167 delete sIdleInvalidator;
168 sIdleInvalidator = NULL;
Naseer Ahmedf40f2c82013-08-14 16:42:40 -0400169 }
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800170 }
radhakrishnac9a67412013-09-25 17:40:42 +0530171
Saurabh Shah7c727642014-06-02 15:47:14 -0700172 if(!qdutils::MDPVersion::getInstance().isSrcSplit() &&
Saurabh Shahc46cf9d2014-07-02 15:22:34 -0700173 !qdutils::MDPVersion::getInstance().isRotDownscaleEnabled() &&
Saurabh Shah7c727642014-06-02 15:47:14 -0700174 property_get("persist.mdpcomp.4k2kSplit", property, "0") > 0 &&
175 (!strncmp(property, "1", PROPERTY_VALUE_MAX) ||
176 !strncasecmp(property,"true", PROPERTY_VALUE_MAX))) {
Raj Kamal389d6e32014-08-04 14:43:24 +0530177 sEnableYUVsplit = true;
radhakrishnac9a67412013-09-25 17:40:42 +0530178 }
Sushil Chauhandefd3522014-05-13 18:17:12 -0700179
Dileep Kumar Reddic6ef3472014-09-24 19:07:08 +0530180 bool defaultPTOR = false;
181 //Enable PTOR when "persist.hwc.ptor.enable" is not defined for
Prabhanjan Kandulafc541b32015-03-30 20:56:16 +0530182 //Bear family targets by default
Dileep Kumar Reddic6ef3472014-09-24 19:07:08 +0530183 if((property_get("persist.hwc.ptor.enable", property, NULL) <= 0) &&
184 (qdutils::MDPVersion::getInstance().is8x16() ||
Prabhanjan Kandulafc541b32015-03-30 20:56:16 +0530185 qdutils::MDPVersion::getInstance().is8x39() ||
186 qdutils::MDPVersion::getInstance().is8x52())) {
Dileep Kumar Reddic6ef3472014-09-24 19:07:08 +0530187 defaultPTOR = true;
188 }
189
190 if (defaultPTOR || (!strncasecmp(property, "true", PROPERTY_VALUE_MAX)) ||
191 (!strncmp(property, "1", PROPERTY_VALUE_MAX ))) {
Sushil Chauhandefd3522014-05-13 18:17:12 -0700192 ctx->mCopyBit[HWC_DISPLAY_PRIMARY] = new CopyBit(ctx,
193 HWC_DISPLAY_PRIMARY);
194 }
195
Dileep Kumar Reddi4070e932014-09-30 09:00:57 +0530196 if((property_get("persist.mdp3.partialUpdate", property, NULL) <= 0) &&
197 (ctx->mMDP.version == qdutils::MDP_V3_0_5)) {
198 enablePartialUpdateForMDP3 = true;
199 }
200
201 if(!enablePartialUpdateForMDP3 &&
202 (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
203 (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
204 enablePartialUpdateForMDP3 = true;
205 }
206
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -0800207 sIsPartialUpdateActive = getPartialUpdatePref(ctx);
208
Arun Kumar K.R299bcda2014-12-18 19:36:40 -0800209 if(property_get("persist.mdpcomp_perfhint", property, "-1") > 0) {
210 int val = atoi(property);
211 if(val > 0 && loadPerfLib()) {
212 sPerfHintWindow = val;
213 ALOGI("PerfHintWindow = %d", sPerfHintWindow);
214 }
215 }
216
radhakrishna35e33072015-04-08 17:20:43 +0530217 if(property_get("persist.hwc.downscale_threshold", property, "1.0") > 0) {
218 sDownscaleThreshold = (float)atof(property);
219 }
220
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700221 return true;
222}
223
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800224void MDPComp::reset(hwc_context_t *ctx) {
225 const int numLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shah2a4eb1b2013-07-22 16:33:23 -0700226 mCurrentFrame.reset(numLayers);
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800227 ctx->mOverlay->clear(mDpy);
228 ctx->mLayerRotMap[mDpy]->clear();
Saurabh Shah2a4eb1b2013-07-22 16:33:23 -0700229}
230
Raj Kamal4393eaa2014-06-06 13:45:20 +0530231void MDPComp::reset() {
Raj Kamalfdfdddf2015-03-16 21:59:25 +0530232 mPrevModeOn = mModeOn;
Raj Kamal4393eaa2014-06-06 13:45:20 +0530233 mModeOn = false;
234}
235
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700236void MDPComp::timeout_handler(void *udata) {
237 struct hwc_context_t* ctx = (struct hwc_context_t*)(udata);
Raj Kamalfdfdddf2015-03-16 21:59:25 +0530238 bool handleTimeout = false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700239
240 if(!ctx) {
241 ALOGE("%s: received empty data in timer callback", __FUNCTION__);
242 return;
243 }
Raj Kamal58b31a02014-12-16 15:53:53 +0530244
245 ctx->mDrawLock.lock();
Raj Kamalfdfdddf2015-03-16 21:59:25 +0530246
247 /* Handle timeout event only if the previous composition
248 on any display is MDP or MIXED*/
249 for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
250 if(ctx->mMDPComp[i])
251 handleTimeout =
252 ctx->mMDPComp[i]->isMDPComp() || handleTimeout;
253 }
254
255 if(!handleTimeout) {
Ramkumar Radhakrishnan92abb4f2014-02-06 21:31:29 -0800256 ALOGD_IF(isDebug(), "%s:Do not handle this timeout", __FUNCTION__);
Raj Kamal58b31a02014-12-16 15:53:53 +0530257 ctx->mDrawLock.unlock();
Ramkumar Radhakrishnan92abb4f2014-02-06 21:31:29 -0800258 return;
259 }
Jesse Hall3be78d92012-08-21 15:12:23 -0700260 if(!ctx->proc) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700261 ALOGE("%s: HWC proc not registered", __FUNCTION__);
Raj Kamal58b31a02014-12-16 15:53:53 +0530262 ctx->mDrawLock.unlock();
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700263 return;
264 }
265 sIdleFallBack = true;
Raj Kamal58b31a02014-12-16 15:53:53 +0530266 ctx->mDrawLock.unlock();
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700267 /* Trigger SF to redraw the current frame */
Jesse Hall3be78d92012-08-21 15:12:23 -0700268 ctx->proc->invalidate(ctx->proc);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700269}
270
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700271void MDPComp::setMaxPipesPerMixer(const uint32_t value) {
272 qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
Saurabh Shah2fd8a252014-12-05 13:49:53 -0800273 uint32_t maxSupported = (int)mdpVersion.getBlendStages();
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700274 if(value > maxSupported) {
275 ALOGW("%s: Input exceeds max value supported. Setting to"
276 "max value: %d", __FUNCTION__, maxSupported);
277 }
278 sMaxPipesPerMixer = min(value, maxSupported);
279}
280
Saurabh Shah59562ff2014-09-30 16:13:12 -0700281void MDPComp::setIdleTimeout(const uint32_t& timeout) {
282 enum { ONE_REFRESH_PERIOD_MS = 17, ONE_BILLION_MS = 1000000000 };
283
284 if(sIdleInvalidator) {
285 if(timeout <= ONE_REFRESH_PERIOD_MS) {
286 //If the specified timeout is < 1 draw cycle worth, "virtually"
287 //disable idle timeout. The ideal way for clients to disable
288 //timeout is to set it to 0
289 sIdleInvalidator->setIdleTimeout(ONE_BILLION_MS);
290 ALOGI("Disabled idle timeout");
291 return;
292 }
293 sIdleInvalidator->setIdleTimeout(timeout);
294 ALOGI("Idle timeout set to %u", timeout);
295 } else {
296 ALOGW("Cannot set idle timeout, IdleInvalidator not enabled");
297 }
298}
299
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800300void MDPComp::setMDPCompLayerFlags(hwc_context_t *ctx,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800301 hwc_display_contents_1_t* list) {
302 LayerProp *layerProp = ctx->layerProp[mDpy];
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800303
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800304 for(int index = 0; index < ctx->listStats[mDpy].numAppLayers; index++) {
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800305 hwc_layer_1_t* layer = &(list->hwLayers[index]);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800306 if(!mCurrentFrame.isFBComposed[index]) {
307 layerProp[index].mFlags |= HWC_MDPCOMP;
308 layer->compositionType = HWC_OVERLAY;
309 layer->hints |= HWC_HINT_CLEAR_FB;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800310 } else {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700311 /* Drop the layer when its already present in FB OR when it lies
312 * outside frame's ROI */
313 if(!mCurrentFrame.needsRedraw || mCurrentFrame.drop[index]) {
Arun Kumar K.R00b84792015-03-27 11:28:36 -0700314 if(index == mCurrentFrame.hwCursorIndex) {
315 layer->compositionType = HWC_CURSOR_OVERLAY;
316 } else {
317 layer->compositionType = HWC_OVERLAY;
318 }
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700319 }
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800320 }
321 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700322}
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500323
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800324void MDPComp::setRedraw(hwc_context_t *ctx,
325 hwc_display_contents_1_t* list) {
326 mCurrentFrame.needsRedraw = false;
327 if(!mCachedFrame.isSameFrame(mCurrentFrame, list) ||
328 (list->flags & HWC_GEOMETRY_CHANGED) ||
329 isSkipPresent(ctx, mDpy)) {
330 mCurrentFrame.needsRedraw = true;
331 }
332}
333
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800334MDPComp::FrameInfo::FrameInfo() {
Saurabh Shahf7fad542014-08-14 10:11:36 -0700335 memset(&mdpToLayer, 0, sizeof(mdpToLayer));
Saurabh Shahaa236822013-04-24 18:07:26 -0700336 reset(0);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800337}
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800338
Saurabh Shahaa236822013-04-24 18:07:26 -0700339void MDPComp::FrameInfo::reset(const int& numLayers) {
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700340 for(int i = 0 ; i < MAX_NUM_BLEND_STAGES; i++ ) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800341 if(mdpToLayer[i].pipeInfo) {
342 delete mdpToLayer[i].pipeInfo;
343 mdpToLayer[i].pipeInfo = NULL;
344 //We dont own the rotator
345 mdpToLayer[i].rot = NULL;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800346 }
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800347 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800348
349 memset(&mdpToLayer, 0, sizeof(mdpToLayer));
350 memset(&layerToMDP, -1, sizeof(layerToMDP));
Saurabh Shahaa236822013-04-24 18:07:26 -0700351 memset(&isFBComposed, 1, sizeof(isFBComposed));
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800352
Saurabh Shahaa236822013-04-24 18:07:26 -0700353 layerCount = numLayers;
354 fbCount = numLayers;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800355 mdpCount = 0;
Saurabh Shah2f3895f2013-05-02 10:13:31 -0700356 needsRedraw = true;
Saurabh Shahd53bc5f2014-02-05 10:17:43 -0800357 fbZ = -1;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800358}
359
Saurabh Shahaa236822013-04-24 18:07:26 -0700360void MDPComp::FrameInfo::map() {
361 // populate layer and MDP maps
362 int mdpIdx = 0;
363 for(int idx = 0; idx < layerCount; idx++) {
364 if(!isFBComposed[idx]) {
365 mdpToLayer[mdpIdx].listIndex = idx;
366 layerToMDP[idx] = mdpIdx++;
367 }
368 }
369}
370
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800371MDPComp::LayerCache::LayerCache() {
372 reset();
373}
374
375void MDPComp::LayerCache::reset() {
Saurabh Shahaa236822013-04-24 18:07:26 -0700376 memset(&hnd, 0, sizeof(hnd));
Prabhanjan Kandula2243aa62013-10-24 12:58:55 +0530377 memset(&isFBComposed, true, sizeof(isFBComposed));
378 memset(&drop, false, sizeof(drop));
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800379 layerCount = 0;
Saurabh Shahaa236822013-04-24 18:07:26 -0700380}
381
382void MDPComp::LayerCache::cacheAll(hwc_display_contents_1_t* list) {
Praveena Pachipulusud9443c72014-02-17 10:42:28 +0530383 const int numAppLayers = (int)list->numHwLayers - 1;
Saurabh Shahaa236822013-04-24 18:07:26 -0700384 for(int i = 0; i < numAppLayers; i++) {
385 hnd[i] = list->hwLayers[i].handle;
386 }
387}
388
389void MDPComp::LayerCache::updateCounts(const FrameInfo& curFrame) {
Saurabh Shahaa236822013-04-24 18:07:26 -0700390 layerCount = curFrame.layerCount;
Prabhanjan Kandula2243aa62013-10-24 12:58:55 +0530391 memcpy(&isFBComposed, &curFrame.isFBComposed, sizeof(isFBComposed));
392 memcpy(&drop, &curFrame.drop, sizeof(drop));
393}
394
Jeykumar Sankaran988d3682013-11-15 11:57:16 -0800395bool MDPComp::LayerCache::isSameFrame(const FrameInfo& curFrame,
396 hwc_display_contents_1_t* list) {
Prabhanjan Kandula2243aa62013-10-24 12:58:55 +0530397 if(layerCount != curFrame.layerCount)
398 return false;
399 for(int i = 0; i < curFrame.layerCount; i++) {
400 if((curFrame.isFBComposed[i] != isFBComposed[i]) ||
401 (curFrame.drop[i] != drop[i])) {
402 return false;
403 }
Jeykumar Sankaran988d3682013-11-15 11:57:16 -0800404 if(curFrame.isFBComposed[i] &&
405 (hnd[i] != list->hwLayers[i].handle)){
406 return false;
407 }
Prabhanjan Kandula2243aa62013-10-24 12:58:55 +0530408 }
409 return true;
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800410}
411
Raj Kamalfdfdddf2015-03-16 21:59:25 +0530412bool MDPComp::LayerCache::isSameFrame(hwc_context_t *ctx, int dpy,
413 hwc_display_contents_1_t* list) {
414
415 if(layerCount != ctx->listStats[dpy].numAppLayers)
416 return false;
417
418 if((list->flags & HWC_GEOMETRY_CHANGED) ||
419 isSkipPresent(ctx, dpy)) {
420 return false;
421 }
422
423 for(int i = 0; i < layerCount; i++) {
424 if(hnd[i] != list->hwLayers[i].handle)
425 return false;
426 }
427
428 return true;
429}
430
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700431bool MDPComp::isSupportedForMDPComp(hwc_context_t *ctx, hwc_layer_1_t* layer) {
432 private_handle_t *hnd = (private_handle_t *)layer->handle;
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800433 if((has90Transform(layer) and (not isRotationDoable(ctx, hnd))) ||
Raj Kamal1179d9c2014-10-28 15:31:35 +0530434 (not isValidDimension(ctx,layer)) ||
435 isSkipLayer(layer)) {
436 //More conditions here, sRGB+Blend etc
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700437 return false;
438 }
radhakrishna35e33072015-04-08 17:20:43 +0530439
440 //In targets with fewer pipes, frequent composition switch between MDP/GPU
441 //can happen for a layer due to lack of pipes. When this switch happens
442 //continuously for RGB downscaled layer with downscale greater than
443 //threshold, it appears as flicker as output
444 //of MDP and GPU are different as they use different filters for downscale.
445 //To avoid this flicker, punt RGB downscaled layer with downscale greater
446 //than threshold value to GPU always.
447 if((sDownscaleThreshold > 1.0)) {
448 if(((not isYuvBuffer(hnd))
449 and (not isDownscaleWithinThreshold(layer,
450 sDownscaleThreshold)))) {
451 ALOGD_IF(isDebug(), "%s: required downscale is greater than \
452 threshold %f", __FUNCTION__, sDownscaleThreshold);
453 return false;
454 }
455 }
456
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700457 return true;
458}
459
Sravan Kumar D.V.Nad5d9292013-04-24 14:23:04 +0530460bool MDPComp::isValidDimension(hwc_context_t *ctx, hwc_layer_1_t *layer) {
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800461 private_handle_t *hnd = (private_handle_t *)layer->handle;
462
463 if(!hnd) {
Sushil Chauhan897a9c32013-07-18 11:09:55 -0700464 if (layer->flags & HWC_COLOR_FILL) {
465 // Color layer
466 return true;
467 }
Ramkumar Radhakrishnan0cabf212014-09-08 20:07:49 -0700468 ALOGD_IF(isDebug(), "%s: layer handle is NULL", __FUNCTION__);
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800469 return false;
470 }
471
Naseer Ahmede850a802013-09-06 13:12:52 -0400472 //XXX: Investigate doing this with pixel phase on MDSS
Naseer Ahmede77f8082013-10-10 13:42:48 -0400473 if(!isSecureBuffer(hnd) && isNonIntegralSourceCrop(layer->sourceCropf))
Naseer Ahmede850a802013-09-06 13:12:52 -0400474 return false;
475
Saurabh Shah62e1d732013-09-17 10:44:05 -0700476 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
Saurabh Shah4fdde762013-04-30 18:47:33 -0700477 hwc_rect_t dst = layer->displayFrame;
Saurabh Shahb6810df2014-06-17 16:00:22 -0700478 bool rotated90 = (bool)(layer->transform & HAL_TRANSFORM_ROT_90);
Saurabh Shahe28a4022014-06-13 11:41:13 -0700479 int crop_w = rotated90 ? crop.bottom - crop.top : crop.right - crop.left;
480 int crop_h = rotated90 ? crop.right - crop.left : crop.bottom - crop.top;
Saurabh Shah4fdde762013-04-30 18:47:33 -0700481 int dst_w = dst.right - dst.left;
482 int dst_h = dst.bottom - dst.top;
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800483 float w_scale = ((float)crop_w / (float)dst_w);
484 float h_scale = ((float)crop_h / (float)dst_h);
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530485 MDPVersion& mdpHw = MDPVersion::getInstance();
Saurabh Shah4fdde762013-04-30 18:47:33 -0700486
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800487 /* Workaround for MDP HW limitation in DSI command mode panels where
488 * FPS will not go beyond 30 if buffers on RGB pipes are of width or height
489 * less than 5 pixels
Sravan Kumar D.V.Nad5d9292013-04-24 14:23:04 +0530490 * There also is a HW limilation in MDP, minimum block size is 2x2
491 * Fallback to GPU if height is less than 2.
492 */
Saurabh Shah189f23d2014-09-26 17:21:00 -0700493 if(mdpHw.hasMinCropWidthLimitation() and (crop_w < 5 or crop_h < 5))
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800494 return false;
495
Ramkumar Radhakrishnan1a763e92015-03-19 16:46:46 -0700496 /* crop_w and crop_h should be even for yuv layer, so fallback to GPU for
497 * those cases
498 */
499 if(isYuvBuffer(hnd) && (crop_w < 2 || crop_h < 2)) {
500 return false;
501 }
502
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800503 if((w_scale > 1.0f) || (h_scale > 1.0f)) {
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530504 const uint32_t maxMDPDownscale = mdpHw.getMaxMDPDownscale();
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800505 const float w_dscale = w_scale;
506 const float h_dscale = h_scale;
507
Jeykumar Sankaran1706a772013-11-27 12:55:19 -0800508 if(ctx->mMDP.version >= qdutils::MDSS_V5) {
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700509
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530510 if(!mdpHw.supportsDecimation()) {
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700511 /* On targets that doesnt support Decimation (eg.,8x26)
512 * maximum downscale support is overlay pipe downscale.
513 */
Jeykumar Sankaran39305802014-12-12 17:55:57 -0800514 if(crop_w > (int) mdpHw.getMaxPipeWidth() ||
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530515 w_dscale > maxMDPDownscale ||
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700516 h_dscale > maxMDPDownscale)
Jeykumar Sankaran1706a772013-11-27 12:55:19 -0800517 return false;
518 } else {
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700519 // Decimation on macrotile format layers is not supported.
520 if(isTileRendered(hnd)) {
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530521 /* Bail out if
522 * 1. Src crop > Mixer limit on nonsplit MDPComp
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700523 * 2. exceeds maximum downscale limit
524 */
Jeykumar Sankaran39305802014-12-12 17:55:57 -0800525 if(((crop_w > (int) mdpHw.getMaxPipeWidth()) &&
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530526 !sSrcSplitEnabled) ||
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700527 w_dscale > maxMDPDownscale ||
528 h_dscale > maxMDPDownscale) {
529 return false;
530 }
531 } else if(w_dscale > 64 || h_dscale > 64)
Jeykumar Sankaran1706a772013-11-27 12:55:19 -0800532 return false;
533 }
534 } else { //A-family
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700535 if(w_dscale > maxMDPDownscale || h_dscale > maxMDPDownscale)
Saurabh Shah4fdde762013-04-30 18:47:33 -0700536 return false;
537 }
Saurabh Shah4fdde762013-04-30 18:47:33 -0700538 }
539
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800540 if((w_scale < 1.0f) || (h_scale < 1.0f)) {
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530541 const uint32_t upscale = mdpHw.getMaxMDPUpscale();
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800542 const float w_uscale = 1.0f / w_scale;
543 const float h_uscale = 1.0f / h_scale;
544
545 if(w_uscale > upscale || h_uscale > upscale)
546 return false;
547 }
548
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800549 return true;
550}
551
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800552bool MDPComp::isFrameDoable(hwc_context_t *ctx) {
Saurabh Shahaa236822013-04-24 18:07:26 -0700553 bool ret = true;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800554
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800555 if(!isEnabled()) {
556 ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
Saurabh Shahaa236822013-04-24 18:07:26 -0700557 ret = false;
Raj Kamal83605462015-05-27 11:30:16 +0530558 } else if (ctx->isDMAStateChanging) {
559 // Bail out if a padding round has been invoked in order to switch DMA
560 // state to block mode. We need this to cater for the case when a layer
561 // requires rotation in the current frame.
562 ALOGD_IF(isDebug(), "%s: padding round invoked to switch DMA state",
563 __FUNCTION__);
564 ret = false;
Saurabh Shah19740d02015-04-10 10:05:42 -0700565 } else if(ctx->mVideoTransFlag && isSecondaryConnected(ctx)) {
Saurabh Shahd4e65852013-06-17 11:33:53 -0700566 //1 Padding round to shift pipes across mixers
567 ALOGD_IF(isDebug(),"%s: MDP Comp. video transition padding round",
568 __FUNCTION__);
569 ret = false;
Raj Kamalc0d34242015-03-17 20:53:14 +0530570 } else if((qdutils::MDPVersion::getInstance().is8x26() ||
571 qdutils::MDPVersion::getInstance().is8x16() ||
Prabhanjan Kandulafc541b32015-03-30 20:56:16 +0530572 qdutils::MDPVersion::getInstance().is8x39() ||
573 qdutils::MDPVersion::getInstance().is8x52()) &&
Raj Kamalc0d34242015-03-17 20:53:14 +0530574 !mDpy && isSecondaryAnimating(ctx) &&
575 isYuvPresent(ctx,HWC_DISPLAY_VIRTUAL)) {
576 ALOGD_IF(isDebug(),"%s: Display animation in progress",
577 __FUNCTION__);
578 ret = false;
Ramkumar Radhakrishnanf26fe9e2014-09-09 13:47:54 -0700579 } else if(qdutils::MDPVersion::getInstance().getTotalPipes() < 8) {
580 /* TODO: freeing up all the resources only for the targets having total
581 number of pipes < 8. Need to analyze number of VIG pipes used
582 for primary in previous draw cycle and accordingly decide
583 whether to fall back to full GPU comp or video only comp
584 */
585 if(isSecondaryConfiguring(ctx)) {
586 ALOGD_IF( isDebug(),"%s: External Display connection is pending",
587 __FUNCTION__);
588 ret = false;
589 } else if(ctx->isPaddingRound) {
590 ALOGD_IF(isDebug(), "%s: padding round invoked for dpy %d",
591 __FUNCTION__,mDpy);
592 ret = false;
593 }
Saurabh Shah0ceeb6a2013-04-23 10:46:07 -0700594 }
Tatenda Chipeperekwadc8d7082014-11-04 16:41:50 -0800595
Saurabh Shahaa236822013-04-24 18:07:26 -0700596 return ret;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800597}
598
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800599void MDPCompNonSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect &crop,
600 hwc_rect &dst) {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800601 hwc_rect_t roi = ctx->listStats[mDpy].lRoi;
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800602 dst = getIntersection(dst, roi);
603 crop = dst;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800604}
605
606/* 1) Identify layers that are not visible or lying outside the updating ROI and
607 * drop them from composition.
608 * 2) If we have a scaling layer which needs cropping against generated
609 * ROI, reset ROI to full resolution. */
610bool MDPCompNonSplit::validateAndApplyROI(hwc_context_t *ctx,
611 hwc_display_contents_1_t* list) {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700612 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800613 hwc_rect_t visibleRect = ctx->listStats[mDpy].lRoi;
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800614
615 for(int i = numAppLayers - 1; i >= 0; i--){
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800616 if(!isValidRect(visibleRect)) {
617 mCurrentFrame.drop[i] = true;
618 mCurrentFrame.dropCount++;
Jeykumar Sankaran0b961452014-01-21 17:26:12 -0800619 continue;
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800620 }
621
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700622 const hwc_layer_1_t* layer = &list->hwLayers[i];
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700623 hwc_rect_t dstRect = layer->displayFrame;
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800624 hwc_rect_t res = getIntersection(visibleRect, dstRect);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700625
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700626 if(!isValidRect(res)) {
627 mCurrentFrame.drop[i] = true;
628 mCurrentFrame.dropCount++;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800629 } else {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700630 /* Reset frame ROI when any layer which needs scaling also needs ROI
631 * cropping */
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800632 if(!isSameRect(res, dstRect) && needsScaling (layer)) {
Arpita Banerjeed8965982013-11-08 17:27:33 -0800633 ALOGI("%s: Resetting ROI due to scaling", __FUNCTION__);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700634 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
635 mCurrentFrame.dropCount = 0;
636 return false;
637 }
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800638
Jeykumar Sankaran0b961452014-01-21 17:26:12 -0800639 /* deduct any opaque region from visibleRect */
radhakrishna4efbdd62014-11-03 13:19:27 +0530640 if (layer->blending == HWC_BLENDING_NONE &&
641 layer->planeAlpha == 0xFF)
Jeykumar Sankaran0b961452014-01-21 17:26:12 -0800642 visibleRect = deductRect(visibleRect, res);
643 }
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700644 }
645 return true;
646}
647
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800648/* Calculate ROI for the frame by accounting all the layer's dispalyFrame which
649 * are updating. If DirtyRegion is applicable, calculate it by accounting all
650 * the changing layer's dirtyRegion. */
651void MDPCompNonSplit::generateROI(hwc_context_t *ctx,
652 hwc_display_contents_1_t* list) {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700653 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800654 if(!canPartialUpdate(ctx, list))
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700655 return;
656
657 struct hwc_rect roi = (struct hwc_rect){0, 0, 0, 0};
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800658 hwc_rect fullFrame = (struct hwc_rect) {0, 0,(int)ctx->dpyAttr[mDpy].xres,
659 (int)ctx->dpyAttr[mDpy].yres};
660
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700661 for(int index = 0; index < numAppLayers; index++ ) {
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800662 hwc_layer_1_t* layer = &list->hwLayers[index];
663 if ((mCachedFrame.hnd[index] != layer->handle) ||
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800664 isYuvBuffer((private_handle_t *)layer->handle)) {
Jeykumar Sankaran455678c2014-05-30 10:22:38 -0700665 hwc_rect_t dst = layer->displayFrame;
666 hwc_rect_t updatingRect = dst;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800667
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800668#ifdef QCOM_BSP
Dileep Kumar Reddi7399d5c2014-12-31 18:01:19 +0530669 if(!needsScaling(layer) && !layer->transform &&
670 (!isYuvBuffer((private_handle_t *)layer->handle)))
Jeykumar Sankaran455678c2014-05-30 10:22:38 -0700671 {
672 hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
673 int x_off = dst.left - src.left;
674 int y_off = dst.top - src.top;
675 updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
676 }
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800677#endif
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800678
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800679 roi = getUnion(roi, updatingRect);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700680 }
681 }
682
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800683 /* No layer is updating. Still SF wants a refresh.*/
684 if(!isValidRect(roi))
685 return;
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800686
687 // Align ROI coordinates to panel restrictions
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800688 roi = getSanitizeROI(roi, fullFrame);
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800689
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800690 ctx->listStats[mDpy].lRoi = roi;
691 if(!validateAndApplyROI(ctx, list))
692 resetROI(ctx, mDpy);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700693
694 ALOGD_IF(isDebug(),"%s: generated ROI: [%d, %d, %d, %d]", __FUNCTION__,
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800695 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
696 ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom);
697}
698
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800699void MDPCompSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect &crop,
700 hwc_rect &dst) {
701 hwc_rect roi = getUnion(ctx->listStats[mDpy].lRoi,
702 ctx->listStats[mDpy].rRoi);
703 hwc_rect tmpDst = getIntersection(dst, roi);
704 if(!isSameRect(dst, tmpDst)) {
705 crop.left = crop.left + (tmpDst.left - dst.left);
706 crop.top = crop.top + (tmpDst.top - dst.top);
707 crop.right = crop.left + (tmpDst.right - tmpDst.left);
708 crop.bottom = crop.top + (tmpDst.bottom - tmpDst.top);
709 dst = tmpDst;
710 }
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800711}
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800712
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800713/* 1) Identify layers that are not visible or lying outside BOTH the updating
714 * ROI's and drop them from composition. If a layer is spanning across both
715 * the halves of the screen but needed by only ROI, the non-contributing
716 * half will not be programmed for MDP.
717 * 2) If we have a scaling layer which needs cropping against generated
718 * ROI, reset ROI to full resolution. */
719bool MDPCompSplit::validateAndApplyROI(hwc_context_t *ctx,
720 hwc_display_contents_1_t* list) {
721
722 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
723
724 hwc_rect_t visibleRectL = ctx->listStats[mDpy].lRoi;
725 hwc_rect_t visibleRectR = ctx->listStats[mDpy].rRoi;
726
727 for(int i = numAppLayers - 1; i >= 0; i--){
728 if(!isValidRect(visibleRectL) && !isValidRect(visibleRectR))
729 {
730 mCurrentFrame.drop[i] = true;
731 mCurrentFrame.dropCount++;
732 continue;
733 }
734
735 const hwc_layer_1_t* layer = &list->hwLayers[i];
736 hwc_rect_t dstRect = layer->displayFrame;
737
738 hwc_rect_t l_res = getIntersection(visibleRectL, dstRect);
739 hwc_rect_t r_res = getIntersection(visibleRectR, dstRect);
740 hwc_rect_t res = getUnion(l_res, r_res);
741
742 if(!isValidRect(l_res) && !isValidRect(r_res)) {
743 mCurrentFrame.drop[i] = true;
744 mCurrentFrame.dropCount++;
745 } else {
746 /* Reset frame ROI when any layer which needs scaling also needs ROI
747 * cropping */
748 if(!isSameRect(res, dstRect) && needsScaling (layer)) {
749 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
750 mCurrentFrame.dropCount = 0;
751 return false;
752 }
753
radhakrishna4efbdd62014-11-03 13:19:27 +0530754 if (layer->blending == HWC_BLENDING_NONE &&
755 layer->planeAlpha == 0xFF) {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800756 visibleRectL = deductRect(visibleRectL, l_res);
757 visibleRectR = deductRect(visibleRectR, r_res);
758 }
759 }
760 }
761 return true;
762}
763/* Calculate ROI for the frame by accounting all the layer's dispalyFrame which
764 * are updating. If DirtyRegion is applicable, calculate it by accounting all
765 * the changing layer's dirtyRegion. */
766void MDPCompSplit::generateROI(hwc_context_t *ctx,
767 hwc_display_contents_1_t* list) {
768 if(!canPartialUpdate(ctx, list))
769 return;
770
771 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
772 int lSplit = getLeftSplit(ctx, mDpy);
773
774 int hw_h = (int)ctx->dpyAttr[mDpy].yres;
775 int hw_w = (int)ctx->dpyAttr[mDpy].xres;
776
777 struct hwc_rect l_frame = (struct hwc_rect){0, 0, lSplit, hw_h};
778 struct hwc_rect r_frame = (struct hwc_rect){lSplit, 0, hw_w, hw_h};
779
780 struct hwc_rect l_roi = (struct hwc_rect){0, 0, 0, 0};
781 struct hwc_rect r_roi = (struct hwc_rect){0, 0, 0, 0};
782
783 for(int index = 0; index < numAppLayers; index++ ) {
784 hwc_layer_1_t* layer = &list->hwLayers[index];
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800785 private_handle_t *hnd = (private_handle_t *)layer->handle;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800786 if ((mCachedFrame.hnd[index] != layer->handle) ||
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800787 isYuvBuffer(hnd)) {
Jeykumar Sankaran71e597c2014-05-07 16:23:14 -0700788 hwc_rect_t dst = layer->displayFrame;
789 hwc_rect_t updatingRect = dst;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800790
791#ifdef QCOM_BSP
792 if(!needsScaling(layer) && !layer->transform)
Jeykumar Sankaran71e597c2014-05-07 16:23:14 -0700793 {
794 hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
795 int x_off = dst.left - src.left;
796 int y_off = dst.top - src.top;
797 updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
798 }
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800799#endif
800
801 hwc_rect_t l_dst = getIntersection(l_frame, updatingRect);
802 if(isValidRect(l_dst))
803 l_roi = getUnion(l_roi, l_dst);
804
805 hwc_rect_t r_dst = getIntersection(r_frame, updatingRect);
806 if(isValidRect(r_dst))
807 r_roi = getUnion(r_roi, r_dst);
808 }
809 }
810
Jeykumar Sankarana40a9342014-04-25 09:37:10 -0700811 /* For panels that cannot accept commands in both the interfaces, we cannot
812 * send two ROI's (for each half). We merge them into single ROI and split
813 * them across lSplit for MDP mixer use. The ROI's will be merged again
814 * finally before udpating the panel in the driver. */
815 if(qdutils::MDPVersion::getInstance().needsROIMerge()) {
816 hwc_rect_t temp_roi = getUnion(l_roi, r_roi);
817 l_roi = getIntersection(temp_roi, l_frame);
818 r_roi = getIntersection(temp_roi, r_frame);
819 }
820
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800821 /* No layer is updating. Still SF wants a refresh. */
822 if(!isValidRect(l_roi) && !isValidRect(r_roi))
823 return;
824
825 l_roi = getSanitizeROI(l_roi, l_frame);
826 r_roi = getSanitizeROI(r_roi, r_frame);
827
828 ctx->listStats[mDpy].lRoi = l_roi;
829 ctx->listStats[mDpy].rRoi = r_roi;
830
831 if(!validateAndApplyROI(ctx, list))
832 resetROI(ctx, mDpy);
833
834 ALOGD_IF(isDebug(),"%s: generated L_ROI: [%d, %d, %d, %d]"
835 "R_ROI: [%d, %d, %d, %d]", __FUNCTION__,
836 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
837 ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom,
838 ctx->listStats[mDpy].rRoi.left, ctx->listStats[mDpy].rRoi.top,
839 ctx->listStats[mDpy].rRoi.right, ctx->listStats[mDpy].rRoi.bottom);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700840}
841
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800842/* Checks for conditions where all the layers marked for MDP comp cannot be
843 * bypassed. On such conditions we try to bypass atleast YUV layers */
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800844bool MDPComp::tryFullFrame(hwc_context_t *ctx,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800845 hwc_display_contents_1_t* list){
846
Saurabh Shahaa236822013-04-24 18:07:26 -0700847 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800848
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -0700849 // Fall back to video only composition, if AIV video mode is enabled
850 if(ctx->listStats[mDpy].mAIVVideoMode) {
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -0700851 ALOGD_IF(isDebug(), "%s: AIV Video Mode enabled dpy %d",
852 __FUNCTION__, mDpy);
853 return false;
854 }
855
Praveena Pachipulusu47346c22014-12-04 11:06:41 +0530856 /* No Idle fall back if secure display or secure RGB layers are present
857 * or if there is only a single layer being composed */
858 if(sIdleFallBack && !ctx->listStats[mDpy].secureUI &&
859 !ctx->listStats[mDpy].secureRGBCount &&
860 (ctx->listStats[mDpy].numAppLayers > 1)) {
Saurabh Shah2d998a92013-05-14 17:55:58 -0700861 ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
862 return false;
863 }
864
Raj Kamalc0d34242015-03-17 20:53:14 +0530865 if(!mDpy && isSecondaryAnimating(ctx) &&
866 (isYuvPresent(ctx,HWC_DISPLAY_EXTERNAL) ||
867 isYuvPresent(ctx,HWC_DISPLAY_VIRTUAL)) ) {
868 ALOGD_IF(isDebug(),"%s: Display animation in progress",
869 __FUNCTION__);
870 return false;
871 }
872
Ramkumar Radhakrishnanf26fe9e2014-09-09 13:47:54 -0700873 // if secondary is configuring or Padding round, fall back to video only
874 // composition and release all assigned non VIG pipes from primary.
875 if(isSecondaryConfiguring(ctx)) {
876 ALOGD_IF( isDebug(),"%s: External Display connection is pending",
877 __FUNCTION__);
878 return false;
879 } else if(ctx->isPaddingRound) {
880 ALOGD_IF(isDebug(), "%s: padding round invoked for dpy %d",
881 __FUNCTION__,mDpy);
882 return false;
883 }
884
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -0500885 // No MDP composition for 3D
886 if(needs3DComposition(ctx, mDpy))
887 return false;
888
Tatenda Chipeperekwacb2a2432014-08-06 17:45:58 -0700889 // check for action safe flag and MDP scaling mode which requires scaling.
Ramkumar Radhakrishnan4af1ef02013-12-12 11:53:08 -0800890 if(ctx->dpyAttr[mDpy].mActionSafePresent
Tatenda Chipeperekwacb2a2432014-08-06 17:45:58 -0700891 || ctx->dpyAttr[mDpy].mMDPScalingMode) {
Ramkumar Radhakrishnan4af1ef02013-12-12 11:53:08 -0800892 ALOGD_IF(isDebug(), "%s: Scaling needed for this frame",__FUNCTION__);
893 return false;
894 }
895
Saurabh Shahd1d93a22015-04-02 15:25:16 -0700896 uint32_t totalDirtyArea = 0;
897 bool computeDirtyArea = not (list->flags & HWC_GEOMETRY_CHANGED) and
898 not isYuvPresent(ctx, mDpy) and
899 not qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() and
900 numAppLayers > 1;
901
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800902 for(int i = 0; i < numAppLayers; ++i) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800903 hwc_layer_1_t* layer = &list->hwLayers[i];
904 private_handle_t *hnd = (private_handle_t *)layer->handle;
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -0800905
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800906 if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700907 if(!canUseRotator(ctx, mDpy)) {
908 ALOGD_IF(isDebug(), "%s: Can't use rotator for dpy %d",
909 __FUNCTION__, mDpy);
Amara Venkata Mastan Manoj Kumar9d373c02013-08-20 14:30:09 -0700910 return false;
911 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800912 }
Prabhanjan Kandula9fb032a2013-06-18 17:37:22 +0530913
914 //For 8x26 with panel width>1k, if RGB layer needs HFLIP fail mdp comp
915 // may not need it if Gfx pre-rotation can handle all flips & rotations
Saurabh Shahcad57772014-12-01 14:19:51 -0800916 MDPVersion& mdpHw = MDPVersion::getInstance();
Sushil Chauhanfda00fc2014-03-20 11:08:41 -0700917 int transform = (layer->flags & HWC_COLOR_FILL) ? 0 : layer->transform;
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530918 if( mdpHw.is8x26() && (ctx->dpyAttr[mDpy].xres > 1024) &&
919 (transform & HWC_TRANSFORM_FLIP_H) && (!isYuvBuffer(hnd)))
920 return false;
Saurabh Shahd1d93a22015-04-02 15:25:16 -0700921
922#ifdef QCOM_BSP
923 if(computeDirtyArea and mCachedFrame.hnd[i] != hnd) {
924 if(needsScaling(layer)) {
925 totalDirtyArea = 0;
926 computeDirtyArea = false;
927 } else {
928 hwc_rect_t dirtyRect = layer->dirtyRect;
929 ALOGD_IF(isDebug(),
930 "Updating layer: %d Dirty rect: %d, %d, %d, %d",
931 i, dirtyRect.left, dirtyRect.top, dirtyRect.right,
932 dirtyRect.bottom);
933 totalDirtyArea += (dirtyRect.right - dirtyRect.left)
934 * (dirtyRect.bottom - dirtyRect.top);
935 }
936 }
937#endif
938 }
939
940 if(totalDirtyArea) {
941 const uint32_t fbArea = ctx->dpyAttr[mDpy].xres *
942 ctx->dpyAttr[mDpy].yres;
943 if(totalDirtyArea < (fbArea / 20)) {
944 ALOGD_IF(isDebug(), "%s: Small update, bailing out. Dirty area %u",
945 __FUNCTION__, totalDirtyArea);
946 return false;
947 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800948 }
Saurabh Shahaa236822013-04-24 18:07:26 -0700949
Saurabh Shaha9da08f2013-07-03 13:27:53 -0700950 if(ctx->mAD->isDoable()) {
951 return false;
952 }
953
Saurabh Shahaa236822013-04-24 18:07:26 -0700954 //If all above hard conditions are met we can do full or partial MDP comp.
955 bool ret = false;
956 if(fullMDPComp(ctx, list)) {
957 ret = true;
Sushil Chauhandefd3522014-05-13 18:17:12 -0700958 } else if(fullMDPCompWithPTOR(ctx, list)) {
959 ret = true;
Jeykumar Sankaran24c199d2013-05-24 09:40:36 -0700960 } else if(partialMDPComp(ctx, list)) {
Saurabh Shahaa236822013-04-24 18:07:26 -0700961 ret = true;
962 }
Prabhanjan Kandula21918db2013-11-26 15:51:58 +0530963
Saurabh Shahaa236822013-04-24 18:07:26 -0700964 return ret;
965}
966
967bool MDPComp::fullMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -0700968
969 if(sSimulationFlags & MDPCOMP_AVOID_FULL_MDP)
970 return false;
971
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700972 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
973 for(int i = 0; i < numAppLayers; i++) {
974 hwc_layer_1_t* layer = &list->hwLayers[i];
Jeykumar Sankaran880da832014-04-18 10:22:35 -0700975 if(not mCurrentFrame.drop[i] and
976 not isSupportedForMDPComp(ctx, layer)) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700977 ALOGD_IF(isDebug(), "%s: Unsupported layer in list",__FUNCTION__);
978 return false;
979 }
980 }
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800981
Raj Kamalb5f0b4a2015-04-08 15:10:37 +0530982 if(!mDpy && isSecondaryConnected(ctx) &&
983 (qdutils::MDPVersion::getInstance().is8x16() ||
984 qdutils::MDPVersion::getInstance().is8x26() ||
985 qdutils::MDPVersion::getInstance().is8x39()) &&
986 isYuvPresent(ctx, HWC_DISPLAY_VIRTUAL)) {
987 ALOGD_IF(isDebug(), "%s: YUV layer present on secondary", __FUNCTION__);
988 return false;
989 }
990
Saurabh Shahaa236822013-04-24 18:07:26 -0700991 mCurrentFrame.fbCount = 0;
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700992 memcpy(&mCurrentFrame.isFBComposed, &mCurrentFrame.drop,
993 sizeof(mCurrentFrame.isFBComposed));
994 mCurrentFrame.mdpCount = mCurrentFrame.layerCount - mCurrentFrame.fbCount -
995 mCurrentFrame.dropCount;
Saurabh Shahaa236822013-04-24 18:07:26 -0700996
Raj Kamal389d6e32014-08-04 14:43:24 +0530997 if(sEnableYUVsplit){
Saurabh Shah3d4b8042013-12-10 15:19:17 -0800998 adjustForSourceSplit(ctx, list);
radhakrishnac9a67412013-09-25 17:40:42 +0530999 }
1000
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001001 if(!postHeuristicsHandling(ctx, list)) {
1002 ALOGD_IF(isDebug(), "post heuristic handling failed");
1003 reset(ctx);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07001004 return false;
1005 }
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001006 ALOGD_IF(sSimulationFlags,"%s: FULL_MDP_COMP SUCCEEDED",
1007 __FUNCTION__);
Saurabh Shahaa236822013-04-24 18:07:26 -07001008 return true;
1009}
1010
Sushil Chauhandefd3522014-05-13 18:17:12 -07001011/* Full MDP Composition with Peripheral Tiny Overlap Removal.
1012 * MDP bandwidth limitations can be avoided, if the overlap region
1013 * covered by the smallest layer at a higher z-order, gets composed
1014 * by Copybit on a render buffer, which can be queued to MDP.
1015 */
1016bool MDPComp::fullMDPCompWithPTOR(hwc_context_t *ctx,
1017 hwc_display_contents_1_t* list) {
1018
1019 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001020 // PTOR does not qualify when there are layers dropped, but if
1021 // dropped layer is only a cursor, PTOR could qualify
1022 const int numNonCursorLayers = numAppLayers - mCurrentFrame.dropCount;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001023 const int stagesForMDP = min(sMaxPipesPerMixer,
1024 ctx->mOverlay->availablePipes(mDpy, Overlay::MIXER_DEFAULT));
1025
1026 // Hard checks where we cannot use this mode
Sushil Chauhanbfc2de02014-07-24 11:52:58 -07001027 if (mDpy || !ctx->mCopyBit[mDpy]) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001028 ALOGD_IF(isDebug(), "%s: Feature not supported!", __FUNCTION__);
1029 return false;
1030 }
1031
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001032 // Frame level checks - consider PTOR in case of dropCount only if the cursor
1033 // layer is dropped, otherwise bail out of PTOR
Sushil Chauhandefd3522014-05-13 18:17:12 -07001034 if ((numAppLayers > stagesForMDP) || isSkipPresent(ctx, mDpy) ||
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001035 isYuvPresent(ctx, mDpy) || isSecurePresent(ctx, mDpy) ||
1036 (mCurrentFrame.dropCount - (int)isCursorPresent(ctx, mDpy))) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001037 ALOGD_IF(isDebug(), "%s: Frame not supported!", __FUNCTION__);
1038 return false;
1039 }
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001040 // MDP comp checks
1041 for(int i = 0; i < numAppLayers; i++) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001042 hwc_layer_1_t* layer = &list->hwLayers[i];
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001043 if(not isSupportedForMDPComp(ctx, layer)) {
1044 ALOGD_IF(isDebug(), "%s: Unsupported layer in list",__FUNCTION__);
1045 return false;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001046 }
1047 }
1048
Raj Kamalb5f0b4a2015-04-08 15:10:37 +05301049 if(!mDpy && isSecondaryConnected(ctx) &&
1050 (qdutils::MDPVersion::getInstance().is8x16() ||
1051 qdutils::MDPVersion::getInstance().is8x26() ||
1052 qdutils::MDPVersion::getInstance().is8x39()) &&
1053 isYuvPresent(ctx, HWC_DISPLAY_VIRTUAL)) {
1054 ALOGD_IF(isDebug(), "%s: YUV layer present on secondary", __FUNCTION__);
1055 return false;
1056 }
1057
Sushil Chauhandefd3522014-05-13 18:17:12 -07001058 /* We cannot use this composition mode, if:
1059 1. A below layer needs scaling.
1060 2. Overlap is not peripheral to display.
1061 3. Overlap or a below layer has 90 degree transform.
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001062 4. Overlap area > (1/3 * FrameBuffer) area, based on Perf inputs.
Sushil Chauhandefd3522014-05-13 18:17:12 -07001063 */
1064
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001065 int minLayerIndex[MAX_PTOR_LAYERS] = { -1, -1};
1066 hwc_rect_t overlapRect[MAX_PTOR_LAYERS];
1067 memset(overlapRect, 0, sizeof(overlapRect));
1068 int layerPixelCount, minPixelCount = 0;
1069 int numPTORLayersFound = 0;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001070 for (int i = numNonCursorLayers - 1; (i >= 0 &&
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001071 numPTORLayersFound < MAX_PTOR_LAYERS); i--) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001072 hwc_layer_1_t* layer = &list->hwLayers[i];
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001073 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
Sushil Chauhandefd3522014-05-13 18:17:12 -07001074 hwc_rect_t dispFrame = layer->displayFrame;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001075 layerPixelCount = (crop.right - crop.left) * (crop.bottom - crop.top);
1076 // PTOR layer should be peripheral and cannot have transform
1077 if (!isPeripheral(dispFrame, ctx->mViewFrame[mDpy]) ||
1078 has90Transform(layer)) {
1079 continue;
1080 }
1081 if((3 * (layerPixelCount + minPixelCount)) >
1082 ((int)ctx->dpyAttr[mDpy].xres * (int)ctx->dpyAttr[mDpy].yres)) {
1083 // Overlap area > (1/3 * FrameBuffer) area, based on Perf inputs.
1084 continue;
1085 }
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001086 bool found = false;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001087 for (int j = i-1; j >= 0; j--) {
1088 // Check if the layers below this layer qualifies for PTOR comp
1089 hwc_layer_1_t* layer = &list->hwLayers[j];
1090 hwc_rect_t disFrame = layer->displayFrame;
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001091 // Layer below PTOR is intersecting and has 90 degree transform or
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001092 // needs scaling cannot be supported.
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001093 if (isValidRect(getIntersection(dispFrame, disFrame))) {
1094 if (has90Transform(layer) || needsScaling(layer)) {
1095 found = false;
1096 break;
1097 }
1098 found = true;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001099 }
1100 }
1101 // Store the minLayer Index
1102 if(found) {
1103 minLayerIndex[numPTORLayersFound] = i;
1104 overlapRect[numPTORLayersFound] = list->hwLayers[i].displayFrame;
1105 minPixelCount += layerPixelCount;
1106 numPTORLayersFound++;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001107 }
1108 }
1109
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001110 // No overlap layers
1111 if (!numPTORLayersFound)
1112 return false;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001113
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001114 // Store the displayFrame and the sourceCrops of the layers
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001115 hwc_rect_t displayFrame[numNonCursorLayers];
1116 hwc_rect_t sourceCrop[numNonCursorLayers];
1117 for(int i = 0; i < numNonCursorLayers; i++) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001118 hwc_layer_1_t* layer = &list->hwLayers[i];
1119 displayFrame[i] = layer->displayFrame;
1120 sourceCrop[i] = integerizeSourceCrop(layer->sourceCropf);
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001121 }
Sushil Chauhandefd3522014-05-13 18:17:12 -07001122
Prabhanjan Kandula9889a202014-09-04 21:50:35 +05301123 /**
1124 * It's possible that 2 PTOR layers might have overlapping.
1125 * In such case, remove the intersection(again if peripheral)
1126 * from the lower PTOR layer to avoid overlapping.
1127 * If intersection is not on peripheral then compromise
1128 * by reducing number of PTOR layers.
1129 **/
1130 hwc_rect_t commonRect = getIntersection(overlapRect[0], overlapRect[1]);
1131 if(isValidRect(commonRect)) {
1132 overlapRect[1] = deductRect(overlapRect[1], commonRect);
1133 list->hwLayers[minLayerIndex[1]].displayFrame = overlapRect[1];
1134 }
1135
1136 ctx->mPtorInfo.count = numPTORLayersFound;
1137 for(int i = 0; i < MAX_PTOR_LAYERS; i++) {
1138 ctx->mPtorInfo.layerIndex[i] = minLayerIndex[i];
1139 }
1140
1141 if (!ctx->mCopyBit[mDpy]->prepareOverlap(ctx, list)) {
1142 // reset PTOR
1143 ctx->mPtorInfo.count = 0;
1144 if(isValidRect(commonRect)) {
1145 // If PTORs are intersecting restore displayframe of PTOR[1]
1146 // before returning, as we have modified it above.
1147 list->hwLayers[minLayerIndex[1]].displayFrame =
1148 displayFrame[minLayerIndex[1]];
1149 }
1150 return false;
1151 }
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001152 private_handle_t *renderBuf = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
1153 Whf layerWhf[numPTORLayersFound]; // To store w,h,f of PTOR layers
1154
Xu Yangcda012c2014-07-30 21:57:21 +08001155 // Store the blending mode, planeAlpha, and transform of PTOR layers
1156 int32_t blending[numPTORLayersFound];
1157 uint8_t planeAlpha[numPTORLayersFound];
1158 uint32_t transform[numPTORLayersFound];
1159
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001160 for(int j = 0; j < numPTORLayersFound; j++) {
1161 int index = ctx->mPtorInfo.layerIndex[j];
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001162
1163 // Update src crop of PTOR layer
1164 hwc_layer_1_t* layer = &list->hwLayers[index];
1165 layer->sourceCropf.left = (float)ctx->mPtorInfo.displayFrame[j].left;
1166 layer->sourceCropf.top = (float)ctx->mPtorInfo.displayFrame[j].top;
1167 layer->sourceCropf.right = (float)ctx->mPtorInfo.displayFrame[j].right;
1168 layer->sourceCropf.bottom =(float)ctx->mPtorInfo.displayFrame[j].bottom;
1169
1170 // Store & update w, h, format of PTOR layer
1171 private_handle_t *hnd = (private_handle_t *)layer->handle;
1172 Whf whf(hnd->width, hnd->height, hnd->format, hnd->size);
1173 layerWhf[j] = whf;
1174 hnd->width = renderBuf->width;
1175 hnd->height = renderBuf->height;
1176 hnd->format = renderBuf->format;
1177
Xu Yangcda012c2014-07-30 21:57:21 +08001178 // Store & update blending mode, planeAlpha and transform of PTOR layer
1179 blending[j] = layer->blending;
1180 planeAlpha[j] = layer->planeAlpha;
1181 transform[j] = layer->transform;
1182 layer->blending = HWC_BLENDING_NONE;
1183 layer->planeAlpha = 0xFF;
1184 layer->transform = 0;
1185
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001186 // Remove overlap from crop & displayFrame of below layers
1187 for (int i = 0; i < index && index !=-1; i++) {
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001188 layer = &list->hwLayers[i];
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001189 if(!isValidRect(getIntersection(layer->displayFrame,
1190 overlapRect[j]))) {
1191 continue;
1192 }
1193 // Update layer attributes
1194 hwc_rect_t srcCrop = integerizeSourceCrop(layer->sourceCropf);
1195 hwc_rect_t destRect = deductRect(layer->displayFrame,
Dileep Kumar Reddi72058b82014-11-11 16:03:03 +05301196 getIntersection(layer->displayFrame, overlapRect[j]));
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001197 qhwc::calculate_crop_rects(srcCrop, layer->displayFrame, destRect,
1198 layer->transform);
1199 layer->sourceCropf.left = (float)srcCrop.left;
1200 layer->sourceCropf.top = (float)srcCrop.top;
1201 layer->sourceCropf.right = (float)srcCrop.right;
1202 layer->sourceCropf.bottom = (float)srcCrop.bottom;
1203 }
Sushil Chauhandefd3522014-05-13 18:17:12 -07001204 }
1205
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001206 mCurrentFrame.mdpCount = numNonCursorLayers;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001207 mCurrentFrame.fbCount = 0;
1208 mCurrentFrame.fbZ = -1;
1209
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001210 for (int j = 0; j < numNonCursorLayers; j++) {
Dileep Kumar Reddi72058b82014-11-11 16:03:03 +05301211 if(isValidRect(list->hwLayers[j].displayFrame)) {
1212 mCurrentFrame.isFBComposed[j] = false;
1213 } else {
1214 mCurrentFrame.mdpCount--;
1215 mCurrentFrame.drop[j] = true;
1216 }
1217 }
Sushil Chauhandefd3522014-05-13 18:17:12 -07001218
1219 bool result = postHeuristicsHandling(ctx, list);
1220
1221 // Restore layer attributes
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001222 for(int i = 0; i < numNonCursorLayers; i++) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001223 hwc_layer_1_t* layer = &list->hwLayers[i];
1224 layer->displayFrame = displayFrame[i];
1225 layer->sourceCropf.left = (float)sourceCrop[i].left;
1226 layer->sourceCropf.top = (float)sourceCrop[i].top;
1227 layer->sourceCropf.right = (float)sourceCrop[i].right;
1228 layer->sourceCropf.bottom = (float)sourceCrop[i].bottom;
1229 }
1230
Xu Yangcda012c2014-07-30 21:57:21 +08001231 // Restore w,h,f, blending attributes, and transform of PTOR layers
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001232 for (int i = 0; i < numPTORLayersFound; i++) {
1233 int idx = ctx->mPtorInfo.layerIndex[i];
Xu Yangcda012c2014-07-30 21:57:21 +08001234 hwc_layer_1_t* layer = &list->hwLayers[idx];
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001235 private_handle_t *hnd = (private_handle_t *)list->hwLayers[idx].handle;
1236 hnd->width = layerWhf[i].w;
1237 hnd->height = layerWhf[i].h;
1238 hnd->format = layerWhf[i].format;
Xu Yangcda012c2014-07-30 21:57:21 +08001239 layer->blending = blending[i];
1240 layer->planeAlpha = planeAlpha[i];
1241 layer->transform = transform[i];
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001242 }
1243
Sushil Chauhandefd3522014-05-13 18:17:12 -07001244 if (!result) {
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001245 // reset PTOR
1246 ctx->mPtorInfo.count = 0;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001247 reset(ctx);
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001248 } else {
1249 ALOGD_IF(isDebug(), "%s: PTOR Indexes: %d and %d", __FUNCTION__,
1250 ctx->mPtorInfo.layerIndex[0], ctx->mPtorInfo.layerIndex[1]);
Sushil Chauhandefd3522014-05-13 18:17:12 -07001251 }
1252
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001253 ALOGD_IF(isDebug(), "%s: Postheuristics %s!", __FUNCTION__,
1254 (result ? "successful" : "failed"));
Sushil Chauhandefd3522014-05-13 18:17:12 -07001255 return result;
1256}
1257
Saurabh Shahaa236822013-04-24 18:07:26 -07001258bool MDPComp::partialMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list)
1259{
radhakrishnac3198ff2015-03-10 17:10:02 +05301260 if(!sEnableMixedMode || !isAlphaPresentinFB(ctx, mDpy)) {
1261 //Mixed mode is disabled/can't be used. No need to even try caching.
Jeykumar Sankaran24c199d2013-05-24 09:40:36 -07001262 return false;
1263 }
1264
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001265 bool ret = false;
Raj Kamal1179d9c2014-10-28 15:31:35 +05301266 if(isSkipPresent(ctx, mDpy) or list->flags & HWC_GEOMETRY_CHANGED) {
1267 //Try load based first
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001268 ret = loadBasedComp(ctx, list) or
Saurabh Shahf2de00f2013-12-11 17:52:53 -08001269 cacheBasedComp(ctx, list);
1270 } else {
1271 ret = cacheBasedComp(ctx, list) or
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001272 loadBasedComp(ctx, list);
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001273 }
1274
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001275 return ret;
1276}
1277
1278bool MDPComp::cacheBasedComp(hwc_context_t *ctx,
1279 hwc_display_contents_1_t* list) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001280 if(sSimulationFlags & MDPCOMP_AVOID_CACHE_MDP)
1281 return false;
1282
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001283 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shahaa236822013-04-24 18:07:26 -07001284 mCurrentFrame.reset(numAppLayers);
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001285 updateLayerCache(ctx, list, mCurrentFrame);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001286
1287 //If an MDP marked layer is unsupported cannot do partial MDP Comp
1288 for(int i = 0; i < numAppLayers; i++) {
1289 if(!mCurrentFrame.isFBComposed[i]) {
1290 hwc_layer_1_t* layer = &list->hwLayers[i];
1291 if(not isSupportedForMDPComp(ctx, layer)) {
1292 ALOGD_IF(isDebug(), "%s: Unsupported layer in list",
1293 __FUNCTION__);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001294 reset(ctx);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001295 return false;
1296 }
1297 }
1298 }
1299
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001300 updateYUV(ctx, list, false /*secure only*/, mCurrentFrame);
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001301 /* mark secure RGB layers for MDP comp */
1302 updateSecureRGB(ctx, list);
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301303 bool ret = markLayersForCaching(ctx, list); //sets up fbZ also
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001304 if(!ret) {
1305 ALOGD_IF(isDebug(),"%s: batching failed, dpy %d",__FUNCTION__, mDpy);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001306 reset(ctx);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001307 return false;
1308 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001309
1310 int mdpCount = mCurrentFrame.mdpCount;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001311
Raj Kamal389d6e32014-08-04 14:43:24 +05301312 if(sEnableYUVsplit){
Saurabh Shah3d4b8042013-12-10 15:19:17 -08001313 adjustForSourceSplit(ctx, list);
radhakrishnac9a67412013-09-25 17:40:42 +05301314 }
1315
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001316 if(!postHeuristicsHandling(ctx, list)) {
1317 ALOGD_IF(isDebug(), "post heuristic handling failed");
1318 reset(ctx);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07001319 return false;
1320 }
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001321 ALOGD_IF(sSimulationFlags,"%s: CACHE_MDP_COMP SUCCEEDED",
1322 __FUNCTION__);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07001323
Saurabh Shahaa236822013-04-24 18:07:26 -07001324 return true;
1325}
1326
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001327bool MDPComp::loadBasedComp(hwc_context_t *ctx,
Saurabh Shahb772ae32013-11-18 15:40:02 -08001328 hwc_display_contents_1_t* list) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001329 if(sSimulationFlags & MDPCOMP_AVOID_LOAD_MDP)
1330 return false;
1331
Arun Kumar K.R2aa44c62014-01-21 23:08:28 -08001332 if(not isLoadBasedCompDoable(ctx)) {
Saurabh Shahf2de00f2013-12-11 17:52:53 -08001333 return false;
1334 }
1335
Saurabh Shahb772ae32013-11-18 15:40:02 -08001336 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001337 const int numNonDroppedLayers = numAppLayers - mCurrentFrame.dropCount;
1338 const int stagesForMDP = min(sMaxPipesPerMixer,
1339 ctx->mOverlay->availablePipes(mDpy, Overlay::MIXER_DEFAULT));
Saurabh Shahf2de00f2013-12-11 17:52:53 -08001340
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001341 int mdpBatchSize = stagesForMDP - 1; //1 stage for FB
1342 int fbBatchSize = numNonDroppedLayers - mdpBatchSize;
1343 int lastMDPSupportedIndex = numAppLayers;
1344 int dropCount = 0;
Saurabh Shahb772ae32013-11-18 15:40:02 -08001345
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001346 //Find the minimum MDP batch size
1347 for(int i = 0; i < numAppLayers;i++) {
1348 if(mCurrentFrame.drop[i]) {
1349 dropCount++;
Jeykumar Sankaran846e2792014-01-23 21:59:58 -08001350 continue;
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001351 }
1352 hwc_layer_1_t* layer = &list->hwLayers[i];
1353 if(not isSupportedForMDPComp(ctx, layer)) {
1354 lastMDPSupportedIndex = i;
1355 mdpBatchSize = min(i - dropCount, stagesForMDP - 1);
1356 fbBatchSize = numNonDroppedLayers - mdpBatchSize;
Jeykumar Sankaran846e2792014-01-23 21:59:58 -08001357 break;
Saurabh Shahb772ae32013-11-18 15:40:02 -08001358 }
Saurabh Shahb772ae32013-11-18 15:40:02 -08001359 }
1360
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001361 ALOGD_IF(isDebug(), "%s:Before optimizing fbBatch, mdpbatch %d, fbbatch %d "
1362 "dropped %d", __FUNCTION__, mdpBatchSize, fbBatchSize,
1363 mCurrentFrame.dropCount);
1364
1365 //Start at a point where the fb batch should at least have 2 layers, for
1366 //this mode to be justified.
1367 while(fbBatchSize < 2) {
1368 ++fbBatchSize;
1369 --mdpBatchSize;
Jeykumar Sankaran846e2792014-01-23 21:59:58 -08001370 }
Saurabh Shahb772ae32013-11-18 15:40:02 -08001371
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001372 //If there are no layers for MDP, this mode doesnt make sense.
1373 if(mdpBatchSize < 1) {
1374 ALOGD_IF(isDebug(), "%s: No MDP layers after optimizing for fbBatch",
1375 __FUNCTION__);
Saurabh Shahb772ae32013-11-18 15:40:02 -08001376 return false;
1377 }
1378
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001379 mCurrentFrame.reset(numAppLayers);
1380
1381 //Try with successively smaller mdp batch sizes until we succeed or reach 1
1382 while(mdpBatchSize > 0) {
1383 //Mark layers for MDP comp
1384 int mdpBatchLeft = mdpBatchSize;
1385 for(int i = 0; i < lastMDPSupportedIndex and mdpBatchLeft; i++) {
1386 if(mCurrentFrame.drop[i]) {
1387 continue;
1388 }
1389 mCurrentFrame.isFBComposed[i] = false;
1390 --mdpBatchLeft;
1391 }
1392
1393 mCurrentFrame.fbZ = mdpBatchSize;
1394 mCurrentFrame.fbCount = fbBatchSize;
1395 mCurrentFrame.mdpCount = mdpBatchSize;
1396
1397 ALOGD_IF(isDebug(), "%s:Trying with: mdpbatch %d fbbatch %d dropped %d",
1398 __FUNCTION__, mdpBatchSize, fbBatchSize,
1399 mCurrentFrame.dropCount);
1400
1401 if(postHeuristicsHandling(ctx, list)) {
1402 ALOGD_IF(isDebug(), "%s: Postheuristics handling succeeded",
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001403 __FUNCTION__);
1404 ALOGD_IF(sSimulationFlags,"%s: LOAD_MDP_COMP SUCCEEDED",
1405 __FUNCTION__);
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001406 return true;
1407 }
1408
1409 reset(ctx);
1410 --mdpBatchSize;
1411 ++fbBatchSize;
1412 }
1413
1414 return false;
Saurabh Shahb772ae32013-11-18 15:40:02 -08001415}
1416
Arun Kumar K.R2aa44c62014-01-21 23:08:28 -08001417bool MDPComp::isLoadBasedCompDoable(hwc_context_t *ctx) {
Prabhanjan Kandula3dbbd882013-12-11 14:43:46 +05301418 if(mDpy or isSecurePresent(ctx, mDpy) or
1419 isYuvPresent(ctx, mDpy)) {
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001420 return false;
1421 }
1422 return true;
1423}
1424
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001425bool MDPComp::canPartialUpdate(hwc_context_t *ctx,
1426 hwc_display_contents_1_t* list){
1427 if(!qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() ||
1428 isSkipPresent(ctx, mDpy) || (list->flags & HWC_GEOMETRY_CHANGED) ||
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001429 isCursorPresent(ctx, mDpy) || !sIsPartialUpdateActive || mDpy) {
1430 // On Async position update, the ROI becomes invalid, hence disable PU
1431 // when cursor is present
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001432 return false;
1433 }
Jeykumar Sankaran4dd10ab2014-07-02 12:23:09 -07001434 if(ctx->listStats[mDpy].secureUI)
1435 return false;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001436 return true;
1437}
1438
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001439bool MDPComp::tryVideoOnly(hwc_context_t *ctx,
1440 hwc_display_contents_1_t* list) {
1441 const bool secureOnly = true;
1442 return videoOnlyComp(ctx, list, not secureOnly) or
1443 videoOnlyComp(ctx, list, secureOnly);
1444}
1445
1446bool MDPComp::videoOnlyComp(hwc_context_t *ctx,
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001447 hwc_display_contents_1_t* list, bool secureOnly) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001448 if(sSimulationFlags & MDPCOMP_AVOID_VIDEO_ONLY)
1449 return false;
Praveena Pachipulusu47346c22014-12-04 11:06:41 +05301450
Saurabh Shahaa236822013-04-24 18:07:26 -07001451 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Praveena Pachipulusu47346c22014-12-04 11:06:41 +05301452 if(!isSecurePresent(ctx, mDpy)) {
1453 /* Bail out if we are processing only secured video layers
1454 * and we dont have any */
1455 if(secureOnly) {
1456 ALOGD_IF(isDebug(),"%s: No Secure Video Layers", __FUNCTION__);
1457 return false;
1458 }
1459 /* No Idle fall back for secure video layers and if there is only
1460 * single layer being composed. */
1461 if(sIdleFallBack && (ctx->listStats[mDpy].numAppLayers > 1)) {
1462 ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
1463 return false;
1464 }
1465 }
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001466
Saurabh Shahaa236822013-04-24 18:07:26 -07001467 mCurrentFrame.reset(numAppLayers);
Jeykumar Sankaraneb3a5e22014-04-08 16:07:55 -07001468 mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001469 updateYUV(ctx, list, secureOnly, mCurrentFrame);
Saurabh Shah4fdde762013-04-30 18:47:33 -07001470 int mdpCount = mCurrentFrame.mdpCount;
Saurabh Shahaa236822013-04-24 18:07:26 -07001471
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001472 if(!isYuvPresent(ctx, mDpy) or (mdpCount == 0)) {
1473 reset(ctx);
Saurabh Shahaa236822013-04-24 18:07:26 -07001474 return false;
1475 }
1476
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001477 if(mCurrentFrame.fbCount)
1478 mCurrentFrame.fbZ = mCurrentFrame.mdpCount;
Saurabh Shah4fdde762013-04-30 18:47:33 -07001479
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05001480 if(sEnableYUVsplit || needs3DComposition(ctx, mDpy)){
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001481 adjustForSourceSplit(ctx, list);
1482 }
1483
1484 if(!postHeuristicsHandling(ctx, list)) {
1485 ALOGD_IF(isDebug(), "post heuristic handling failed");
Justin Philip37ab9a82015-01-06 11:55:12 +05301486 if(errno == ENOBUFS) {
1487 ALOGD_IF(isDebug(), "SMP Allocation failed");
1488 //On SMP allocation failure in video only comp add padding round
1489 ctx->isPaddingRound = true;
1490 }
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001491 reset(ctx);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07001492 return false;
1493 }
1494
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001495 ALOGD_IF(sSimulationFlags,"%s: VIDEO_ONLY_COMP SUCCEEDED",
1496 __FUNCTION__);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001497 return true;
1498}
1499
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001500/* if tryFullFrame fails, try to push all video and secure RGB layers to MDP */
1501bool MDPComp::tryMDPOnlyLayers(hwc_context_t *ctx,
1502 hwc_display_contents_1_t* list) {
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001503 // Fall back to video only composition, if AIV video mode is enabled
1504 if(ctx->listStats[mDpy].mAIVVideoMode) {
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07001505 ALOGD_IF(isDebug(), "%s: AIV Video Mode enabled dpy %d",
1506 __FUNCTION__, mDpy);
1507 return false;
1508 }
1509
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05001510 // No MDP composition for 3D
1511 if(needs3DComposition(ctx,mDpy))
1512 return false;
1513
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001514 const bool secureOnly = true;
1515 return mdpOnlyLayersComp(ctx, list, not secureOnly) or
1516 mdpOnlyLayersComp(ctx, list, secureOnly);
1517
1518}
1519
1520bool MDPComp::mdpOnlyLayersComp(hwc_context_t *ctx,
1521 hwc_display_contents_1_t* list, bool secureOnly) {
1522
1523 if(sSimulationFlags & MDPCOMP_AVOID_MDP_ONLY_LAYERS)
1524 return false;
1525
Praveena Pachipulusu47346c22014-12-04 11:06:41 +05301526 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
1527 if(!isSecurePresent(ctx, mDpy) && !ctx->listStats[mDpy].secureUI) {
1528 /* Bail out if we are processing only secured video/ui layers
1529 * and we dont have any */
1530 if(secureOnly) {
1531 ALOGD_IF(isDebug(), "%s: No secure video/ui layers");
1532 return false;
1533 }
1534 /* No Idle fall back for secure video/ui layers and if there is only
1535 * single layer being composed. */
1536 if(sIdleFallBack && (ctx->listStats[mDpy].numAppLayers > 1)) {
1537 ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
1538 return false;
1539 }
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001540 }
1541
Tatenda Chipeperekwa95675a72014-12-15 17:06:43 -08001542 /* Bail out if we dont have any secure RGB layers */
1543 if (!ctx->listStats[mDpy].secureRGBCount) {
1544 reset(ctx);
1545 return false;
1546 }
1547
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001548 mCurrentFrame.reset(numAppLayers);
1549 mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
1550
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001551 updateYUV(ctx, list, secureOnly, mCurrentFrame);
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001552 /* mark secure RGB layers for MDP comp */
1553 updateSecureRGB(ctx, list);
1554
1555 if(mCurrentFrame.mdpCount == 0) {
1556 reset(ctx);
1557 return false;
1558 }
1559
1560 /* find the maximum batch of layers to be marked for framebuffer */
1561 bool ret = markLayersForCaching(ctx, list); //sets up fbZ also
1562 if(!ret) {
1563 ALOGD_IF(isDebug(),"%s: batching failed, dpy %d",__FUNCTION__, mDpy);
1564 reset(ctx);
1565 return false;
1566 }
1567
1568 if(sEnableYUVsplit){
1569 adjustForSourceSplit(ctx, list);
1570 }
1571
1572 if(!postHeuristicsHandling(ctx, list)) {
1573 ALOGD_IF(isDebug(), "post heuristic handling failed");
1574 reset(ctx);
1575 return false;
1576 }
1577
1578 ALOGD_IF(sSimulationFlags,"%s: MDP_ONLY_LAYERS_COMP SUCCEEDED",
1579 __FUNCTION__);
1580 return true;
1581}
1582
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001583/* Checks for conditions where YUV layers cannot be bypassed */
1584bool MDPComp::isYUVDoable(hwc_context_t* ctx, hwc_layer_1_t* layer) {
Ramkumar Radhakrishnana70981a2013-08-28 11:33:53 -07001585 if(isSkipLayer(layer)) {
Saurabh Shahe2474082013-05-15 16:32:13 -07001586 ALOGD_IF(isDebug(), "%s: Video marked SKIP dpy %d", __FUNCTION__, mDpy);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001587 return false;
1588 }
1589
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08001590 if(has90Transform(layer) && !canUseRotator(ctx, mDpy)) {
Amara Venkata Mastan Manoj Kumar9d373c02013-08-20 14:30:09 -07001591 ALOGD_IF(isDebug(), "%s: no free DMA pipe",__FUNCTION__);
1592 return false;
1593 }
1594
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001595 if(isSecuring(ctx, layer)) {
1596 ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
1597 return false;
1598 }
1599
Saurabh Shah4fdde762013-04-30 18:47:33 -07001600 if(!isValidDimension(ctx, layer)) {
1601 ALOGD_IF(isDebug(), "%s: Buffer is of invalid width",
1602 __FUNCTION__);
1603 return false;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001604 }
Saurabh Shah4fdde762013-04-30 18:47:33 -07001605
Naseer Ahmeddc61a972013-07-10 17:50:54 -04001606 if(layer->planeAlpha < 0xFF) {
1607 ALOGD_IF(isDebug(), "%s: Cannot handle YUV layer with plane alpha\
1608 in video only mode",
1609 __FUNCTION__);
1610 return false;
1611 }
1612
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001613 return true;
1614}
1615
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001616/* Checks for conditions where Secure RGB layers cannot be bypassed */
1617bool MDPComp::isSecureRGBDoable(hwc_context_t* ctx, hwc_layer_1_t* layer) {
1618 if(isSkipLayer(layer)) {
1619 ALOGD_IF(isDebug(), "%s: Secure RGB layer marked SKIP dpy %d",
1620 __FUNCTION__, mDpy);
1621 return false;
1622 }
1623
1624 if(isSecuring(ctx, layer)) {
1625 ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
1626 return false;
1627 }
1628
1629 if(not isSupportedForMDPComp(ctx, layer)) {
1630 ALOGD_IF(isDebug(), "%s: Unsupported secure RGB layer",
1631 __FUNCTION__);
1632 return false;
1633 }
1634 return true;
1635}
1636
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301637/* starts at fromIndex and check for each layer to find
1638 * if it it has overlapping with any Updating layer above it in zorder
1639 * till the end of the batch. returns true if it finds any intersection */
1640bool MDPComp::canPushBatchToTop(const hwc_display_contents_1_t* list,
1641 int fromIndex, int toIndex) {
1642 for(int i = fromIndex; i < toIndex; i++) {
1643 if(mCurrentFrame.isFBComposed[i] && !mCurrentFrame.drop[i]) {
1644 if(intersectingUpdatingLayers(list, i+1, toIndex, i)) {
1645 return false;
1646 }
1647 }
1648 }
1649 return true;
1650}
1651
1652/* Checks if given layer at targetLayerIndex has any
1653 * intersection with all the updating layers in beween
1654 * fromIndex and toIndex. Returns true if it finds intersectiion */
1655bool MDPComp::intersectingUpdatingLayers(const hwc_display_contents_1_t* list,
1656 int fromIndex, int toIndex, int targetLayerIndex) {
1657 for(int i = fromIndex; i <= toIndex; i++) {
1658 if(!mCurrentFrame.isFBComposed[i]) {
1659 if(areLayersIntersecting(&list->hwLayers[i],
1660 &list->hwLayers[targetLayerIndex])) {
1661 return true;
1662 }
1663 }
1664 }
1665 return false;
1666}
1667
1668int MDPComp::getBatch(hwc_display_contents_1_t* list,
1669 int& maxBatchStart, int& maxBatchEnd,
1670 int& maxBatchCount) {
1671 int i = 0;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301672 int fbZOrder =-1;
Jeykumar Sankaran9502f352014-01-20 12:25:32 -08001673 int droppedLayerCt = 0;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301674 while (i < mCurrentFrame.layerCount) {
1675 int batchCount = 0;
1676 int batchStart = i;
1677 int batchEnd = i;
Jeykumar Sankaran9502f352014-01-20 12:25:32 -08001678 /* Adjust batch Z order with the dropped layers so far */
1679 int fbZ = batchStart - droppedLayerCt;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301680 int firstZReverseIndex = -1;
Prabhanjan Kandula0ed2cc92013-12-06 12:39:04 +05301681 int updatingLayersAbove = 0;//Updating layer count in middle of batch
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301682 while(i < mCurrentFrame.layerCount) {
1683 if(!mCurrentFrame.isFBComposed[i]) {
1684 if(!batchCount) {
1685 i++;
1686 break;
1687 }
1688 updatingLayersAbove++;
1689 i++;
1690 continue;
1691 } else {
1692 if(mCurrentFrame.drop[i]) {
1693 i++;
Jeykumar Sankaran9502f352014-01-20 12:25:32 -08001694 droppedLayerCt++;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301695 continue;
1696 } else if(updatingLayersAbove <= 0) {
1697 batchCount++;
1698 batchEnd = i;
1699 i++;
1700 continue;
1701 } else { //Layer is FBComposed, not a drop & updatingLayer > 0
1702
1703 // We have a valid updating layer already. If layer-i not
1704 // have overlapping with all updating layers in between
1705 // batch-start and i, then we can add layer i to batch.
1706 if(!intersectingUpdatingLayers(list, batchStart, i-1, i)) {
1707 batchCount++;
1708 batchEnd = i;
1709 i++;
1710 continue;
1711 } else if(canPushBatchToTop(list, batchStart, i)) {
1712 //If All the non-updating layers with in this batch
1713 //does not have intersection with the updating layers
1714 //above in z-order, then we can safely move the batch to
1715 //higher z-order. Increment fbZ as it is moving up.
1716 if( firstZReverseIndex < 0) {
1717 firstZReverseIndex = i;
1718 }
1719 batchCount++;
1720 batchEnd = i;
1721 fbZ += updatingLayersAbove;
1722 i++;
1723 updatingLayersAbove = 0;
1724 continue;
1725 } else {
1726 //both failed.start the loop again from here.
1727 if(firstZReverseIndex >= 0) {
1728 i = firstZReverseIndex;
1729 }
1730 break;
1731 }
1732 }
1733 }
1734 }
1735 if(batchCount > maxBatchCount) {
1736 maxBatchCount = batchCount;
1737 maxBatchStart = batchStart;
1738 maxBatchEnd = batchEnd;
1739 fbZOrder = fbZ;
1740 }
1741 }
1742 return fbZOrder;
1743}
1744
1745bool MDPComp::markLayersForCaching(hwc_context_t* ctx,
1746 hwc_display_contents_1_t* list) {
1747 /* Idea is to keep as many non-updating(cached) layers in FB and
1748 * send rest of them through MDP. This is done in 2 steps.
1749 * 1. Find the maximum contiguous batch of non-updating layers.
1750 * 2. See if we can improve this batch size for caching by adding
1751 * opaque layers around the batch, if they don't have
1752 * any overlapping with the updating layers in between.
1753 * NEVER mark an updating layer for caching.
1754 * But cached ones can be marked for MDP */
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001755
1756 int maxBatchStart = -1;
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001757 int maxBatchEnd = -1;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001758 int maxBatchCount = 0;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301759 int fbZ = -1;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001760
Saurabh Shahd53bc5f2014-02-05 10:17:43 -08001761 /* Nothing is cached. No batching needed */
1762 if(mCurrentFrame.fbCount == 0) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001763 return true;
Saurabh Shahaa236822013-04-24 18:07:26 -07001764 }
Saurabh Shahd53bc5f2014-02-05 10:17:43 -08001765
1766 /* No MDP comp layers, try to use other comp modes */
1767 if(mCurrentFrame.mdpCount == 0) {
1768 return false;
Saurabh Shahaa236822013-04-24 18:07:26 -07001769 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001770
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301771 fbZ = getBatch(list, maxBatchStart, maxBatchEnd, maxBatchCount);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001772
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301773 /* reset rest of the layers lying inside ROI for MDP comp */
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001774 for(int i = 0; i < mCurrentFrame.layerCount; i++) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001775 hwc_layer_1_t* layer = &list->hwLayers[i];
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001776 if((i < maxBatchStart || i > maxBatchEnd) &&
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301777 mCurrentFrame.isFBComposed[i]){
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001778 if(!mCurrentFrame.drop[i]){
1779 //If an unsupported layer is being attempted to
1780 //be pulled out we should fail
1781 if(not isSupportedForMDPComp(ctx, layer)) {
1782 return false;
1783 }
1784 mCurrentFrame.isFBComposed[i] = false;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001785 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001786 }
1787 }
1788
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301789 // update the frame data
1790 mCurrentFrame.fbZ = fbZ;
1791 mCurrentFrame.fbCount = maxBatchCount;
Saurabh Shahaa236822013-04-24 18:07:26 -07001792 mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001793 mCurrentFrame.fbCount - mCurrentFrame.dropCount;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001794
1795 ALOGD_IF(isDebug(),"%s: cached count: %d",__FUNCTION__,
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301796 mCurrentFrame.fbCount);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001797
1798 return true;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001799}
Saurabh Shah85234ec2013-04-12 17:09:00 -07001800
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001801void MDPComp::updateLayerCache(hwc_context_t* ctx,
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001802 hwc_display_contents_1_t* list, FrameInfo& frame) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001803 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001804 int fbCount = 0;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001805
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001806 for(int i = 0; i < numAppLayers; i++) {
1807 if (mCachedFrame.hnd[i] == list->hwLayers[i].handle) {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001808 if(!frame.drop[i])
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001809 fbCount++;
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001810 frame.isFBComposed[i] = true;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001811 } else {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001812 frame.isFBComposed[i] = false;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001813 }
1814 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001815
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001816 frame.fbCount = fbCount;
1817 frame.mdpCount = frame.layerCount - frame.fbCount
1818 - frame.dropCount;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001819
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001820 ALOGD_IF(isDebug(),"%s: MDP count: %d FB count %d drop count: %d",
1821 __FUNCTION__, frame.mdpCount, frame.fbCount, frame.dropCount);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001822}
1823
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001824// drop other non-AIV layers from external display list.
1825void MDPComp::dropNonAIVLayers(hwc_context_t* ctx,
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07001826 hwc_display_contents_1_t* list) {
1827 for (size_t i = 0; i < (size_t)ctx->listStats[mDpy].numAppLayers; i++) {
1828 hwc_layer_1_t * layer = &list->hwLayers[i];
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001829 if(!(isAIVVideoLayer(layer) || isAIVCCLayer(layer))) {
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07001830 mCurrentFrame.dropCount++;
1831 mCurrentFrame.drop[i] = true;
1832 }
1833 }
1834 mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
1835 mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
1836 mCurrentFrame.fbCount - mCurrentFrame.dropCount;
1837 ALOGD_IF(isDebug(),"%s: fb count: %d mdp count %d drop count %d",
1838 __FUNCTION__, mCurrentFrame.fbCount, mCurrentFrame.mdpCount,
1839 mCurrentFrame.dropCount);
1840}
1841
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001842void MDPComp::updateYUV(hwc_context_t* ctx, hwc_display_contents_1_t* list,
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001843 bool secureOnly, FrameInfo& frame) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001844 int nYuvCount = ctx->listStats[mDpy].yuvCount;
radhakrishna03640472015-05-25 17:34:13 +05301845 int nVGpipes = qdutils::MDPVersion::getInstance().getVGPipes();
1846
1847 /* If number of YUV layers in the layer list is more than the number of
1848 VG pipes available in the target (non-split), try to program maximum
1849 possible number of YUV layers to MDP, instead of falling back to GPU
1850 completely.*/
1851 nYuvCount = (nYuvCount > nVGpipes) ? nVGpipes : nYuvCount;
1852
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001853 for(int index = 0;index < nYuvCount; index++){
1854 int nYuvIndex = ctx->listStats[mDpy].yuvIndices[index];
1855 hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
1856
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001857 if(mCurrentFrame.drop[nYuvIndex]) {
1858 continue;
1859 }
1860
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001861 if(!isYUVDoable(ctx, layer)) {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001862 if(!frame.isFBComposed[nYuvIndex]) {
1863 frame.isFBComposed[nYuvIndex] = true;
1864 frame.fbCount++;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001865 }
1866 } else {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001867 if(frame.isFBComposed[nYuvIndex]) {
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001868 private_handle_t *hnd = (private_handle_t *)layer->handle;
1869 if(!secureOnly || isSecureBuffer(hnd)) {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001870 frame.isFBComposed[nYuvIndex] = false;
1871 frame.fbCount--;
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001872 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001873 }
1874 }
1875 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001876
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001877 frame.mdpCount = frame.layerCount - frame.fbCount - frame.dropCount;
1878 ALOGD_IF(isDebug(),"%s: fb count: %d",__FUNCTION__, frame.fbCount);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001879}
1880
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001881void MDPComp::updateSecureRGB(hwc_context_t* ctx,
1882 hwc_display_contents_1_t* list) {
1883 int nSecureRGBCount = ctx->listStats[mDpy].secureRGBCount;
1884 for(int index = 0;index < nSecureRGBCount; index++){
1885 int nSecureRGBIndex = ctx->listStats[mDpy].secureRGBIndices[index];
1886 hwc_layer_1_t* layer = &list->hwLayers[nSecureRGBIndex];
1887
1888 if(!isSecureRGBDoable(ctx, layer)) {
1889 if(!mCurrentFrame.isFBComposed[nSecureRGBIndex]) {
1890 mCurrentFrame.isFBComposed[nSecureRGBIndex] = true;
1891 mCurrentFrame.fbCount++;
1892 }
1893 } else {
1894 if(mCurrentFrame.isFBComposed[nSecureRGBIndex]) {
1895 mCurrentFrame.isFBComposed[nSecureRGBIndex] = false;
1896 mCurrentFrame.fbCount--;
1897 }
1898 }
1899 }
1900
1901 mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
1902 mCurrentFrame.fbCount - mCurrentFrame.dropCount;
1903 ALOGD_IF(isDebug(),"%s: fb count: %d",__FUNCTION__,
1904 mCurrentFrame.fbCount);
1905}
1906
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001907hwc_rect_t MDPComp::getUpdatingFBRect(hwc_context_t *ctx,
1908 hwc_display_contents_1_t* list){
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001909 hwc_rect_t fbRect = (struct hwc_rect){0, 0, 0, 0};
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001910
1911 /* Update only the region of FB needed for composition */
1912 for(int i = 0; i < mCurrentFrame.layerCount; i++ ) {
1913 if(mCurrentFrame.isFBComposed[i] && !mCurrentFrame.drop[i]) {
1914 hwc_layer_1_t* layer = &list->hwLayers[i];
1915 hwc_rect_t dst = layer->displayFrame;
1916 fbRect = getUnion(fbRect, dst);
1917 }
1918 }
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08001919 trimAgainstROI(ctx, fbRect, fbRect);
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001920 return fbRect;
1921}
1922
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001923bool MDPComp::postHeuristicsHandling(hwc_context_t *ctx,
1924 hwc_display_contents_1_t* list) {
1925
1926 //Capability checks
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08001927 if(!resourceCheck(ctx, list)) {
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001928 ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
1929 return false;
1930 }
1931
1932 //Limitations checks
1933 if(!hwLimitationsCheck(ctx, list)) {
1934 ALOGD_IF(isDebug(), "%s: HW limitations",__FUNCTION__);
1935 return false;
1936 }
1937
Saurabh Shah3d4b8042013-12-10 15:19:17 -08001938 //Configure framebuffer first if applicable
1939 if(mCurrentFrame.fbZ >= 0) {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001940 hwc_rect_t fbRect = getUpdatingFBRect(ctx, list);
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001941 if(!ctx->mFBUpdate[mDpy]->prepare(ctx, list, fbRect, mCurrentFrame.fbZ))
1942 {
Saurabh Shah3d4b8042013-12-10 15:19:17 -08001943 ALOGD_IF(isDebug(), "%s configure framebuffer failed",
1944 __FUNCTION__);
1945 return false;
1946 }
1947 }
1948
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001949 mCurrentFrame.map();
1950
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001951 if(!allocLayerPipes(ctx, list)) {
1952 ALOGD_IF(isDebug(), "%s: Unable to allocate MDP pipes", __FUNCTION__);
Saurabh Shahaa236822013-04-24 18:07:26 -07001953 return false;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001954 }
1955
1956 for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
Saurabh Shahaa236822013-04-24 18:07:26 -07001957 index++) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001958 if(!mCurrentFrame.isFBComposed[index]) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001959 int mdpIndex = mCurrentFrame.layerToMDP[index];
1960 hwc_layer_1_t* layer = &list->hwLayers[index];
1961
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301962 //Leave fbZ for framebuffer. CACHE/GLES layers go here.
1963 if(mdpNextZOrder == mCurrentFrame.fbZ) {
1964 mdpNextZOrder++;
1965 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001966 MdpPipeInfo* cur_pipe = mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
1967 cur_pipe->zOrder = mdpNextZOrder++;
1968
radhakrishnac9a67412013-09-25 17:40:42 +05301969 private_handle_t *hnd = (private_handle_t *)layer->handle;
Raj Kamal389d6e32014-08-04 14:43:24 +05301970 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
radhakrishnac9a67412013-09-25 17:40:42 +05301971 if(configure4k2kYuv(ctx, layer,
1972 mCurrentFrame.mdpToLayer[mdpIndex])
1973 != 0 ){
1974 ALOGD_IF(isDebug(), "%s: Failed to configure split pipes \
1975 for layer %d",__FUNCTION__, index);
1976 return false;
1977 }
1978 else{
1979 mdpNextZOrder++;
1980 }
1981 continue;
1982 }
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05001983 if(needs3DComposition(ctx,mDpy) && get3DFormat(hnd) != HAL_NO_3D) {
1984 mdpNextZOrder++;
1985 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001986 if(configure(ctx, layer, mCurrentFrame.mdpToLayer[mdpIndex]) != 0 ){
1987 ALOGD_IF(isDebug(), "%s: Failed to configure overlay for \
radhakrishnac9a67412013-09-25 17:40:42 +05301988 layer %d",__FUNCTION__, index);
Saurabh Shahaa236822013-04-24 18:07:26 -07001989 return false;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001990 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001991 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001992 }
1993
Saurabh Shaha36be922013-12-16 18:18:39 -08001994 if(!ctx->mOverlay->validateAndSet(mDpy, ctx->dpyAttr[mDpy].fd)) {
1995 ALOGD_IF(isDebug(), "%s: Failed to validate and set overlay for dpy %d"
1996 ,__FUNCTION__, mDpy);
1997 return false;
1998 }
1999
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002000 setRedraw(ctx, list);
Saurabh Shahaa236822013-04-24 18:07:26 -07002001 return true;
2002}
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002003
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08002004bool MDPComp::resourceCheck(hwc_context_t* ctx,
2005 hwc_display_contents_1_t* list) {
Saurabh Shah173f4242013-11-20 09:50:12 -08002006 const bool fbUsed = mCurrentFrame.fbCount;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002007 int cursorInUse = 0;
2008 if(mDpy == HWC_DISPLAY_PRIMARY) {
2009 // check if cursor is in use for primary
2010 cursorInUse = HWCursor::getInstance()->isCursorSet();
2011 }
2012 int maxStages = qdutils::MDPVersion::getInstance().getBlendStages();
2013 // HW Cursor needs one blending stage, account for that in the check below
2014 // On high end targets(8994) has 8 blending stages, HAL is configured to use < 8.
2015 // Make use of the remaining stages for HW Cursor so that the composition
2016 // strategy would not fail due to this limitation.
2017 if (maxStages > sMaxPipesPerMixer) {
2018 cursorInUse = 0;
2019 }
2020 if(mCurrentFrame.mdpCount > (sMaxPipesPerMixer - fbUsed - cursorInUse)) {
Saurabh Shah173f4242013-11-20 09:50:12 -08002021 ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
2022 return false;
2023 }
Saurabh Shahacec8e42014-11-25 11:07:04 -08002024
2025 //Will benefit cases where a video has non-updating background.
2026 if((mDpy > HWC_DISPLAY_PRIMARY) and
2027 (mCurrentFrame.mdpCount > sMaxSecLayers)) {
2028 ALOGD_IF(isDebug(), "%s: Exceeds max secondary pipes",__FUNCTION__);
2029 return false;
2030 }
2031
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08002032 // Init rotCount to number of rotate sessions used by other displays
2033 int rotCount = ctx->mRotMgr->getNumActiveSessions();
2034 // Count the number of rotator sessions required for current display
2035 for (int index = 0; index < mCurrentFrame.layerCount; index++) {
2036 if(!mCurrentFrame.isFBComposed[index]) {
2037 hwc_layer_1_t* layer = &list->hwLayers[index];
2038 private_handle_t *hnd = (private_handle_t *)layer->handle;
2039 if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
2040 rotCount++;
2041 }
2042 }
2043 }
2044 // if number of layers to rotate exceeds max rotator sessions, bail out.
2045 if(rotCount > RotMgr::MAX_ROT_SESS) {
2046 ALOGD_IF(isDebug(), "%s: Exceeds max rotator sessions %d",
2047 __FUNCTION__, mDpy);
2048 return false;
2049 }
Saurabh Shah173f4242013-11-20 09:50:12 -08002050 return true;
2051}
2052
Prabhanjan Kandula21918db2013-11-26 15:51:58 +05302053bool MDPComp::hwLimitationsCheck(hwc_context_t* ctx,
2054 hwc_display_contents_1_t* list) {
2055
2056 //A-family hw limitation:
2057 //If a layer need alpha scaling, MDP can not support.
2058 if(ctx->mMDP.version < qdutils::MDSS_V5) {
2059 for(int i = 0; i < mCurrentFrame.layerCount; ++i) {
2060 if(!mCurrentFrame.isFBComposed[i] &&
2061 isAlphaScaled( &list->hwLayers[i])) {
2062 ALOGD_IF(isDebug(), "%s:frame needs alphaScaling",__FUNCTION__);
2063 return false;
2064 }
2065 }
2066 }
2067
2068 // On 8x26 & 8974 hw, we have a limitation of downscaling+blending.
2069 //If multiple layers requires downscaling and also they are overlapping
2070 //fall back to GPU since MDSS can not handle it.
2071 if(qdutils::MDPVersion::getInstance().is8x74v2() ||
2072 qdutils::MDPVersion::getInstance().is8x26()) {
2073 for(int i = 0; i < mCurrentFrame.layerCount-1; ++i) {
2074 hwc_layer_1_t* botLayer = &list->hwLayers[i];
2075 if(!mCurrentFrame.isFBComposed[i] &&
2076 isDownscaleRequired(botLayer)) {
2077 //if layer-i is marked for MDP and needs downscaling
2078 //check if any MDP layer on top of i & overlaps with layer-i
2079 for(int j = i+1; j < mCurrentFrame.layerCount; ++j) {
2080 hwc_layer_1_t* topLayer = &list->hwLayers[j];
2081 if(!mCurrentFrame.isFBComposed[j] &&
2082 isDownscaleRequired(topLayer)) {
2083 hwc_rect_t r = getIntersection(botLayer->displayFrame,
2084 topLayer->displayFrame);
2085 if(isValidRect(r))
2086 return false;
2087 }
2088 }
2089 }
2090 }
2091 }
2092 return true;
2093}
2094
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002095static bool validForCursor(hwc_context_t* ctx, int dpy, hwc_layer_1_t* layer) {
2096 private_handle_t *hnd = (private_handle_t *)layer->handle;
2097 hwc_rect dst = layer->displayFrame;
2098 hwc_rect src = integerizeSourceCrop(layer->sourceCropf);
2099 int srcW = src.right - src.left;
2100 int srcH = src.bottom - src.top;
2101 int dstW = dst.right - dst.left;
2102 int dstH = dst.bottom - dst.top;
2103 qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
2104 uint32_t maxCursorSize = mdpVersion.getMaxCursorSize();
2105 uint32_t numHwCursors = mdpVersion.getCursorPipes();
2106 bool primarySplit = isDisplaySplit(ctx, HWC_DISPLAY_PRIMARY);
2107 uint32_t cursorPipesNeeded = 1; // One cursor pipe needed(default)
2108 bool ret = false;
2109
2110 if(dpy > HWC_DISPLAY_PRIMARY) {
2111 // Cursor not supported on secondary displays, as it involves scaling
2112 // in most of the cases
2113 return false;
2114 } else if (isSkipLayer(layer)) {
2115 return false;
2116 // Checks for HW limitation
2117 } else if (numHwCursors == 0 || maxCursorSize <= 0) {
2118 return false;
2119 } else if (needsScaling(layer)) {
2120 return false;
2121 } else if (layer->transform != 0) {
2122 return false;
2123 } else if (hnd->format != HAL_PIXEL_FORMAT_RGBA_8888) {
2124 return false;
2125 } else if (srcW > (int)maxCursorSize || srcH > (int)maxCursorSize) {
2126 return false;
2127 }
2128
2129 if (isDisplaySplit(ctx, dpy) && !mdpVersion.isSrcSplit()) {
2130 // In case of split display with no srcSplit, the driver allocates two
2131 // pipes to support async position update across mixers, hence
2132 // need to account for that here.
2133 cursorPipesNeeded = 2;
2134 }
2135 if (cursorPipesNeeded <= numHwCursors) {
2136 ret = true;
2137 }
2138 return ret;
2139}
2140
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08002141// Checks only if videos or single layer(RGB) is updating
2142// which is used for setting dynamic fps or perf hint for single
2143// layer video playback
2144bool MDPComp::onlyVideosUpdating(hwc_context_t *ctx,
2145 hwc_display_contents_1_t* list) {
2146 bool support = false;
2147 FrameInfo frame;
2148 frame.reset(mCurrentFrame.layerCount);
2149 memset(&frame.drop, 0, sizeof(frame.drop));
2150 frame.dropCount = 0;
2151 ALOGD_IF(isDebug(), "%s: Update Cache and YUVInfo", __FUNCTION__);
2152 updateLayerCache(ctx, list, frame);
2153 updateYUV(ctx, list, false /*secure only*/, frame);
2154 // There are only updating YUV layers or there is single RGB
2155 // Layer(Youtube)
2156 if((ctx->listStats[mDpy].yuvCount == frame.mdpCount) ||
2157 (frame.layerCount == 1)) {
2158 support = true;
2159 }
2160 return support;
2161}
2162
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302163void MDPComp::setDynRefreshRate(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
2164 //For primary display, set the dynamic refreshrate
2165 if(!mDpy && qdutils::MDPVersion::getInstance().isDynFpsSupported() &&
2166 ctx->mUseMetaDataRefreshRate) {
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302167 uint32_t refreshRate = ctx->dpyAttr[mDpy].refreshRate;
2168 MDPVersion& mdpHw = MDPVersion::getInstance();
2169 if(sIdleFallBack) {
2170 //Set minimum panel refresh rate during idle timeout
2171 refreshRate = mdpHw.getMinFpsSupported();
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08002172 } else if(onlyVideosUpdating(ctx, list)) {
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302173 //Set the new fresh rate, if there is only one updating YUV layer
2174 //or there is one single RGB layer with this request
2175 refreshRate = ctx->listStats[mDpy].refreshRateRequest;
2176 }
2177 setRefreshRate(ctx, mDpy, refreshRate);
2178 }
2179}
2180
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002181int MDPComp::prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002182 int ret = 0;
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07002183 char property[PROPERTY_VALUE_MAX];
2184
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002185 if(!list) {
2186 ALOGE("%s: Invalid list", __FUNCTION__);
Raj Kamal4393eaa2014-06-06 13:45:20 +05302187 mCachedFrame.reset();
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002188 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Raj Kamal4393eaa2014-06-06 13:45:20 +05302189 return -1;
2190 }
2191
2192 const int numLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shah286cf122014-09-08 14:13:08 -07002193 if(mDpy == HWC_DISPLAY_PRIMARY) {
2194 sSimulationFlags = 0;
2195 if(property_get("debug.hwc.simulate", property, NULL) > 0) {
2196 int currentFlags = atoi(property);
2197 if(currentFlags != sSimulationFlags) {
2198 sSimulationFlags = currentFlags;
2199 ALOGI("%s: Simulation Flag read: 0x%x (%d)", __FUNCTION__,
2200 sSimulationFlags, sSimulationFlags);
2201 }
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07002202 }
2203 }
Ramkumar Radhakrishnanc5893f12013-06-06 19:43:53 -07002204
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302205 //reset old data
2206 mCurrentFrame.reset(numLayers);
2207 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
2208 mCurrentFrame.dropCount = 0;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002209 mCurrentFrame.hwCursorIndex = -1;
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302210
Raj Kamal9ed3d6b2014-02-07 16:15:17 +05302211 //Do not cache the information for next draw cycle.
2212 if(numLayers > MAX_NUM_APP_LAYERS or (!numLayers)) {
2213 ALOGI("%s: Unsupported layer count for mdp composition",
2214 __FUNCTION__);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002215 mCachedFrame.reset();
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302216#ifdef DYNAMIC_FPS
Praveena Pachipulusu1c5431e2015-05-29 19:38:30 +05302217 // Reset refresh rate
2218 setRefreshRate(ctx, mDpy, ctx->dpyAttr[mDpy].refreshRate);
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302219#endif
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002220 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002221 return -1;
2222 }
2223
Ramkumar Radhakrishnana70981a2013-08-28 11:33:53 -07002224 // Detect the start of animation and fall back to GPU only once to cache
2225 // all the layers in FB and display FB content untill animation completes.
2226 if(ctx->listStats[mDpy].isDisplayAnimating) {
2227 mCurrentFrame.needsRedraw = false;
2228 if(ctx->mAnimationState[mDpy] == ANIMATION_STOPPED) {
2229 mCurrentFrame.needsRedraw = true;
2230 ctx->mAnimationState[mDpy] = ANIMATION_STARTED;
2231 }
2232 setMDPCompLayerFlags(ctx, list);
2233 mCachedFrame.updateCounts(mCurrentFrame);
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302234#ifdef DYNAMIC_FPS
Praveena Pachipulusu1c5431e2015-05-29 19:38:30 +05302235 // Reset refresh rate
2236 setRefreshRate(ctx, mDpy, ctx->dpyAttr[mDpy].refreshRate);
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302237#endif
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002238 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Ramkumar Radhakrishnana70981a2013-08-28 11:33:53 -07002239 ret = -1;
2240 return ret;
2241 } else {
2242 ctx->mAnimationState[mDpy] = ANIMATION_STOPPED;
2243 }
2244
Raj Kamalfdfdddf2015-03-16 21:59:25 +05302245 if(!mDpy and !isSecondaryConnected(ctx) and !mPrevModeOn and
2246 mCachedFrame.isSameFrame(ctx,mDpy,list)) {
2247
2248 ALOGD_IF(isDebug(),"%s: Avoid new composition",__FUNCTION__);
2249 mCurrentFrame.needsRedraw = false;
2250 setMDPCompLayerFlags(ctx, list);
2251 mCachedFrame.updateCounts(mCurrentFrame);
2252#ifdef DYNAMIC_FPS
2253 setDynRefreshRate(ctx, list);
2254#endif
2255 return -1;
2256
2257 }
2258
Saurabh Shahb39f8152013-08-22 10:21:44 -07002259 //Hard conditions, if not met, cannot do MDP comp
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002260 if(isFrameDoable(ctx)) {
2261 generateROI(ctx, list);
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07002262 // if AIV Video mode is enabled, drop all non AIV layers from the
2263 // external display list.
2264 if(ctx->listStats[mDpy].mAIVVideoMode) {
2265 dropNonAIVLayers(ctx, list);
2266 }
Saurabh Shahb39f8152013-08-22 10:21:44 -07002267
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002268 // Configure the cursor if present
2269 int topIndex = ctx->listStats[mDpy].numAppLayers - 1;
2270 if(ctx->listStats[mDpy].cursorLayerPresent &&
2271 validForCursor(ctx, mDpy, &(list->hwLayers[topIndex]))) {
2272 if(configHwCursor(ctx->dpyAttr[mDpy].fd, mDpy,
2273 &(list->hwLayers[topIndex]))) {
2274 // As cursor is configured, mark that layer as dropped, so that
2275 // it wont be considered for composition by other strategies.
2276 mCurrentFrame.hwCursorIndex = topIndex;
2277 mCurrentFrame.drop[topIndex] = true;
2278 mCurrentFrame.dropCount++;
2279 }
2280 } else {
2281 // Release the hw cursor
2282 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
2283 }
2284
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07002285 // if tryFullFrame fails, try to push all video and secure RGB layers
2286 // to MDP for composition.
2287 mModeOn = tryFullFrame(ctx, list) || tryMDPOnlyLayers(ctx, list) ||
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07002288 tryVideoOnly(ctx, list);
Raj Kamal4393eaa2014-06-06 13:45:20 +05302289 if(mModeOn) {
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002290 setMDPCompLayerFlags(ctx, list);
2291 } else {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08002292 resetROI(ctx, mDpy);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002293 reset(ctx);
2294 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
2295 mCurrentFrame.dropCount = 0;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002296 // Check if cursor is in use for primary and mark accordingly
2297 if(!mDpy && HWCursor::getInstance()->isCursorSet()) {
2298 int topIndex = ctx->listStats[mDpy].numAppLayers - 1;
2299 hwc_layer_1_t *layer = &(list->hwLayers[topIndex]);
2300 layer->compositionType = HWC_CURSOR_OVERLAY;
2301 }
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002302 ret = -1;
Saurabh Shah286cf122014-09-08 14:13:08 -07002303 ALOGE_IF(sSimulationFlags && (mDpy == HWC_DISPLAY_PRIMARY),
2304 "MDP Composition Strategies Failed");
Saurabh Shahb39f8152013-08-22 10:21:44 -07002305 }
2306 } else {
Dileep Kumar Reddi4070e932014-09-30 09:00:57 +05302307 if ((ctx->mMDP.version == qdutils::MDP_V3_0_5) && ctx->mCopyBit[mDpy] &&
2308 enablePartialUpdateForMDP3) {
2309 generateROI(ctx, list);
2310 for(int i = 0; i < ctx->listStats[mDpy].numAppLayers; i++) {
2311 ctx->copybitDrop[i] = mCurrentFrame.drop[i];
2312 }
2313 }
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002314 ALOGD_IF( isDebug(),"%s: MDP Comp not possible for this frame",
2315 __FUNCTION__);
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002316 // Release the hw cursor
2317 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002318 ret = -1;
Saurabh Shahb39f8152013-08-22 10:21:44 -07002319 }
Saurabh Shahb39f8152013-08-22 10:21:44 -07002320
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002321 if(isDebug()) {
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002322 ALOGD("GEOMETRY change: %d",
2323 (list->flags & HWC_GEOMETRY_CHANGED));
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002324 android::String8 sDump("");
Jeykumar Sankaran6850ac62014-05-27 10:07:26 -07002325 dump(sDump, ctx);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002326 ALOGD("%s",sDump.string());
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002327 }
2328
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07002329#ifdef DYNAMIC_FPS
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302330 setDynRefreshRate(ctx, list);
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07002331#endif
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08002332 setPerfHint(ctx, list);
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07002333
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002334 mCachedFrame.cacheAll(list);
2335 mCachedFrame.updateCounts(mCurrentFrame);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002336 return ret;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002337}
2338
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002339bool MDPComp::allocSplitVGPipes(hwc_context_t *ctx, int index) {
radhakrishnac9a67412013-09-25 17:40:42 +05302340
2341 bool bRet = true;
radhakrishnac9a67412013-09-25 17:40:42 +05302342 int mdpIndex = mCurrentFrame.layerToMDP[index];
2343 PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
2344 info.pipeInfo = new MdpYUVPipeInfo;
2345 info.rot = NULL;
2346 MdpYUVPipeInfo& pipe_info = *(MdpYUVPipeInfo*)info.pipeInfo;
radhakrishnac9a67412013-09-25 17:40:42 +05302347
2348 pipe_info.lIndex = ovutils::OV_INVALID;
2349 pipe_info.rIndex = ovutils::OV_INVALID;
2350
Saurabh Shahc62f3982014-03-05 14:28:26 -08002351 Overlay::PipeSpecs pipeSpecs;
2352 pipeSpecs.formatClass = Overlay::FORMAT_YUV;
2353 pipeSpecs.needsScaling = true;
2354 pipeSpecs.dpy = mDpy;
2355 pipeSpecs.fb = false;
2356
2357 pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
radhakrishnac9a67412013-09-25 17:40:42 +05302358 if(pipe_info.lIndex == ovutils::OV_INVALID){
2359 bRet = false;
2360 ALOGD_IF(isDebug(),"%s: allocating first VG pipe failed",
2361 __FUNCTION__);
2362 }
Saurabh Shahc62f3982014-03-05 14:28:26 -08002363 pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
radhakrishnac9a67412013-09-25 17:40:42 +05302364 if(pipe_info.rIndex == ovutils::OV_INVALID){
2365 bRet = false;
2366 ALOGD_IF(isDebug(),"%s: allocating second VG pipe failed",
2367 __FUNCTION__);
2368 }
2369 return bRet;
2370}
Sushil Chauhandefd3522014-05-13 18:17:12 -07002371
2372int MDPComp::drawOverlap(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
2373 int fd = -1;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002374 if (ctx->mPtorInfo.isActive()) {
2375 fd = ctx->mCopyBit[mDpy]->drawOverlap(ctx, list);
Sushil Chauhandefd3522014-05-13 18:17:12 -07002376 if (fd < 0) {
2377 ALOGD_IF(isDebug(),"%s: failed", __FUNCTION__);
Sushil Chauhandefd3522014-05-13 18:17:12 -07002378 }
2379 }
2380 return fd;
2381}
Arun Kumar K.R2aa44c62014-01-21 23:08:28 -08002382//=============MDPCompNonSplit==================================================
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002383
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002384void MDPCompNonSplit::adjustForSourceSplit(hwc_context_t *ctx,
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302385 hwc_display_contents_1_t* list) {
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002386 //If 4k2k Yuv layer split is possible, and if
2387 //fbz is above 4k2k layer, increment fb zorder by 1
2388 //as we split 4k2k layer and increment zorder for right half
2389 //of the layer
Shalaj Jaina70b4352014-06-15 13:47:47 -07002390 if(!ctx)
2391 return;
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002392 if(mCurrentFrame.fbZ >= 0) {
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302393 for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
2394 index++) {
2395 if(!mCurrentFrame.isFBComposed[index]) {
2396 if(mdpNextZOrder == mCurrentFrame.fbZ) {
2397 mdpNextZOrder++;
2398 }
2399 mdpNextZOrder++;
2400 hwc_layer_1_t* layer = &list->hwLayers[index];
2401 private_handle_t *hnd = (private_handle_t *)layer->handle;
Raj Kamal389d6e32014-08-04 14:43:24 +05302402 if(isYUVSplitNeeded(hnd)) {
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302403 if(mdpNextZOrder <= mCurrentFrame.fbZ)
2404 mCurrentFrame.fbZ += 1;
2405 mdpNextZOrder++;
2406 //As we split 4kx2k yuv layer and program to 2 VG pipes
2407 //(if available) increase mdpcount by 1.
2408 mCurrentFrame.mdpCount++;
2409 }
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002410 }
2411 }
2412 }
radhakrishnac9a67412013-09-25 17:40:42 +05302413}
2414
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002415/*
2416 * Configures pipe(s) for MDP composition
2417 */
Saurabh Shah88e4d272013-09-03 13:31:29 -07002418int MDPCompNonSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002419 PipeLayerPair& PipeLayerPair) {
Saurabh Shah88e4d272013-09-03 13:31:29 -07002420 MdpPipeInfoNonSplit& mdp_info =
2421 *(static_cast<MdpPipeInfoNonSplit*>(PipeLayerPair.pipeInfo));
Justin Philipd6166602014-08-12 13:42:21 +05302422 eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shahacf10202013-02-26 10:15:15 -08002423 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Saurabh Shahacf10202013-02-26 10:15:15 -08002424 eDest dest = mdp_info.index;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002425
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002426 ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipe: %d",
2427 __FUNCTION__, layer, zOrder, dest);
2428
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002429 return configureNonSplit(ctx, layer, mDpy, mdpFlags, zOrder, dest,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002430 &PipeLayerPair.rot);
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002431}
2432
Saurabh Shah88e4d272013-09-03 13:31:29 -07002433bool MDPCompNonSplit::allocLayerPipes(hwc_context_t *ctx,
Saurabh Shahe51f8ca2013-05-06 17:26:16 -07002434 hwc_display_contents_1_t* list) {
Saurabh Shah8cc77712015-03-31 10:48:51 -07002435 for(uint32_t formatType = FORMAT_YUV; formatType < FORMAT_MAX;
2436 formatType++) {
2437 for(int index = 0; index < mCurrentFrame.layerCount; index++) {
2438 if(mCurrentFrame.isFBComposed[index]) continue;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002439
Saurabh Shah8cc77712015-03-31 10:48:51 -07002440 hwc_layer_1_t* layer = &list->hwLayers[index];
2441 private_handle_t *hnd = (private_handle_t *)layer->handle;
2442 if(formatType == FORMAT_YUV && !isYuvBuffer(hnd))
radhakrishnac9a67412013-09-25 17:40:42 +05302443 continue;
Saurabh Shah8cc77712015-03-31 10:48:51 -07002444 if(formatType == FORMAT_RGB && isYuvBuffer(hnd))
2445 continue;
2446
2447 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
2448 if(allocSplitVGPipes(ctx, index)){
2449 continue;
2450 }
radhakrishnac9a67412013-09-25 17:40:42 +05302451 }
radhakrishnac9a67412013-09-25 17:40:42 +05302452
Saurabh Shah8cc77712015-03-31 10:48:51 -07002453 int mdpIndex = mCurrentFrame.layerToMDP[index];
2454 PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
2455 info.pipeInfo = new MdpPipeInfoNonSplit;
2456 info.rot = NULL;
2457 MdpPipeInfoNonSplit& pipe_info =
2458 *(MdpPipeInfoNonSplit*)info.pipeInfo;
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -08002459
Saurabh Shah8cc77712015-03-31 10:48:51 -07002460 Overlay::PipeSpecs pipeSpecs;
2461 pipeSpecs.formatClass = isYuvBuffer(hnd) ?
2462 Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
2463 pipeSpecs.needsScaling = qhwc::needsScaling(layer) or
2464 (qdutils::MDPVersion::getInstance().is8x26() and
2465 ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres > 1024);
2466 pipeSpecs.dpy = mDpy;
2467 pipeSpecs.fb = false;
2468 pipeSpecs.numActiveDisplays = ctx->numActiveDisplays;
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -08002469
Saurabh Shah8cc77712015-03-31 10:48:51 -07002470 pipe_info.index = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahc62f3982014-03-05 14:28:26 -08002471
Saurabh Shah8cc77712015-03-31 10:48:51 -07002472 if(pipe_info.index == ovutils::OV_INVALID) {
2473 ALOGD_IF(isDebug(), "%s: Unable to get pipe for layer %d of "\
2474 "format type %d", __FUNCTION__, index, formatType);
2475 return false;
2476 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002477 }
2478 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002479 return true;
2480}
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002481
radhakrishnac9a67412013-09-25 17:40:42 +05302482int MDPCompNonSplit::configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
2483 PipeLayerPair& PipeLayerPair) {
2484 MdpYUVPipeInfo& mdp_info =
2485 *(static_cast<MdpYUVPipeInfo*>(PipeLayerPair.pipeInfo));
2486 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Justin Philipd6166602014-08-12 13:42:21 +05302487 eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
radhakrishnac9a67412013-09-25 17:40:42 +05302488 eDest lDest = mdp_info.lIndex;
2489 eDest rDest = mdp_info.rIndex;
2490
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002491 return configureSourceSplit(ctx, layer, mDpy, mdpFlagsL, zOrder,
radhakrishnac9a67412013-09-25 17:40:42 +05302492 lDest, rDest, &PipeLayerPair.rot);
2493}
2494
Saurabh Shah88e4d272013-09-03 13:31:29 -07002495bool MDPCompNonSplit::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002496
Raj Kamal4393eaa2014-06-06 13:45:20 +05302497 if(!isEnabled() or !mModeOn) {
2498 ALOGD_IF(isDebug(),"%s: MDP Comp not enabled/configured", __FUNCTION__);
Prabhanjan Kandula08222fc2013-07-10 17:20:59 +05302499 return true;
2500 }
2501
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002502 overlay::Overlay& ov = *ctx->mOverlay;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002503 LayerProp *layerProp = ctx->layerProp[mDpy];
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002504
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002505 int numHwLayers = ctx->listStats[mDpy].numAppLayers;
2506 for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ )
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002507 {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002508 if(mCurrentFrame.isFBComposed[i]) continue;
2509
Naseer Ahmed5b6708a2012-08-02 13:46:08 -07002510 hwc_layer_1_t *layer = &list->hwLayers[i];
Saurabh Shahacf10202013-02-26 10:15:15 -08002511 private_handle_t *hnd = (private_handle_t *)layer->handle;
2512 if(!hnd) {
Sushil Chauhan897a9c32013-07-18 11:09:55 -07002513 if (!(layer->flags & HWC_COLOR_FILL)) {
2514 ALOGE("%s handle null", __FUNCTION__);
2515 return false;
2516 }
2517 // No PLAY for Color layer
2518 layerProp[i].mFlags &= ~HWC_MDPCOMP;
2519 continue;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002520 }
2521
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002522 int mdpIndex = mCurrentFrame.layerToMDP[i];
2523
Raj Kamal389d6e32014-08-04 14:43:24 +05302524 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit)
radhakrishnac9a67412013-09-25 17:40:42 +05302525 {
2526 MdpYUVPipeInfo& pipe_info =
2527 *(MdpYUVPipeInfo*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
2528 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
2529 ovutils::eDest indexL = pipe_info.lIndex;
2530 ovutils::eDest indexR = pipe_info.rIndex;
2531 int fd = hnd->fd;
Praveena Pachipulusud9443c72014-02-17 10:42:28 +05302532 uint32_t offset = (uint32_t)hnd->offset;
radhakrishnac9a67412013-09-25 17:40:42 +05302533 if(rot) {
2534 rot->queueBuffer(fd, offset);
2535 fd = rot->getDstMemId();
2536 offset = rot->getDstOffset();
2537 }
2538 if(indexL != ovutils::OV_INVALID) {
2539 ovutils::eDest destL = (ovutils::eDest)indexL;
2540 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2541 using pipe: %d", __FUNCTION__, layer, hnd, indexL );
2542 if (!ov.queueBuffer(fd, offset, destL)) {
2543 ALOGE("%s: queueBuffer failed for display:%d",
2544 __FUNCTION__, mDpy);
2545 return false;
2546 }
2547 }
2548
2549 if(indexR != ovutils::OV_INVALID) {
2550 ovutils::eDest destR = (ovutils::eDest)indexR;
2551 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2552 using pipe: %d", __FUNCTION__, layer, hnd, indexR );
2553 if (!ov.queueBuffer(fd, offset, destR)) {
2554 ALOGE("%s: queueBuffer failed for display:%d",
2555 __FUNCTION__, mDpy);
2556 return false;
2557 }
2558 }
2559 }
2560 else{
2561 MdpPipeInfoNonSplit& pipe_info =
Saurabh Shah88e4d272013-09-03 13:31:29 -07002562 *(MdpPipeInfoNonSplit*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
radhakrishnac9a67412013-09-25 17:40:42 +05302563 ovutils::eDest dest = pipe_info.index;
2564 if(dest == ovutils::OV_INVALID) {
2565 ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, dest);
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002566 return false;
radhakrishnac9a67412013-09-25 17:40:42 +05302567 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002568
radhakrishnac9a67412013-09-25 17:40:42 +05302569 if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
2570 continue;
2571 }
2572
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002573 int fd = hnd->fd;
2574 uint32_t offset = (uint32_t)hnd->offset;
2575 int index = ctx->mPtorInfo.getPTORArrayIndex(i);
2576 if (!mDpy && (index != -1)) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07002577 hnd = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002578 fd = hnd->fd;
Sushil Chauhan875a92e2014-07-25 12:20:23 -07002579 offset = 0;
Sushil Chauhandefd3522014-05-13 18:17:12 -07002580 }
2581
radhakrishnac9a67412013-09-25 17:40:42 +05302582 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2583 using pipe: %d", __FUNCTION__, layer,
2584 hnd, dest );
2585
radhakrishnac9a67412013-09-25 17:40:42 +05302586 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
2587 if(rot) {
2588 if(!rot->queueBuffer(fd, offset))
2589 return false;
2590 fd = rot->getDstMemId();
2591 offset = rot->getDstOffset();
2592 }
2593
2594 if (!ov.queueBuffer(fd, offset, dest)) {
2595 ALOGE("%s: queueBuffer failed for display:%d ",
2596 __FUNCTION__, mDpy);
2597 return false;
2598 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002599 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002600
2601 layerProp[i].mFlags &= ~HWC_MDPCOMP;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002602 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002603 return true;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002604}
2605
Saurabh Shah88e4d272013-09-03 13:31:29 -07002606//=============MDPCompSplit===================================================
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002607
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002608void MDPCompSplit::adjustForSourceSplit(hwc_context_t *ctx,
radhakrishnac9a67412013-09-25 17:40:42 +05302609 hwc_display_contents_1_t* list){
2610 //if 4kx2k yuv layer is totally present in either in left half
2611 //or right half then try splitting the yuv layer to avoid decimation
radhakrishnac9a67412013-09-25 17:40:42 +05302612 const int lSplit = getLeftSplit(ctx, mDpy);
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302613 if(mCurrentFrame.fbZ >= 0) {
2614 for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
2615 index++) {
2616 if(!mCurrentFrame.isFBComposed[index]) {
2617 if(mdpNextZOrder == mCurrentFrame.fbZ) {
2618 mdpNextZOrder++;
2619 }
2620 mdpNextZOrder++;
2621 hwc_layer_1_t* layer = &list->hwLayers[index];
2622 private_handle_t *hnd = (private_handle_t *)layer->handle;
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002623 if(isYUVSplitNeeded(hnd) ||
2624 (needs3DComposition(ctx,mDpy) &&
2625 get3DFormat(hnd) != HAL_NO_3D)) {
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302626 hwc_rect_t dst = layer->displayFrame;
2627 if((dst.left > lSplit) || (dst.right < lSplit)) {
2628 mCurrentFrame.mdpCount += 1;
2629 }
2630 if(mdpNextZOrder <= mCurrentFrame.fbZ)
2631 mCurrentFrame.fbZ += 1;
2632 mdpNextZOrder++;
2633 }
2634 }
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002635 }
radhakrishnac9a67412013-09-25 17:40:42 +05302636 }
2637}
2638
Saurabh Shah88e4d272013-09-03 13:31:29 -07002639bool MDPCompSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
Saurabh Shahc62f3982014-03-05 14:28:26 -08002640 MdpPipeInfoSplit& pipe_info) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002641
Saurabh Shahc62f3982014-03-05 14:28:26 -08002642 const int lSplit = getLeftSplit(ctx, mDpy);
2643 private_handle_t *hnd = (private_handle_t *)layer->handle;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002644 hwc_rect_t dst = layer->displayFrame;
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002645 pipe_info.lIndex = ovutils::OV_INVALID;
2646 pipe_info.rIndex = ovutils::OV_INVALID;
2647
Saurabh Shahc62f3982014-03-05 14:28:26 -08002648 Overlay::PipeSpecs pipeSpecs;
2649 pipeSpecs.formatClass = isYuvBuffer(hnd) ?
2650 Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
2651 pipeSpecs.needsScaling = qhwc::needsScalingWithSplit(ctx, layer, mDpy);
2652 pipeSpecs.dpy = mDpy;
2653 pipeSpecs.mixer = Overlay::MIXER_LEFT;
2654 pipeSpecs.fb = false;
2655
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08002656 // Acquire pipe only for the updating half
2657 hwc_rect_t l_roi = ctx->listStats[mDpy].lRoi;
2658 hwc_rect_t r_roi = ctx->listStats[mDpy].rRoi;
2659
2660 if (dst.left < lSplit && isValidRect(getIntersection(dst, l_roi))) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002661 pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002662 if(pipe_info.lIndex == ovutils::OV_INVALID)
2663 return false;
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002664 }
2665
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08002666 if(dst.right > lSplit && isValidRect(getIntersection(dst, r_roi))) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002667 pipeSpecs.mixer = Overlay::MIXER_RIGHT;
2668 pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002669 if(pipe_info.rIndex == ovutils::OV_INVALID)
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002670 return false;
2671 }
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002672
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002673 return true;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002674}
2675
Saurabh Shah88e4d272013-09-03 13:31:29 -07002676bool MDPCompSplit::allocLayerPipes(hwc_context_t *ctx,
Saurabh Shahe51f8ca2013-05-06 17:26:16 -07002677 hwc_display_contents_1_t* list) {
Saurabh Shah8cc77712015-03-31 10:48:51 -07002678 for(uint32_t formatType = FORMAT_YUV; formatType < FORMAT_MAX;
2679 formatType++) {
2680 for(int index = 0 ; index < mCurrentFrame.layerCount; index++) {
2681 if(mCurrentFrame.isFBComposed[index]) continue;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002682
Saurabh Shah8cc77712015-03-31 10:48:51 -07002683 hwc_layer_1_t* layer = &list->hwLayers[index];
2684 private_handle_t *hnd = (private_handle_t *)layer->handle;
2685 if(formatType == FORMAT_YUV && !isYuvBuffer(hnd))
2686 continue;
2687 if(formatType == FORMAT_RGB && isYuvBuffer(hnd))
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002688 continue;
2689
Saurabh Shah8cc77712015-03-31 10:48:51 -07002690 hwc_rect_t dst = layer->displayFrame;
2691 const int lSplit = getLeftSplit(ctx, mDpy);
2692 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
2693 if((dst.left > lSplit)||(dst.right < lSplit)){
2694 if(allocSplitVGPipes(ctx, index)){
2695 continue;
2696 }
2697 }
2698 }
2699 //XXX: Check for forced 2D composition
2700 if(needs3DComposition(ctx, mDpy) && get3DFormat(hnd) != HAL_NO_3D)
2701 if(allocSplitVGPipes(ctx,index))
2702 continue;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002703
Saurabh Shah8cc77712015-03-31 10:48:51 -07002704 int mdpIndex = mCurrentFrame.layerToMDP[index];
2705 PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
2706 info.pipeInfo = new MdpPipeInfoSplit;
2707 info.rot = NULL;
2708 MdpPipeInfoSplit& pipe_info = *(MdpPipeInfoSplit*)info.pipeInfo;
2709
2710 if(!acquireMDPPipes(ctx, layer, pipe_info)) {
2711 ALOGD_IF(isDebug(), "%s: Unable to get pipe for layer %d of "\
2712 "format type %d", __FUNCTION__, index, formatType);
2713 return false;
2714 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002715 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002716 }
2717 return true;
2718}
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002719
radhakrishnac9a67412013-09-25 17:40:42 +05302720int MDPCompSplit::configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
2721 PipeLayerPair& PipeLayerPair) {
2722 const int lSplit = getLeftSplit(ctx, mDpy);
2723 hwc_rect_t dst = layer->displayFrame;
2724 if((dst.left > lSplit)||(dst.right < lSplit)){
2725 MdpYUVPipeInfo& mdp_info =
2726 *(static_cast<MdpYUVPipeInfo*>(PipeLayerPair.pipeInfo));
2727 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Justin Philipd6166602014-08-12 13:42:21 +05302728 eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
radhakrishnac9a67412013-09-25 17:40:42 +05302729 eDest lDest = mdp_info.lIndex;
2730 eDest rDest = mdp_info.rIndex;
2731
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002732 return configureSourceSplit(ctx, layer, mDpy, mdpFlagsL, zOrder,
radhakrishnac9a67412013-09-25 17:40:42 +05302733 lDest, rDest, &PipeLayerPair.rot);
2734 }
2735 else{
2736 return configure(ctx, layer, PipeLayerPair);
2737 }
2738}
2739
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002740/*
2741 * Configures pipe(s) for MDP composition
2742 */
Saurabh Shah88e4d272013-09-03 13:31:29 -07002743int MDPCompSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
Saurabh Shah67a38c32013-06-10 16:23:15 -07002744 PipeLayerPair& PipeLayerPair) {
Saurabh Shah88e4d272013-09-03 13:31:29 -07002745 MdpPipeInfoSplit& mdp_info =
2746 *(static_cast<MdpPipeInfoSplit*>(PipeLayerPair.pipeInfo));
Saurabh Shahacf10202013-02-26 10:15:15 -08002747 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Justin Philipd6166602014-08-12 13:42:21 +05302748 eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shahacf10202013-02-26 10:15:15 -08002749 eDest lDest = mdp_info.lIndex;
2750 eDest rDest = mdp_info.rIndex;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002751
2752 ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
Jeykumar Sankaran39305802014-12-12 17:55:57 -08002753 "dest_pipeR: %d",__FUNCTION__, layer, zOrder, lDest, rDest);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002754
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002755 return configureSplit(ctx, layer, mDpy, mdpFlagsL, zOrder, lDest,
Jeykumar Sankaran39305802014-12-12 17:55:57 -08002756 rDest, &PipeLayerPair.rot);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002757}
2758
Saurabh Shah88e4d272013-09-03 13:31:29 -07002759bool MDPCompSplit::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002760
Raj Kamal4393eaa2014-06-06 13:45:20 +05302761 if(!isEnabled() or !mModeOn) {
2762 ALOGD_IF(isDebug(),"%s: MDP Comp not enabled/configured", __FUNCTION__);
Prabhanjan Kandula08222fc2013-07-10 17:20:59 +05302763 return true;
2764 }
2765
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002766 overlay::Overlay& ov = *ctx->mOverlay;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002767 LayerProp *layerProp = ctx->layerProp[mDpy];
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002768
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002769 int numHwLayers = ctx->listStats[mDpy].numAppLayers;
2770 for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ )
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002771 {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002772 if(mCurrentFrame.isFBComposed[i]) continue;
2773
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002774 hwc_layer_1_t *layer = &list->hwLayers[i];
Saurabh Shahacf10202013-02-26 10:15:15 -08002775 private_handle_t *hnd = (private_handle_t *)layer->handle;
2776 if(!hnd) {
2777 ALOGE("%s handle null", __FUNCTION__);
2778 return false;
2779 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002780
2781 if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
2782 continue;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002783 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002784
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002785 int mdpIndex = mCurrentFrame.layerToMDP[i];
2786
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002787 if((isYUVSplitNeeded(hnd) && sEnableYUVsplit) ||
2788 (needs3DComposition(ctx, mDpy) && get3DFormat(hnd) != HAL_NO_3D))
radhakrishnac9a67412013-09-25 17:40:42 +05302789 {
2790 MdpYUVPipeInfo& pipe_info =
2791 *(MdpYUVPipeInfo*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
2792 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
2793 ovutils::eDest indexL = pipe_info.lIndex;
2794 ovutils::eDest indexR = pipe_info.rIndex;
2795 int fd = hnd->fd;
Praveena Pachipulusud9443c72014-02-17 10:42:28 +05302796 uint32_t offset = (uint32_t)hnd->offset;
radhakrishnac9a67412013-09-25 17:40:42 +05302797 if(rot) {
2798 rot->queueBuffer(fd, offset);
2799 fd = rot->getDstMemId();
2800 offset = rot->getDstOffset();
2801 }
2802 if(indexL != ovutils::OV_INVALID) {
2803 ovutils::eDest destL = (ovutils::eDest)indexL;
2804 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2805 using pipe: %d", __FUNCTION__, layer, hnd, indexL );
2806 if (!ov.queueBuffer(fd, offset, destL)) {
2807 ALOGE("%s: queueBuffer failed for display:%d",
2808 __FUNCTION__, mDpy);
2809 return false;
2810 }
2811 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002812
radhakrishnac9a67412013-09-25 17:40:42 +05302813 if(indexR != ovutils::OV_INVALID) {
2814 ovutils::eDest destR = (ovutils::eDest)indexR;
2815 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2816 using pipe: %d", __FUNCTION__, layer, hnd, indexR );
2817 if (!ov.queueBuffer(fd, offset, destR)) {
2818 ALOGE("%s: queueBuffer failed for display:%d",
2819 __FUNCTION__, mDpy);
2820 return false;
2821 }
Saurabh Shaha9da08f2013-07-03 13:27:53 -07002822 }
2823 }
radhakrishnac9a67412013-09-25 17:40:42 +05302824 else{
2825 MdpPipeInfoSplit& pipe_info =
2826 *(MdpPipeInfoSplit*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
2827 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
Saurabh Shaha9da08f2013-07-03 13:27:53 -07002828
radhakrishnac9a67412013-09-25 17:40:42 +05302829 ovutils::eDest indexL = pipe_info.lIndex;
2830 ovutils::eDest indexR = pipe_info.rIndex;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002831
radhakrishnac9a67412013-09-25 17:40:42 +05302832 int fd = hnd->fd;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002833 uint32_t offset = (uint32_t)hnd->offset;
2834 int index = ctx->mPtorInfo.getPTORArrayIndex(i);
2835 if (!mDpy && (index != -1)) {
2836 hnd = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
2837 fd = hnd->fd;
Sushil Chauhan875a92e2014-07-25 12:20:23 -07002838 offset = 0;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002839 }
radhakrishnac9a67412013-09-25 17:40:42 +05302840
Tatenda Chipeperekwa88fe6352014-04-14 10:36:06 -07002841 if(ctx->mAD->draw(ctx, fd, offset)) {
2842 fd = ctx->mAD->getDstFd();
2843 offset = ctx->mAD->getDstOffset();
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002844 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002845
radhakrishnac9a67412013-09-25 17:40:42 +05302846 if(rot) {
2847 rot->queueBuffer(fd, offset);
2848 fd = rot->getDstMemId();
2849 offset = rot->getDstOffset();
2850 }
2851
2852 //************* play left mixer **********
2853 if(indexL != ovutils::OV_INVALID) {
2854 ovutils::eDest destL = (ovutils::eDest)indexL;
2855 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2856 using pipe: %d", __FUNCTION__, layer, hnd, indexL );
2857 if (!ov.queueBuffer(fd, offset, destL)) {
2858 ALOGE("%s: queueBuffer failed for left mixer",
2859 __FUNCTION__);
2860 return false;
2861 }
2862 }
2863
2864 //************* play right mixer **********
2865 if(indexR != ovutils::OV_INVALID) {
2866 ovutils::eDest destR = (ovutils::eDest)indexR;
2867 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2868 using pipe: %d", __FUNCTION__, layer, hnd, indexR );
2869 if (!ov.queueBuffer(fd, offset, destR)) {
2870 ALOGE("%s: queueBuffer failed for right mixer",
2871 __FUNCTION__);
2872 return false;
2873 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002874 }
2875 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002876
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002877 layerProp[i].mFlags &= ~HWC_MDPCOMP;
2878 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002879
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002880 return true;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002881}
Saurabh Shahab47c692014-02-12 18:45:57 -08002882
2883//================MDPCompSrcSplit==============================================
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08002884
2885bool MDPCompSrcSplit::validateAndApplyROI(hwc_context_t *ctx,
2886 hwc_display_contents_1_t* list) {
2887 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
2888 hwc_rect_t visibleRect = ctx->listStats[mDpy].lRoi;
2889
2890 for(int i = numAppLayers - 1; i >= 0; i--) {
2891 if(!isValidRect(visibleRect)) {
2892 mCurrentFrame.drop[i] = true;
2893 mCurrentFrame.dropCount++;
2894 continue;
2895 }
2896
2897 const hwc_layer_1_t* layer = &list->hwLayers[i];
2898 hwc_rect_t dstRect = layer->displayFrame;
2899 hwc_rect_t res = getIntersection(visibleRect, dstRect);
2900
2901 if(!isValidRect(res)) {
2902 mCurrentFrame.drop[i] = true;
2903 mCurrentFrame.dropCount++;
2904 } else {
2905 /* Reset frame ROI when any layer which needs scaling also needs ROI
2906 * cropping */
2907 if(!isSameRect(res, dstRect) && needsScaling (layer)) {
2908 ALOGI("%s: Resetting ROI due to scaling", __FUNCTION__);
2909 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
2910 mCurrentFrame.dropCount = 0;
2911 return false;
2912 }
2913
2914 /* deduct any opaque region from visibleRect */
2915 if (layer->blending == HWC_BLENDING_NONE &&
2916 layer->planeAlpha == 0xFF)
2917 visibleRect = deductRect(visibleRect, res);
2918 }
2919 }
2920 return true;
2921}
2922
2923/*
2924 * HW Limitation: ping pong split can always split the ping pong output
2925 * equally across two DSI's. So the ROI programmed should be of equal width
2926 * for both the halves
2927 */
2928void MDPCompSrcSplit::generateROI(hwc_context_t *ctx,
2929 hwc_display_contents_1_t* list) {
2930 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
2931
2932
2933 if(!canPartialUpdate(ctx, list))
2934 return;
2935
2936 struct hwc_rect roi = (struct hwc_rect){0, 0, 0, 0};
2937 hwc_rect fullFrame = (struct hwc_rect) {0, 0,(int)ctx->dpyAttr[mDpy].xres,
2938 (int)ctx->dpyAttr[mDpy].yres};
2939
2940 for(int index = 0; index < numAppLayers; index++ ) {
2941 hwc_layer_1_t* layer = &list->hwLayers[index];
2942
2943 // If we have a RGB layer which needs rotation, no partial update
2944 if(!isYuvBuffer((private_handle_t *)layer->handle) && layer->transform)
2945 return;
2946
2947 if ((mCachedFrame.hnd[index] != layer->handle) ||
2948 isYuvBuffer((private_handle_t *)layer->handle)) {
2949 hwc_rect_t dst = layer->displayFrame;
2950 hwc_rect_t updatingRect = dst;
2951
2952#ifdef QCOM_BSP
2953 if(!needsScaling(layer) && !layer->transform)
2954 {
2955 hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
2956 int x_off = dst.left - src.left;
2957 int y_off = dst.top - src.top;
2958 updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
2959 }
2960#endif
2961
2962 roi = getUnion(roi, updatingRect);
2963 }
2964 }
2965
2966 /* No layer is updating. Still SF wants a refresh.*/
2967 if(!isValidRect(roi))
2968 return;
2969
2970 roi = expandROIFromMidPoint(roi, fullFrame);
2971
2972 hwc_rect lFrame = fullFrame;
2973 lFrame.right /= 2;
2974 hwc_rect lRoi = getIntersection(roi, lFrame);
2975
2976 // Align ROI coordinates to panel restrictions
2977 lRoi = getSanitizeROI(lRoi, lFrame);
2978
2979 hwc_rect rFrame = fullFrame;
2980 rFrame.left = lFrame.right;
2981 hwc_rect rRoi = getIntersection(roi, rFrame);
2982
2983 // Align ROI coordinates to panel restrictions
2984 rRoi = getSanitizeROI(rRoi, rFrame);
2985
2986 roi = getUnion(lRoi, rRoi);
2987
2988 ctx->listStats[mDpy].lRoi = roi;
2989 if(!validateAndApplyROI(ctx, list))
2990 resetROI(ctx, mDpy);
2991
2992 ALOGD_IF(isDebug(),"%s: generated ROI: [%d, %d, %d, %d] [%d, %d, %d, %d]",
2993 __FUNCTION__,
2994 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
2995 ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom,
2996 ctx->listStats[mDpy].rRoi.left, ctx->listStats[mDpy].rRoi.top,
2997 ctx->listStats[mDpy].rRoi.right, ctx->listStats[mDpy].rRoi.bottom);
2998}
2999
Saurabh Shahab47c692014-02-12 18:45:57 -08003000bool MDPCompSrcSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
Saurabh Shahc62f3982014-03-05 14:28:26 -08003001 MdpPipeInfoSplit& pipe_info) {
Saurabh Shahab47c692014-02-12 18:45:57 -08003002 private_handle_t *hnd = (private_handle_t *)layer->handle;
3003 hwc_rect_t dst = layer->displayFrame;
3004 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
3005 pipe_info.lIndex = ovutils::OV_INVALID;
3006 pipe_info.rIndex = ovutils::OV_INVALID;
3007
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08003008 if(qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() && !mDpy)
3009 trimAgainstROI(ctx,crop, dst);
3010
Saurabh Shahab47c692014-02-12 18:45:57 -08003011 //If 2 pipes are staged on a single stage of a mixer, then the left pipe
3012 //should have a higher priority than the right one. Pipe priorities are
3013 //starting with VG0, VG1 ... , RGB0 ..., DMA1
Saurabh Shahab47c692014-02-12 18:45:57 -08003014
Saurabh Shahc62f3982014-03-05 14:28:26 -08003015 Overlay::PipeSpecs pipeSpecs;
3016 pipeSpecs.formatClass = isYuvBuffer(hnd) ?
3017 Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
3018 pipeSpecs.needsScaling = qhwc::needsScaling(layer);
3019 pipeSpecs.dpy = mDpy;
3020 pipeSpecs.fb = false;
3021
Saurabh Shahab47c692014-02-12 18:45:57 -08003022 //1 pipe by default for a layer
Saurabh Shahc62f3982014-03-05 14:28:26 -08003023 pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahab47c692014-02-12 18:45:57 -08003024 if(pipe_info.lIndex == ovutils::OV_INVALID) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08003025 return false;
Saurabh Shahab47c692014-02-12 18:45:57 -08003026 }
3027
Saurabh Shahea7a01d2014-05-22 17:45:36 -07003028 /* Use 2 pipes IF
3029 a) Layer's crop width is > 2048 or
3030 b) Layer's dest width > 2048 or
3031 c) On primary, driver has indicated with caps to split always. This is
3032 based on an empirically derived value of panel height. Applied only
3033 if the layer's width is > mixer's width
3034 */
3035
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +05303036 MDPVersion& mdpHw = MDPVersion::getInstance();
Saurabh Shahea7a01d2014-05-22 17:45:36 -07003037 bool primarySplitAlways = (mDpy == HWC_DISPLAY_PRIMARY) and
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +05303038 mdpHw.isSrcSplitAlways();
Saurabh Shah514759d2014-11-11 18:02:24 -08003039 const uint32_t lSplit = getLeftSplit(ctx, mDpy);
3040 const uint32_t dstWidth = dst.right - dst.left;
3041 const uint32_t dstHeight = dst.bottom - dst.top;
Saurabh Shah05f4e222015-02-05 14:36:22 -08003042 uint32_t cropWidth = has90Transform(layer) ? crop.bottom - crop.top :
Saurabh Shah189f23d2014-09-26 17:21:00 -07003043 crop.right - crop.left;
Saurabh Shah05f4e222015-02-05 14:36:22 -08003044 uint32_t cropHeight = has90Transform(layer) ? crop.right - crop.left :
Saurabh Shah514759d2014-11-11 18:02:24 -08003045 crop.bottom - crop.top;
3046 //Approximation to actual clock, ignoring the common factors in pipe and
3047 //mixer cases like line_time
3048 const uint32_t layerClock = getLayerClock(dstWidth, dstHeight, cropHeight);
3049 const uint32_t mixerClock = lSplit;
Saurabh Shahea7a01d2014-05-22 17:45:36 -07003050
Saurabh Shah05f4e222015-02-05 14:36:22 -08003051 const uint32_t downscale = getRotDownscale(ctx, layer);
3052 if(downscale) {
3053 cropWidth /= downscale;
3054 cropHeight /= downscale;
3055 }
3056
Jeykumar Sankaran39305802014-12-12 17:55:57 -08003057 if(dstWidth > mdpHw.getMaxPipeWidth() or
3058 cropWidth > mdpHw.getMaxPipeWidth() or
Saurabh Shah514759d2014-11-11 18:02:24 -08003059 (primarySplitAlways and
3060 (cropWidth > lSplit or layerClock > mixerClock))) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08003061 pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahab47c692014-02-12 18:45:57 -08003062 if(pipe_info.rIndex == ovutils::OV_INVALID) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08003063 return false;
Saurabh Shahdd8237a2014-02-28 14:29:09 -08003064 }
3065
Jeykumar Sankaran89e23ab2015-01-28 15:57:46 -08003066 if(ctx->mOverlay->needsPrioritySwap(pipe_info.lIndex,
3067 pipe_info.rIndex)) {
Saurabh Shahdd8237a2014-02-28 14:29:09 -08003068 qhwc::swap(pipe_info.lIndex, pipe_info.rIndex);
Saurabh Shahab47c692014-02-12 18:45:57 -08003069 }
3070 }
3071
3072 return true;
3073}
3074
Saurabh Shahab47c692014-02-12 18:45:57 -08003075int MDPCompSrcSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
3076 PipeLayerPair& PipeLayerPair) {
3077 private_handle_t *hnd = (private_handle_t *)layer->handle;
3078 if(!hnd) {
3079 ALOGE("%s: layer handle is NULL", __FUNCTION__);
3080 return -1;
3081 }
3082 MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
3083 MdpPipeInfoSplit& mdp_info =
3084 *(static_cast<MdpPipeInfoSplit*>(PipeLayerPair.pipeInfo));
3085 Rotator **rot = &PipeLayerPair.rot;
3086 eZorder z = static_cast<eZorder>(mdp_info.zOrder);
Saurabh Shahab47c692014-02-12 18:45:57 -08003087 eDest lDest = mdp_info.lIndex;
3088 eDest rDest = mdp_info.rIndex;
3089 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
3090 hwc_rect_t dst = layer->displayFrame;
3091 int transform = layer->transform;
3092 eTransform orient = static_cast<eTransform>(transform);
Saurabh Shahab47c692014-02-12 18:45:57 -08003093 int rotFlags = ROT_FLAGS_NONE;
Sushil Chauhan65e26302015-01-14 10:48:57 -08003094 uint32_t format = ovutils::getMdpFormat(hnd->format, hnd->flags);
Saurabh Shahab47c692014-02-12 18:45:57 -08003095 Whf whf(getWidth(hnd), getHeight(hnd), format, hnd->size);
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05003096 eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shahab47c692014-02-12 18:45:57 -08003097
3098 ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
3099 "dest_pipeR: %d",__FUNCTION__, layer, z, lDest, rDest);
3100
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08003101 if(qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() && !mDpy) {
3102 /* MDP driver crops layer coordinates against ROI in Non-Split
3103 * and Split MDP comp. But HWC needs to crop them for source split.
3104 * Reason: 1) Source split is efficient only when the final effective
3105 * load is distributed evenly across mixers.
3106 * 2) We have to know the effective width of the layer that
3107 * the ROI needs to find the no. of pipes the layer needs.
3108 */
3109 trimAgainstROI(ctx, crop, dst);
3110 }
3111
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05003112 if(needs3DComposition(ctx, mDpy) &&
3113 get3DFormat(hnd) != HAL_NO_3D){
3114 return configure3DVideo(ctx, layer, mDpy, mdpFlags, z, lDest,
3115 rDest, &PipeLayerPair.rot);
3116 }
3117
Saurabh Shahab47c692014-02-12 18:45:57 -08003118 // Handle R/B swap
3119 if (layer->flags & HWC_FORMAT_RB_SWAP) {
3120 if (hnd->format == HAL_PIXEL_FORMAT_RGBA_8888)
3121 whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRA_8888);
3122 else if (hnd->format == HAL_PIXEL_FORMAT_RGBX_8888)
3123 whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
3124 }
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07003125 // update source crop and destination position of AIV video layer.
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07003126 if(ctx->listStats[mDpy].mAIVVideoMode && isYuvBuffer(hnd)) {
3127 updateCoordinates(ctx, crop, dst, mDpy);
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07003128 }
Ramkumar Radhakrishnana5c72872014-08-28 19:04:18 -07003129 /* Calculate the external display position based on MDP downscale,
3130 ActionSafe, and extorientation features. */
3131 calcExtDisplayPosition(ctx, hnd, mDpy, crop, dst, transform, orient);
Saurabh Shahab47c692014-02-12 18:45:57 -08003132
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003133 int downscale = getRotDownscale(ctx, layer);
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003134 setMdpFlags(ctx, layer, mdpFlags, downscale, transform);
Saurabh Shahab47c692014-02-12 18:45:57 -08003135
3136 if(lDest != OV_INVALID && rDest != OV_INVALID) {
3137 //Enable overfetch
Saurabh Shah97e2d802014-04-14 18:03:54 -07003138 setMdpFlags(mdpFlags, OV_MDSS_MDP_DUAL_PIPE);
Saurabh Shahab47c692014-02-12 18:45:57 -08003139 }
3140
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003141 if((has90Transform(layer) or downscale) and isRotationDoable(ctx, hnd)) {
Saurabh Shahab47c692014-02-12 18:45:57 -08003142 (*rot) = ctx->mRotMgr->getNext();
3143 if((*rot) == NULL) return -1;
Saurabh Shah39240c92014-03-31 10:31:42 -07003144 ctx->mLayerRotMap[mDpy]->add(layer, *rot);
Saurabh Shah1bd5b6f2014-05-19 12:23:13 -07003145 //If the video is using a single pipe, enable BWC
3146 if(rDest == OV_INVALID) {
Saurabh Shahcd018352014-11-11 13:54:19 -08003147 BwcPM::setBwc(ctx, mDpy, hnd, crop, dst, transform, downscale,
3148 mdpFlags);
Saurabh Shah1bd5b6f2014-05-19 12:23:13 -07003149 }
radhakrishnab8e2c952015-06-04 16:09:16 +05303150 uint32_t frame_rate = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].refreshRate;
3151 if(!mDpy && !isSecondaryConnected(ctx)) {
3152 if(metadata && (metadata->operation & UPDATE_REFRESH_RATE))
3153 frame_rate = metadata->refreshrate;
3154 }
Saurabh Shahab47c692014-02-12 18:45:57 -08003155 //Configure rotator for pre-rotation
radhakrishnab8e2c952015-06-04 16:09:16 +05303156 if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale,
3157 frame_rate) < 0) {
Saurabh Shahab47c692014-02-12 18:45:57 -08003158 ALOGE("%s: configRotator failed!", __FUNCTION__);
3159 return -1;
3160 }
Saurabh Shah8ec9b5e2014-06-30 14:37:17 -07003161 updateSource(orient, whf, crop, *rot);
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003162 rotFlags |= ovutils::ROT_PREROTATED;
Saurabh Shahab47c692014-02-12 18:45:57 -08003163 }
3164
3165 //If 2 pipes being used, divide layer into half, crop and dst
3166 hwc_rect_t cropL = crop;
3167 hwc_rect_t cropR = crop;
3168 hwc_rect_t dstL = dst;
3169 hwc_rect_t dstR = dst;
3170 if(lDest != OV_INVALID && rDest != OV_INVALID) {
3171 cropL.right = (crop.right + crop.left) / 2;
3172 cropR.left = cropL.right;
3173 sanitizeSourceCrop(cropL, cropR, hnd);
3174
Saurabh Shahb729b192014-08-15 18:04:24 -07003175 bool cropSwap = false;
Saurabh Shahab47c692014-02-12 18:45:57 -08003176 //Swap crops on H flip since 2 pipes are being used
3177 if((orient & OVERLAY_TRANSFORM_FLIP_H) && (*rot) == NULL) {
3178 hwc_rect_t tmp = cropL;
3179 cropL = cropR;
3180 cropR = tmp;
Saurabh Shahb729b192014-08-15 18:04:24 -07003181 cropSwap = true;
Saurabh Shahab47c692014-02-12 18:45:57 -08003182 }
3183
Saurabh Shahb729b192014-08-15 18:04:24 -07003184 //cropSwap trick: If the src and dst widths are both odd, let us say
3185 //2507, then splitting both into half would cause left width to be 1253
3186 //and right 1254. If crop is swapped because of H flip, this will cause
3187 //left crop width to be 1254, whereas left dst width remains 1253, thus
3188 //inducing a scaling that is unaccounted for. To overcome that we add 1
3189 //to the dst width if there is a cropSwap. So if the original width was
3190 //2507, the left dst width will be 1254. Even if the original width was
3191 //even for ex: 2508, the left dst width will still remain 1254.
3192 dstL.right = (dst.right + dst.left + cropSwap) / 2;
Saurabh Shahab47c692014-02-12 18:45:57 -08003193 dstR.left = dstL.right;
3194 }
3195
3196 //For the mdp, since either we are pre-rotating or MDP does flips
3197 orient = OVERLAY_TRANSFORM_0;
3198 transform = 0;
3199
3200 //configure left pipe
3201 if(lDest != OV_INVALID) {
Saurabh Shah2c8ad052014-08-15 13:27:46 -07003202 PipeArgs pargL(mdpFlags, whf, z,
Saurabh Shahab47c692014-02-12 18:45:57 -08003203 static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
3204 (ovutils::eBlending) getBlending(layer->blending));
3205
3206 if(configMdp(ctx->mOverlay, pargL, orient,
3207 cropL, dstL, metadata, lDest) < 0) {
3208 ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
3209 return -1;
3210 }
3211 }
3212
3213 //configure right pipe
3214 if(rDest != OV_INVALID) {
Saurabh Shah2c8ad052014-08-15 13:27:46 -07003215 PipeArgs pargR(mdpFlags, whf, z,
Saurabh Shahab47c692014-02-12 18:45:57 -08003216 static_cast<eRotFlags>(rotFlags),
3217 layer->planeAlpha,
3218 (ovutils::eBlending) getBlending(layer->blending));
3219 if(configMdp(ctx->mOverlay, pargR, orient,
3220 cropR, dstR, metadata, rDest) < 0) {
3221 ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
3222 return -1;
3223 }
3224 }
3225
3226 return 0;
3227}
3228
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -08003229bool MDPComp::getPartialUpdatePref(hwc_context_t *ctx) {
3230 Locker::Autolock _l(ctx->mDrawLock);
3231 const int fbNum = Overlay::getFbForDpy(Overlay::DPY_PRIMARY);
3232 char path[MAX_SYSFS_FILE_PATH];
3233 snprintf (path, sizeof(path), "sys/class/graphics/fb%d/dyn_pu", fbNum);
3234 int fd = open(path, O_RDONLY);
3235 if(fd < 0) {
3236 ALOGE("%s: Failed to open sysfd node: %s", __FUNCTION__, path);
3237 return -1;
3238 }
3239 char value[4];
3240 ssize_t size_read = read(fd, value, sizeof(value)-1);
3241 if(size_read <= 0) {
3242 ALOGE("%s: Failed to read sysfd node: %s", __FUNCTION__, path);
3243 close(fd);
3244 return -1;
3245 }
3246 close(fd);
3247 value[size_read] = '\0';
3248 return atoi(value);
3249}
3250
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003251int MDPComp::setPartialUpdatePref(hwc_context_t *ctx, bool enable) {
3252 Locker::Autolock _l(ctx->mDrawLock);
3253 const int fbNum = Overlay::getFbForDpy(Overlay::DPY_PRIMARY);
3254 char path[MAX_SYSFS_FILE_PATH];
3255 snprintf (path, sizeof(path), "sys/class/graphics/fb%d/dyn_pu", fbNum);
3256 int fd = open(path, O_WRONLY);
3257 if(fd < 0) {
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -08003258 ALOGE("%s: Failed to open sysfd node: %s", __FUNCTION__, path);
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003259 return -1;
3260 }
3261 char value[4];
3262 snprintf(value, sizeof(value), "%d", (int)enable);
3263 ssize_t ret = write(fd, value, strlen(value));
3264 if(ret <= 0) {
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -08003265 ALOGE("%s: Failed to write to sysfd nodes: %s", __FUNCTION__, path);
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003266 close(fd);
3267 return -1;
3268 }
3269 close(fd);
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003270 return 0;
3271}
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08003272
3273bool MDPComp::loadPerfLib() {
3274 char perfLibPath[PROPERTY_VALUE_MAX] = {0};
3275 bool success = false;
3276 if((property_get("ro.vendor.extension_library", perfLibPath, NULL) <= 0)) {
3277 ALOGE("vendor library not set in ro.vendor.extension_library");
3278 return false;
3279 }
3280
3281 sLibPerfHint = dlopen(perfLibPath, RTLD_NOW);
3282 if(sLibPerfHint) {
3283 *(void **)&sPerfLockAcquire = dlsym(sLibPerfHint, "perf_lock_acq");
3284 *(void **)&sPerfLockRelease = dlsym(sLibPerfHint, "perf_lock_rel");
3285 if (!sPerfLockAcquire || !sPerfLockRelease) {
3286 ALOGE("Failed to load symbols for perfLock");
3287 dlclose(sLibPerfHint);
3288 sLibPerfHint = NULL;
3289 return false;
3290 }
3291 success = true;
3292 ALOGI("Successfully Loaded perf hint API's");
3293 } else {
3294 ALOGE("Failed to open %s : %s", perfLibPath, dlerror());
3295 }
3296 return success;
3297}
3298
3299void MDPComp::setPerfHint(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
3300 if ((sPerfHintWindow < 0) || mDpy || !sLibPerfHint) {
3301 return;
3302 }
3303 static int count = sPerfHintWindow;
3304 static int perflockFlag = 0;
3305
3306 /* Send hint to mpctl when single layer is updated
3307 * for a successful number of windows. Hint release
3308 * happens immediately upon multiple layer update.
3309 */
3310 if (onlyVideosUpdating(ctx, list)) {
3311 if(count) {
3312 count--;
3313 }
3314 } else {
3315 if (perflockFlag) {
3316 perflockFlag = 0;
3317 sPerfLockRelease(sPerfLockHandle);
3318 }
3319 count = sPerfHintWindow;
3320 }
3321 if (count == 0 && !perflockFlag) {
3322 int perfHint = 0x4501; // 45-display layer hint, 01-Enable
3323 sPerfLockHandle = sPerfLockAcquire(0 /*handle*/, 0/*duration*/,
3324 &perfHint, sizeof(perfHint)/sizeof(int));
Arun Kumar K.R8b927022015-02-24 12:34:21 -08003325 if(sPerfLockHandle > 0) {
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08003326 perflockFlag = 1;
3327 }
3328 }
3329}
3330
Naseer Ahmed7c958d42012-07-31 18:57:03 -07003331}; //namespace
3332