blob: 2fe80b45d3b7420223c310301c5670034e3bec29 [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;
58
Saurabh Shah8cc77712015-03-31 10:48:51 -070059enum AllocOrder { FORMAT_YUV, FORMAT_RGB, FORMAT_MAX };
60
Saurabh Shah88e4d272013-09-03 13:31:29 -070061MDPComp* MDPComp::getObject(hwc_context_t *ctx, const int& dpy) {
Saurabh Shah60e8bde2014-04-30 14:46:03 -070062 if(qdutils::MDPVersion::getInstance().isSrcSplit()) {
63 sSrcSplitEnabled = true;
64 return new MDPCompSrcSplit(dpy);
65 } else if(isDisplaySplit(ctx, dpy)) {
Saurabh Shah88e4d272013-09-03 13:31:29 -070066 return new MDPCompSplit(dpy);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -080067 }
Saurabh Shah88e4d272013-09-03 13:31:29 -070068 return new MDPCompNonSplit(dpy);
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -080069}
70
Saurabh Shahac279de2015-05-21 18:56:58 -070071MDPComp::MDPComp(int dpy) : mDpy(dpy), mModeOn(false), mPrevModeOn(false) {
72};
Jeykumar Sankaran85977e32013-02-25 17:06:08 -080073
Jeykumar Sankaran6850ac62014-05-27 10:07:26 -070074void MDPComp::dump(android::String8& buf, hwc_context_t *ctx)
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -080075{
Jeykumar Sankaran3c6bb042013-08-15 14:01:04 -070076 if(mCurrentFrame.layerCount > MAX_NUM_APP_LAYERS)
77 return;
78
Jeykumar Sankaran85977e32013-02-25 17:06:08 -080079 dumpsys_log(buf,"HWC Map for Dpy: %s \n",
Jeykumar Sankaran27dee262013-08-01 17:09:54 -070080 (mDpy == 0) ? "\"PRIMARY\"" :
81 (mDpy == 1) ? "\"EXTERNAL\"" : "\"VIRTUAL\"");
Saurabh Shahe9bc60f2013-08-29 12:58:06 -070082 dumpsys_log(buf,"CURR_FRAME: layerCount:%2d mdpCount:%2d "
Arun Kumar K.R00b84792015-03-27 11:28:36 -070083 "fbCount:%2d dropCount:%2d\n", mCurrentFrame.layerCount,
84 mCurrentFrame.mdpCount, mCurrentFrame.fbCount, mCurrentFrame.dropCount);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -080085 dumpsys_log(buf,"needsFBRedraw:%3s pipesUsed:%2d MaxPipesPerMixer: %d \n",
86 (mCurrentFrame.needsRedraw? "YES" : "NO"),
87 mCurrentFrame.mdpCount, sMaxPipesPerMixer);
Jeykumar Sankaran6850ac62014-05-27 10:07:26 -070088 if(isDisplaySplit(ctx, mDpy)) {
89 dumpsys_log(buf, "Programmed ROI's: Left: [%d, %d, %d, %d] "
90 "Right: [%d, %d, %d, %d] \n",
91 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
92 ctx->listStats[mDpy].lRoi.right,
93 ctx->listStats[mDpy].lRoi.bottom,
94 ctx->listStats[mDpy].rRoi.left,ctx->listStats[mDpy].rRoi.top,
95 ctx->listStats[mDpy].rRoi.right,
96 ctx->listStats[mDpy].rRoi.bottom);
97 } else {
98 dumpsys_log(buf, "Programmed ROI: [%d, %d, %d, %d] \n",
99 ctx->listStats[mDpy].lRoi.left,ctx->listStats[mDpy].lRoi.top,
100 ctx->listStats[mDpy].lRoi.right,
101 ctx->listStats[mDpy].lRoi.bottom);
102 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800103 dumpsys_log(buf," --------------------------------------------- \n");
104 dumpsys_log(buf," listIdx | cached? | mdpIndex | comptype | Z \n");
105 dumpsys_log(buf," --------------------------------------------- \n");
106 for(int index = 0; index < mCurrentFrame.layerCount; index++ )
107 dumpsys_log(buf," %7d | %7s | %8d | %9s | %2d \n",
108 index,
109 (mCurrentFrame.isFBComposed[index] ? "YES" : "NO"),
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700110 mCurrentFrame.layerToMDP[index],
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800111 (mCurrentFrame.isFBComposed[index] ?
Arun Kumar K.R00b84792015-03-27 11:28:36 -0700112 (mCurrentFrame.drop[index] ?
113 ((mCurrentFrame.hwCursorIndex == index) ? "CURSOR": "DROP"):
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700114 (mCurrentFrame.needsRedraw ? "GLES" : "CACHE")) : "MDP"),
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800115 (mCurrentFrame.isFBComposed[index] ? mCurrentFrame.fbZ :
116 mCurrentFrame.mdpToLayer[mCurrentFrame.layerToMDP[index]].pipeInfo->zOrder));
117 dumpsys_log(buf,"\n");
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800118}
119
120bool MDPComp::init(hwc_context_t *ctx) {
121
122 if(!ctx) {
123 ALOGE("%s: Invalid hwc context!!",__FUNCTION__);
124 return false;
125 }
126
Saurabh Shah59562ff2014-09-30 16:13:12 -0700127 char property[PROPERTY_VALUE_MAX] = {0};
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800128
129 sEnabled = false;
Dileep Kumar Reddid8e601d2014-10-28 18:20:43 +0530130 if((ctx->mMDP.version >= qdutils::MDP_V4_0) &&
131 (property_get("persist.hwc.mdpcomp.enable", property, NULL) > 0) &&
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800132 (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
133 (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800134 sEnabled = true;
135 }
136
Jeykumar Sankaran24c199d2013-05-24 09:40:36 -0700137 sEnableMixedMode = true;
138 if((property_get("debug.mdpcomp.mixedmode.disable", property, NULL) > 0) &&
139 (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
140 (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
141 sEnableMixedMode = false;
142 }
143
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700144 qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
145
Saurabh Shah2fd8a252014-12-05 13:49:53 -0800146 sMaxPipesPerMixer = (int)mdpVersion.getBlendStages();
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700147 if(property_get("persist.hwc.mdpcomp.maxpermixer", property, "-1") > 0) {
Saurabh Shah85234ec2013-04-12 17:09:00 -0700148 int val = atoi(property);
149 if(val >= 0)
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700150 sMaxPipesPerMixer = min(val, sMaxPipesPerMixer);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800151 }
152
Saurabh Shahacec8e42014-11-25 11:07:04 -0800153 /* Maximum layers allowed to use MDP on secondary panels. If property
154 * doesn't exist, default to 1. Using the property it can be set to 0 or
155 * more.
156 */
157 if(property_get("persist.hwc.maxseclayers", property, "1") > 0) {
158 int val = atoi(property);
159 sMaxSecLayers = (val >= 0) ? val : 1;
160 sMaxSecLayers = min(sMaxSecLayers, sMaxPipesPerMixer);
161 }
162
Naseer Ahmedf40f2c82013-08-14 16:42:40 -0400163 if(ctx->mMDP.panel != MIPI_CMD_PANEL) {
Saurabh Shah59562ff2014-09-30 16:13:12 -0700164 sIdleInvalidator = IdleInvalidator::getInstance();
165 if(sIdleInvalidator->init(timeout_handler, ctx) < 0) {
166 delete sIdleInvalidator;
167 sIdleInvalidator = NULL;
Naseer Ahmedf40f2c82013-08-14 16:42:40 -0400168 }
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800169 }
radhakrishnac9a67412013-09-25 17:40:42 +0530170
Saurabh Shah7c727642014-06-02 15:47:14 -0700171 if(!qdutils::MDPVersion::getInstance().isSrcSplit() &&
Saurabh Shahc46cf9d2014-07-02 15:22:34 -0700172 !qdutils::MDPVersion::getInstance().isRotDownscaleEnabled() &&
Saurabh Shah7c727642014-06-02 15:47:14 -0700173 property_get("persist.mdpcomp.4k2kSplit", property, "0") > 0 &&
174 (!strncmp(property, "1", PROPERTY_VALUE_MAX) ||
175 !strncasecmp(property,"true", PROPERTY_VALUE_MAX))) {
Raj Kamal389d6e32014-08-04 14:43:24 +0530176 sEnableYUVsplit = true;
radhakrishnac9a67412013-09-25 17:40:42 +0530177 }
Sushil Chauhandefd3522014-05-13 18:17:12 -0700178
Dileep Kumar Reddic6ef3472014-09-24 19:07:08 +0530179 bool defaultPTOR = false;
180 //Enable PTOR when "persist.hwc.ptor.enable" is not defined for
Prabhanjan Kandulafc541b32015-03-30 20:56:16 +0530181 //Bear family targets by default
Dileep Kumar Reddic6ef3472014-09-24 19:07:08 +0530182 if((property_get("persist.hwc.ptor.enable", property, NULL) <= 0) &&
183 (qdutils::MDPVersion::getInstance().is8x16() ||
Prabhanjan Kandulafc541b32015-03-30 20:56:16 +0530184 qdutils::MDPVersion::getInstance().is8x39() ||
185 qdutils::MDPVersion::getInstance().is8x52())) {
Dileep Kumar Reddic6ef3472014-09-24 19:07:08 +0530186 defaultPTOR = true;
187 }
188
189 if (defaultPTOR || (!strncasecmp(property, "true", PROPERTY_VALUE_MAX)) ||
190 (!strncmp(property, "1", PROPERTY_VALUE_MAX ))) {
Sushil Chauhandefd3522014-05-13 18:17:12 -0700191 ctx->mCopyBit[HWC_DISPLAY_PRIMARY] = new CopyBit(ctx,
192 HWC_DISPLAY_PRIMARY);
193 }
194
Dileep Kumar Reddi4070e932014-09-30 09:00:57 +0530195 if((property_get("persist.mdp3.partialUpdate", property, NULL) <= 0) &&
196 (ctx->mMDP.version == qdutils::MDP_V3_0_5)) {
197 enablePartialUpdateForMDP3 = true;
198 }
199
200 if(!enablePartialUpdateForMDP3 &&
201 (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
202 (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
203 enablePartialUpdateForMDP3 = true;
204 }
205
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -0800206 sIsPartialUpdateActive = getPartialUpdatePref(ctx);
207
Arun Kumar K.R299bcda2014-12-18 19:36:40 -0800208 if(property_get("persist.mdpcomp_perfhint", property, "-1") > 0) {
209 int val = atoi(property);
210 if(val > 0 && loadPerfLib()) {
211 sPerfHintWindow = val;
212 ALOGI("PerfHintWindow = %d", sPerfHintWindow);
213 }
214 }
215
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700216 return true;
217}
218
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800219void MDPComp::reset(hwc_context_t *ctx) {
220 const int numLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shah2a4eb1b2013-07-22 16:33:23 -0700221 mCurrentFrame.reset(numLayers);
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800222 ctx->mOverlay->clear(mDpy);
223 ctx->mLayerRotMap[mDpy]->clear();
Saurabh Shah2a4eb1b2013-07-22 16:33:23 -0700224}
225
Raj Kamal4393eaa2014-06-06 13:45:20 +0530226void MDPComp::reset() {
Raj Kamalfdfdddf2015-03-16 21:59:25 +0530227 mPrevModeOn = mModeOn;
Raj Kamal4393eaa2014-06-06 13:45:20 +0530228 mModeOn = false;
229}
230
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700231void MDPComp::timeout_handler(void *udata) {
232 struct hwc_context_t* ctx = (struct hwc_context_t*)(udata);
Raj Kamalfdfdddf2015-03-16 21:59:25 +0530233 bool handleTimeout = false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700234
235 if(!ctx) {
236 ALOGE("%s: received empty data in timer callback", __FUNCTION__);
237 return;
238 }
Raj Kamal58b31a02014-12-16 15:53:53 +0530239
240 ctx->mDrawLock.lock();
Raj Kamalfdfdddf2015-03-16 21:59:25 +0530241
242 /* Handle timeout event only if the previous composition
243 on any display is MDP or MIXED*/
244 for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
245 if(ctx->mMDPComp[i])
246 handleTimeout =
247 ctx->mMDPComp[i]->isMDPComp() || handleTimeout;
248 }
249
250 if(!handleTimeout) {
Ramkumar Radhakrishnan92abb4f2014-02-06 21:31:29 -0800251 ALOGD_IF(isDebug(), "%s:Do not handle this timeout", __FUNCTION__);
Raj Kamal58b31a02014-12-16 15:53:53 +0530252 ctx->mDrawLock.unlock();
Ramkumar Radhakrishnan92abb4f2014-02-06 21:31:29 -0800253 return;
254 }
Jesse Hall3be78d92012-08-21 15:12:23 -0700255 if(!ctx->proc) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700256 ALOGE("%s: HWC proc not registered", __FUNCTION__);
Raj Kamal58b31a02014-12-16 15:53:53 +0530257 ctx->mDrawLock.unlock();
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700258 return;
259 }
260 sIdleFallBack = true;
Raj Kamal58b31a02014-12-16 15:53:53 +0530261 ctx->mDrawLock.unlock();
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700262 /* Trigger SF to redraw the current frame */
Jesse Hall3be78d92012-08-21 15:12:23 -0700263 ctx->proc->invalidate(ctx->proc);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700264}
265
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700266void MDPComp::setMaxPipesPerMixer(const uint32_t value) {
267 qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
Saurabh Shah2fd8a252014-12-05 13:49:53 -0800268 uint32_t maxSupported = (int)mdpVersion.getBlendStages();
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700269 if(value > maxSupported) {
270 ALOGW("%s: Input exceeds max value supported. Setting to"
271 "max value: %d", __FUNCTION__, maxSupported);
272 }
273 sMaxPipesPerMixer = min(value, maxSupported);
274}
275
Saurabh Shah59562ff2014-09-30 16:13:12 -0700276void MDPComp::setIdleTimeout(const uint32_t& timeout) {
277 enum { ONE_REFRESH_PERIOD_MS = 17, ONE_BILLION_MS = 1000000000 };
278
279 if(sIdleInvalidator) {
280 if(timeout <= ONE_REFRESH_PERIOD_MS) {
281 //If the specified timeout is < 1 draw cycle worth, "virtually"
282 //disable idle timeout. The ideal way for clients to disable
283 //timeout is to set it to 0
284 sIdleInvalidator->setIdleTimeout(ONE_BILLION_MS);
285 ALOGI("Disabled idle timeout");
286 return;
287 }
288 sIdleInvalidator->setIdleTimeout(timeout);
289 ALOGI("Idle timeout set to %u", timeout);
290 } else {
291 ALOGW("Cannot set idle timeout, IdleInvalidator not enabled");
292 }
293}
294
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800295void MDPComp::setMDPCompLayerFlags(hwc_context_t *ctx,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800296 hwc_display_contents_1_t* list) {
297 LayerProp *layerProp = ctx->layerProp[mDpy];
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800298
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800299 for(int index = 0; index < ctx->listStats[mDpy].numAppLayers; index++) {
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800300 hwc_layer_1_t* layer = &(list->hwLayers[index]);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800301 if(!mCurrentFrame.isFBComposed[index]) {
302 layerProp[index].mFlags |= HWC_MDPCOMP;
303 layer->compositionType = HWC_OVERLAY;
304 layer->hints |= HWC_HINT_CLEAR_FB;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800305 } else {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700306 /* Drop the layer when its already present in FB OR when it lies
307 * outside frame's ROI */
308 if(!mCurrentFrame.needsRedraw || mCurrentFrame.drop[index]) {
Arun Kumar K.R00b84792015-03-27 11:28:36 -0700309 if(index == mCurrentFrame.hwCursorIndex) {
310 layer->compositionType = HWC_CURSOR_OVERLAY;
311 } else {
312 layer->compositionType = HWC_OVERLAY;
313 }
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700314 }
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800315 }
316 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700317}
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500318
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800319void MDPComp::setRedraw(hwc_context_t *ctx,
320 hwc_display_contents_1_t* list) {
321 mCurrentFrame.needsRedraw = false;
322 if(!mCachedFrame.isSameFrame(mCurrentFrame, list) ||
323 (list->flags & HWC_GEOMETRY_CHANGED) ||
324 isSkipPresent(ctx, mDpy)) {
325 mCurrentFrame.needsRedraw = true;
326 }
327}
328
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800329MDPComp::FrameInfo::FrameInfo() {
Saurabh Shahf7fad542014-08-14 10:11:36 -0700330 memset(&mdpToLayer, 0, sizeof(mdpToLayer));
Saurabh Shahaa236822013-04-24 18:07:26 -0700331 reset(0);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800332}
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800333
Saurabh Shahaa236822013-04-24 18:07:26 -0700334void MDPComp::FrameInfo::reset(const int& numLayers) {
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700335 for(int i = 0 ; i < MAX_NUM_BLEND_STAGES; i++ ) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800336 if(mdpToLayer[i].pipeInfo) {
337 delete mdpToLayer[i].pipeInfo;
338 mdpToLayer[i].pipeInfo = NULL;
339 //We dont own the rotator
340 mdpToLayer[i].rot = NULL;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800341 }
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800342 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800343
344 memset(&mdpToLayer, 0, sizeof(mdpToLayer));
345 memset(&layerToMDP, -1, sizeof(layerToMDP));
Saurabh Shahaa236822013-04-24 18:07:26 -0700346 memset(&isFBComposed, 1, sizeof(isFBComposed));
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800347
Saurabh Shahaa236822013-04-24 18:07:26 -0700348 layerCount = numLayers;
349 fbCount = numLayers;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800350 mdpCount = 0;
Saurabh Shah2f3895f2013-05-02 10:13:31 -0700351 needsRedraw = true;
Saurabh Shahd53bc5f2014-02-05 10:17:43 -0800352 fbZ = -1;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800353}
354
Saurabh Shahaa236822013-04-24 18:07:26 -0700355void MDPComp::FrameInfo::map() {
356 // populate layer and MDP maps
357 int mdpIdx = 0;
358 for(int idx = 0; idx < layerCount; idx++) {
359 if(!isFBComposed[idx]) {
360 mdpToLayer[mdpIdx].listIndex = idx;
361 layerToMDP[idx] = mdpIdx++;
362 }
363 }
364}
365
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800366MDPComp::LayerCache::LayerCache() {
367 reset();
368}
369
370void MDPComp::LayerCache::reset() {
Saurabh Shahaa236822013-04-24 18:07:26 -0700371 memset(&hnd, 0, sizeof(hnd));
Prabhanjan Kandula2243aa62013-10-24 12:58:55 +0530372 memset(&isFBComposed, true, sizeof(isFBComposed));
373 memset(&drop, false, sizeof(drop));
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800374 layerCount = 0;
Saurabh Shahaa236822013-04-24 18:07:26 -0700375}
376
377void MDPComp::LayerCache::cacheAll(hwc_display_contents_1_t* list) {
Praveena Pachipulusud9443c72014-02-17 10:42:28 +0530378 const int numAppLayers = (int)list->numHwLayers - 1;
Saurabh Shahaa236822013-04-24 18:07:26 -0700379 for(int i = 0; i < numAppLayers; i++) {
380 hnd[i] = list->hwLayers[i].handle;
381 }
382}
383
384void MDPComp::LayerCache::updateCounts(const FrameInfo& curFrame) {
Saurabh Shahaa236822013-04-24 18:07:26 -0700385 layerCount = curFrame.layerCount;
Prabhanjan Kandula2243aa62013-10-24 12:58:55 +0530386 memcpy(&isFBComposed, &curFrame.isFBComposed, sizeof(isFBComposed));
387 memcpy(&drop, &curFrame.drop, sizeof(drop));
388}
389
Jeykumar Sankaran988d3682013-11-15 11:57:16 -0800390bool MDPComp::LayerCache::isSameFrame(const FrameInfo& curFrame,
391 hwc_display_contents_1_t* list) {
Prabhanjan Kandula2243aa62013-10-24 12:58:55 +0530392 if(layerCount != curFrame.layerCount)
393 return false;
394 for(int i = 0; i < curFrame.layerCount; i++) {
395 if((curFrame.isFBComposed[i] != isFBComposed[i]) ||
396 (curFrame.drop[i] != drop[i])) {
397 return false;
398 }
Jeykumar Sankaran988d3682013-11-15 11:57:16 -0800399 if(curFrame.isFBComposed[i] &&
400 (hnd[i] != list->hwLayers[i].handle)){
401 return false;
402 }
Prabhanjan Kandula2243aa62013-10-24 12:58:55 +0530403 }
404 return true;
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800405}
406
Raj Kamalfdfdddf2015-03-16 21:59:25 +0530407bool MDPComp::LayerCache::isSameFrame(hwc_context_t *ctx, int dpy,
408 hwc_display_contents_1_t* list) {
409
410 if(layerCount != ctx->listStats[dpy].numAppLayers)
411 return false;
412
413 if((list->flags & HWC_GEOMETRY_CHANGED) ||
414 isSkipPresent(ctx, dpy)) {
415 return false;
416 }
417
418 for(int i = 0; i < layerCount; i++) {
419 if(hnd[i] != list->hwLayers[i].handle)
420 return false;
421 }
422
423 return true;
424}
425
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700426bool MDPComp::isSupportedForMDPComp(hwc_context_t *ctx, hwc_layer_1_t* layer) {
427 private_handle_t *hnd = (private_handle_t *)layer->handle;
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800428 if((has90Transform(layer) and (not isRotationDoable(ctx, hnd))) ||
Raj Kamal1179d9c2014-10-28 15:31:35 +0530429 (not isValidDimension(ctx,layer)) ||
430 isSkipLayer(layer)) {
431 //More conditions here, sRGB+Blend etc
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700432 return false;
433 }
434 return true;
435}
436
Sravan Kumar D.V.Nad5d9292013-04-24 14:23:04 +0530437bool MDPComp::isValidDimension(hwc_context_t *ctx, hwc_layer_1_t *layer) {
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800438 private_handle_t *hnd = (private_handle_t *)layer->handle;
439
440 if(!hnd) {
Sushil Chauhan897a9c32013-07-18 11:09:55 -0700441 if (layer->flags & HWC_COLOR_FILL) {
442 // Color layer
443 return true;
444 }
Ramkumar Radhakrishnan0cabf212014-09-08 20:07:49 -0700445 ALOGD_IF(isDebug(), "%s: layer handle is NULL", __FUNCTION__);
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800446 return false;
447 }
448
Naseer Ahmede850a802013-09-06 13:12:52 -0400449 //XXX: Investigate doing this with pixel phase on MDSS
Naseer Ahmede77f8082013-10-10 13:42:48 -0400450 if(!isSecureBuffer(hnd) && isNonIntegralSourceCrop(layer->sourceCropf))
Naseer Ahmede850a802013-09-06 13:12:52 -0400451 return false;
452
Saurabh Shah62e1d732013-09-17 10:44:05 -0700453 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
Saurabh Shah4fdde762013-04-30 18:47:33 -0700454 hwc_rect_t dst = layer->displayFrame;
Saurabh Shahb6810df2014-06-17 16:00:22 -0700455 bool rotated90 = (bool)(layer->transform & HAL_TRANSFORM_ROT_90);
Saurabh Shahe28a4022014-06-13 11:41:13 -0700456 int crop_w = rotated90 ? crop.bottom - crop.top : crop.right - crop.left;
457 int crop_h = rotated90 ? crop.right - crop.left : crop.bottom - crop.top;
Saurabh Shah4fdde762013-04-30 18:47:33 -0700458 int dst_w = dst.right - dst.left;
459 int dst_h = dst.bottom - dst.top;
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800460 float w_scale = ((float)crop_w / (float)dst_w);
461 float h_scale = ((float)crop_h / (float)dst_h);
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530462 MDPVersion& mdpHw = MDPVersion::getInstance();
Saurabh Shah4fdde762013-04-30 18:47:33 -0700463
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800464 /* Workaround for MDP HW limitation in DSI command mode panels where
465 * FPS will not go beyond 30 if buffers on RGB pipes are of width or height
466 * less than 5 pixels
Sravan Kumar D.V.Nad5d9292013-04-24 14:23:04 +0530467 * There also is a HW limilation in MDP, minimum block size is 2x2
468 * Fallback to GPU if height is less than 2.
469 */
Saurabh Shah189f23d2014-09-26 17:21:00 -0700470 if(mdpHw.hasMinCropWidthLimitation() and (crop_w < 5 or crop_h < 5))
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800471 return false;
472
Ramkumar Radhakrishnan1a763e92015-03-19 16:46:46 -0700473 /* crop_w and crop_h should be even for yuv layer, so fallback to GPU for
474 * those cases
475 */
476 if(isYuvBuffer(hnd) && (crop_w < 2 || crop_h < 2)) {
477 return false;
478 }
479
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800480 if((w_scale > 1.0f) || (h_scale > 1.0f)) {
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530481 const uint32_t maxMDPDownscale = mdpHw.getMaxMDPDownscale();
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800482 const float w_dscale = w_scale;
483 const float h_dscale = h_scale;
484
Jeykumar Sankaran1706a772013-11-27 12:55:19 -0800485 if(ctx->mMDP.version >= qdutils::MDSS_V5) {
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700486
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530487 if(!mdpHw.supportsDecimation()) {
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700488 /* On targets that doesnt support Decimation (eg.,8x26)
489 * maximum downscale support is overlay pipe downscale.
490 */
Jeykumar Sankaran39305802014-12-12 17:55:57 -0800491 if(crop_w > (int) mdpHw.getMaxPipeWidth() ||
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530492 w_dscale > maxMDPDownscale ||
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700493 h_dscale > maxMDPDownscale)
Jeykumar Sankaran1706a772013-11-27 12:55:19 -0800494 return false;
495 } else {
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700496 // Decimation on macrotile format layers is not supported.
497 if(isTileRendered(hnd)) {
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530498 /* Bail out if
499 * 1. Src crop > Mixer limit on nonsplit MDPComp
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700500 * 2. exceeds maximum downscale limit
501 */
Jeykumar Sankaran39305802014-12-12 17:55:57 -0800502 if(((crop_w > (int) mdpHw.getMaxPipeWidth()) &&
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530503 !sSrcSplitEnabled) ||
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700504 w_dscale > maxMDPDownscale ||
505 h_dscale > maxMDPDownscale) {
506 return false;
507 }
508 } else if(w_dscale > 64 || h_dscale > 64)
Jeykumar Sankaran1706a772013-11-27 12:55:19 -0800509 return false;
510 }
511 } else { //A-family
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700512 if(w_dscale > maxMDPDownscale || h_dscale > maxMDPDownscale)
Saurabh Shah4fdde762013-04-30 18:47:33 -0700513 return false;
514 }
Saurabh Shah4fdde762013-04-30 18:47:33 -0700515 }
516
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800517 if((w_scale < 1.0f) || (h_scale < 1.0f)) {
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530518 const uint32_t upscale = mdpHw.getMaxMDPUpscale();
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800519 const float w_uscale = 1.0f / w_scale;
520 const float h_uscale = 1.0f / h_scale;
521
522 if(w_uscale > upscale || h_uscale > upscale)
523 return false;
524 }
525
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800526 return true;
527}
528
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800529bool MDPComp::isFrameDoable(hwc_context_t *ctx) {
Saurabh Shahaa236822013-04-24 18:07:26 -0700530 bool ret = true;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800531
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800532 if(!isEnabled()) {
533 ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
Saurabh Shahaa236822013-04-24 18:07:26 -0700534 ret = false;
Raj Kamal068f4572014-04-14 16:14:06 +0530535 } else if((qdutils::MDPVersion::getInstance().is8x26() ||
Prabhanjan Kandula958ffa92014-05-12 14:56:56 +0530536 qdutils::MDPVersion::getInstance().is8x16() ||
Prabhanjan Kandulafc541b32015-03-30 20:56:16 +0530537 qdutils::MDPVersion::getInstance().is8x39() ||
538 qdutils::MDPVersion::getInstance().is8x52()) &&
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800539 ctx->mVideoTransFlag &&
540 isSecondaryConnected(ctx)) {
Saurabh Shahd4e65852013-06-17 11:33:53 -0700541 //1 Padding round to shift pipes across mixers
542 ALOGD_IF(isDebug(),"%s: MDP Comp. video transition padding round",
543 __FUNCTION__);
544 ret = false;
Raj Kamalc0d34242015-03-17 20:53:14 +0530545 } else if((qdutils::MDPVersion::getInstance().is8x26() ||
546 qdutils::MDPVersion::getInstance().is8x16() ||
Prabhanjan Kandulafc541b32015-03-30 20:56:16 +0530547 qdutils::MDPVersion::getInstance().is8x39() ||
548 qdutils::MDPVersion::getInstance().is8x52()) &&
Raj Kamalc0d34242015-03-17 20:53:14 +0530549 !mDpy && isSecondaryAnimating(ctx) &&
550 isYuvPresent(ctx,HWC_DISPLAY_VIRTUAL)) {
551 ALOGD_IF(isDebug(),"%s: Display animation in progress",
552 __FUNCTION__);
553 ret = false;
Ramkumar Radhakrishnanf26fe9e2014-09-09 13:47:54 -0700554 } else if(qdutils::MDPVersion::getInstance().getTotalPipes() < 8) {
555 /* TODO: freeing up all the resources only for the targets having total
556 number of pipes < 8. Need to analyze number of VIG pipes used
557 for primary in previous draw cycle and accordingly decide
558 whether to fall back to full GPU comp or video only comp
559 */
560 if(isSecondaryConfiguring(ctx)) {
561 ALOGD_IF( isDebug(),"%s: External Display connection is pending",
562 __FUNCTION__);
563 ret = false;
564 } else if(ctx->isPaddingRound) {
565 ALOGD_IF(isDebug(), "%s: padding round invoked for dpy %d",
566 __FUNCTION__,mDpy);
567 ret = false;
568 }
Tatenda Chipeperekwadc8d7082014-11-04 16:41:50 -0800569 } else if (ctx->isDMAStateChanging) {
570 // Bail out if a padding round has been invoked in order to switch DMA
571 // state to block mode. We need this to cater for the case when a layer
572 // requires rotation in the current frame.
573 ALOGD_IF(isDebug(), "%s: padding round invoked to switch DMA state",
574 __FUNCTION__);
575 return false;
Saurabh Shah0ceeb6a2013-04-23 10:46:07 -0700576 }
Tatenda Chipeperekwadc8d7082014-11-04 16:41:50 -0800577
Saurabh Shahaa236822013-04-24 18:07:26 -0700578 return ret;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800579}
580
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800581void MDPCompNonSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect &crop,
582 hwc_rect &dst) {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800583 hwc_rect_t roi = ctx->listStats[mDpy].lRoi;
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800584 dst = getIntersection(dst, roi);
585 crop = dst;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800586}
587
588/* 1) Identify layers that are not visible or lying outside the updating ROI and
589 * drop them from composition.
590 * 2) If we have a scaling layer which needs cropping against generated
591 * ROI, reset ROI to full resolution. */
592bool MDPCompNonSplit::validateAndApplyROI(hwc_context_t *ctx,
593 hwc_display_contents_1_t* list) {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700594 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800595 hwc_rect_t visibleRect = ctx->listStats[mDpy].lRoi;
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800596
597 for(int i = numAppLayers - 1; i >= 0; i--){
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800598 if(!isValidRect(visibleRect)) {
599 mCurrentFrame.drop[i] = true;
600 mCurrentFrame.dropCount++;
Jeykumar Sankaran0b961452014-01-21 17:26:12 -0800601 continue;
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800602 }
603
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700604 const hwc_layer_1_t* layer = &list->hwLayers[i];
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700605 hwc_rect_t dstRect = layer->displayFrame;
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800606 hwc_rect_t res = getIntersection(visibleRect, dstRect);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700607
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700608 if(!isValidRect(res)) {
609 mCurrentFrame.drop[i] = true;
610 mCurrentFrame.dropCount++;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800611 } else {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700612 /* Reset frame ROI when any layer which needs scaling also needs ROI
613 * cropping */
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800614 if(!isSameRect(res, dstRect) && needsScaling (layer)) {
Arpita Banerjeed8965982013-11-08 17:27:33 -0800615 ALOGI("%s: Resetting ROI due to scaling", __FUNCTION__);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700616 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
617 mCurrentFrame.dropCount = 0;
618 return false;
619 }
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800620
Jeykumar Sankaran0b961452014-01-21 17:26:12 -0800621 /* deduct any opaque region from visibleRect */
radhakrishna4efbdd62014-11-03 13:19:27 +0530622 if (layer->blending == HWC_BLENDING_NONE &&
623 layer->planeAlpha == 0xFF)
Jeykumar Sankaran0b961452014-01-21 17:26:12 -0800624 visibleRect = deductRect(visibleRect, res);
625 }
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700626 }
627 return true;
628}
629
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800630/* Calculate ROI for the frame by accounting all the layer's dispalyFrame which
631 * are updating. If DirtyRegion is applicable, calculate it by accounting all
632 * the changing layer's dirtyRegion. */
633void MDPCompNonSplit::generateROI(hwc_context_t *ctx,
634 hwc_display_contents_1_t* list) {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700635 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800636 if(!canPartialUpdate(ctx, list))
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700637 return;
638
639 struct hwc_rect roi = (struct hwc_rect){0, 0, 0, 0};
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800640 hwc_rect fullFrame = (struct hwc_rect) {0, 0,(int)ctx->dpyAttr[mDpy].xres,
641 (int)ctx->dpyAttr[mDpy].yres};
642
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700643 for(int index = 0; index < numAppLayers; index++ ) {
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800644 hwc_layer_1_t* layer = &list->hwLayers[index];
645 if ((mCachedFrame.hnd[index] != layer->handle) ||
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800646 isYuvBuffer((private_handle_t *)layer->handle)) {
Jeykumar Sankaran455678c2014-05-30 10:22:38 -0700647 hwc_rect_t dst = layer->displayFrame;
648 hwc_rect_t updatingRect = dst;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800649
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800650#ifdef QCOM_BSP
Dileep Kumar Reddi7399d5c2014-12-31 18:01:19 +0530651 if(!needsScaling(layer) && !layer->transform &&
652 (!isYuvBuffer((private_handle_t *)layer->handle)))
Jeykumar Sankaran455678c2014-05-30 10:22:38 -0700653 {
654 hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
655 int x_off = dst.left - src.left;
656 int y_off = dst.top - src.top;
657 updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
658 }
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800659#endif
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800660
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800661 roi = getUnion(roi, updatingRect);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700662 }
663 }
664
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800665 /* No layer is updating. Still SF wants a refresh.*/
666 if(!isValidRect(roi))
667 return;
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800668
669 // Align ROI coordinates to panel restrictions
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800670 roi = getSanitizeROI(roi, fullFrame);
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800671
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800672 ctx->listStats[mDpy].lRoi = roi;
673 if(!validateAndApplyROI(ctx, list))
674 resetROI(ctx, mDpy);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700675
676 ALOGD_IF(isDebug(),"%s: generated ROI: [%d, %d, %d, %d]", __FUNCTION__,
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800677 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
678 ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom);
679}
680
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800681void MDPCompSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect &crop,
682 hwc_rect &dst) {
683 hwc_rect roi = getUnion(ctx->listStats[mDpy].lRoi,
684 ctx->listStats[mDpy].rRoi);
685 hwc_rect tmpDst = getIntersection(dst, roi);
686 if(!isSameRect(dst, tmpDst)) {
687 crop.left = crop.left + (tmpDst.left - dst.left);
688 crop.top = crop.top + (tmpDst.top - dst.top);
689 crop.right = crop.left + (tmpDst.right - tmpDst.left);
690 crop.bottom = crop.top + (tmpDst.bottom - tmpDst.top);
691 dst = tmpDst;
692 }
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800693}
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800694
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800695/* 1) Identify layers that are not visible or lying outside BOTH the updating
696 * ROI's and drop them from composition. If a layer is spanning across both
697 * the halves of the screen but needed by only ROI, the non-contributing
698 * half will not be programmed for MDP.
699 * 2) If we have a scaling layer which needs cropping against generated
700 * ROI, reset ROI to full resolution. */
701bool MDPCompSplit::validateAndApplyROI(hwc_context_t *ctx,
702 hwc_display_contents_1_t* list) {
703
704 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
705
706 hwc_rect_t visibleRectL = ctx->listStats[mDpy].lRoi;
707 hwc_rect_t visibleRectR = ctx->listStats[mDpy].rRoi;
708
709 for(int i = numAppLayers - 1; i >= 0; i--){
710 if(!isValidRect(visibleRectL) && !isValidRect(visibleRectR))
711 {
712 mCurrentFrame.drop[i] = true;
713 mCurrentFrame.dropCount++;
714 continue;
715 }
716
717 const hwc_layer_1_t* layer = &list->hwLayers[i];
718 hwc_rect_t dstRect = layer->displayFrame;
719
720 hwc_rect_t l_res = getIntersection(visibleRectL, dstRect);
721 hwc_rect_t r_res = getIntersection(visibleRectR, dstRect);
722 hwc_rect_t res = getUnion(l_res, r_res);
723
724 if(!isValidRect(l_res) && !isValidRect(r_res)) {
725 mCurrentFrame.drop[i] = true;
726 mCurrentFrame.dropCount++;
727 } else {
728 /* Reset frame ROI when any layer which needs scaling also needs ROI
729 * cropping */
730 if(!isSameRect(res, dstRect) && needsScaling (layer)) {
731 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
732 mCurrentFrame.dropCount = 0;
733 return false;
734 }
735
radhakrishna4efbdd62014-11-03 13:19:27 +0530736 if (layer->blending == HWC_BLENDING_NONE &&
737 layer->planeAlpha == 0xFF) {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800738 visibleRectL = deductRect(visibleRectL, l_res);
739 visibleRectR = deductRect(visibleRectR, r_res);
740 }
741 }
742 }
743 return true;
744}
745/* Calculate ROI for the frame by accounting all the layer's dispalyFrame which
746 * are updating. If DirtyRegion is applicable, calculate it by accounting all
747 * the changing layer's dirtyRegion. */
748void MDPCompSplit::generateROI(hwc_context_t *ctx,
749 hwc_display_contents_1_t* list) {
750 if(!canPartialUpdate(ctx, list))
751 return;
752
753 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
754 int lSplit = getLeftSplit(ctx, mDpy);
755
756 int hw_h = (int)ctx->dpyAttr[mDpy].yres;
757 int hw_w = (int)ctx->dpyAttr[mDpy].xres;
758
759 struct hwc_rect l_frame = (struct hwc_rect){0, 0, lSplit, hw_h};
760 struct hwc_rect r_frame = (struct hwc_rect){lSplit, 0, hw_w, hw_h};
761
762 struct hwc_rect l_roi = (struct hwc_rect){0, 0, 0, 0};
763 struct hwc_rect r_roi = (struct hwc_rect){0, 0, 0, 0};
764
765 for(int index = 0; index < numAppLayers; index++ ) {
766 hwc_layer_1_t* layer = &list->hwLayers[index];
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800767 private_handle_t *hnd = (private_handle_t *)layer->handle;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800768 if ((mCachedFrame.hnd[index] != layer->handle) ||
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800769 isYuvBuffer(hnd)) {
Jeykumar Sankaran71e597c2014-05-07 16:23:14 -0700770 hwc_rect_t dst = layer->displayFrame;
771 hwc_rect_t updatingRect = dst;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800772
773#ifdef QCOM_BSP
774 if(!needsScaling(layer) && !layer->transform)
Jeykumar Sankaran71e597c2014-05-07 16:23:14 -0700775 {
776 hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
777 int x_off = dst.left - src.left;
778 int y_off = dst.top - src.top;
779 updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
780 }
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800781#endif
782
783 hwc_rect_t l_dst = getIntersection(l_frame, updatingRect);
784 if(isValidRect(l_dst))
785 l_roi = getUnion(l_roi, l_dst);
786
787 hwc_rect_t r_dst = getIntersection(r_frame, updatingRect);
788 if(isValidRect(r_dst))
789 r_roi = getUnion(r_roi, r_dst);
790 }
791 }
792
Jeykumar Sankarana40a9342014-04-25 09:37:10 -0700793 /* For panels that cannot accept commands in both the interfaces, we cannot
794 * send two ROI's (for each half). We merge them into single ROI and split
795 * them across lSplit for MDP mixer use. The ROI's will be merged again
796 * finally before udpating the panel in the driver. */
797 if(qdutils::MDPVersion::getInstance().needsROIMerge()) {
798 hwc_rect_t temp_roi = getUnion(l_roi, r_roi);
799 l_roi = getIntersection(temp_roi, l_frame);
800 r_roi = getIntersection(temp_roi, r_frame);
801 }
802
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800803 /* No layer is updating. Still SF wants a refresh. */
804 if(!isValidRect(l_roi) && !isValidRect(r_roi))
805 return;
806
807 l_roi = getSanitizeROI(l_roi, l_frame);
808 r_roi = getSanitizeROI(r_roi, r_frame);
809
810 ctx->listStats[mDpy].lRoi = l_roi;
811 ctx->listStats[mDpy].rRoi = r_roi;
812
813 if(!validateAndApplyROI(ctx, list))
814 resetROI(ctx, mDpy);
815
816 ALOGD_IF(isDebug(),"%s: generated L_ROI: [%d, %d, %d, %d]"
817 "R_ROI: [%d, %d, %d, %d]", __FUNCTION__,
818 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
819 ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom,
820 ctx->listStats[mDpy].rRoi.left, ctx->listStats[mDpy].rRoi.top,
821 ctx->listStats[mDpy].rRoi.right, ctx->listStats[mDpy].rRoi.bottom);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700822}
823
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800824/* Checks for conditions where all the layers marked for MDP comp cannot be
825 * bypassed. On such conditions we try to bypass atleast YUV layers */
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800826bool MDPComp::tryFullFrame(hwc_context_t *ctx,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800827 hwc_display_contents_1_t* list){
828
Saurabh Shahaa236822013-04-24 18:07:26 -0700829 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800830
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -0700831 // Fall back to video only composition, if AIV video mode is enabled
832 if(ctx->listStats[mDpy].mAIVVideoMode) {
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -0700833 ALOGD_IF(isDebug(), "%s: AIV Video Mode enabled dpy %d",
834 __FUNCTION__, mDpy);
835 return false;
836 }
837
Praveena Pachipulusu47346c22014-12-04 11:06:41 +0530838 /* No Idle fall back if secure display or secure RGB layers are present
839 * or if there is only a single layer being composed */
840 if(sIdleFallBack && !ctx->listStats[mDpy].secureUI &&
841 !ctx->listStats[mDpy].secureRGBCount &&
842 (ctx->listStats[mDpy].numAppLayers > 1)) {
Saurabh Shah2d998a92013-05-14 17:55:58 -0700843 ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
844 return false;
845 }
846
Raj Kamalc0d34242015-03-17 20:53:14 +0530847 if(!mDpy && isSecondaryAnimating(ctx) &&
848 (isYuvPresent(ctx,HWC_DISPLAY_EXTERNAL) ||
849 isYuvPresent(ctx,HWC_DISPLAY_VIRTUAL)) ) {
850 ALOGD_IF(isDebug(),"%s: Display animation in progress",
851 __FUNCTION__);
852 return false;
853 }
854
Ramkumar Radhakrishnanf26fe9e2014-09-09 13:47:54 -0700855 // if secondary is configuring or Padding round, fall back to video only
856 // composition and release all assigned non VIG pipes from primary.
857 if(isSecondaryConfiguring(ctx)) {
858 ALOGD_IF( isDebug(),"%s: External Display connection is pending",
859 __FUNCTION__);
860 return false;
861 } else if(ctx->isPaddingRound) {
862 ALOGD_IF(isDebug(), "%s: padding round invoked for dpy %d",
863 __FUNCTION__,mDpy);
864 return false;
865 }
866
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -0500867 // No MDP composition for 3D
868 if(needs3DComposition(ctx, mDpy))
869 return false;
870
Tatenda Chipeperekwacb2a2432014-08-06 17:45:58 -0700871 // check for action safe flag and MDP scaling mode which requires scaling.
Ramkumar Radhakrishnan4af1ef02013-12-12 11:53:08 -0800872 if(ctx->dpyAttr[mDpy].mActionSafePresent
Tatenda Chipeperekwacb2a2432014-08-06 17:45:58 -0700873 || ctx->dpyAttr[mDpy].mMDPScalingMode) {
Ramkumar Radhakrishnan4af1ef02013-12-12 11:53:08 -0800874 ALOGD_IF(isDebug(), "%s: Scaling needed for this frame",__FUNCTION__);
875 return false;
876 }
877
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800878 for(int i = 0; i < numAppLayers; ++i) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800879 hwc_layer_1_t* layer = &list->hwLayers[i];
880 private_handle_t *hnd = (private_handle_t *)layer->handle;
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -0800881
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800882 if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700883 if(!canUseRotator(ctx, mDpy)) {
884 ALOGD_IF(isDebug(), "%s: Can't use rotator for dpy %d",
885 __FUNCTION__, mDpy);
Amara Venkata Mastan Manoj Kumar9d373c02013-08-20 14:30:09 -0700886 return false;
887 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800888 }
Prabhanjan Kandula9fb032a2013-06-18 17:37:22 +0530889
890 //For 8x26 with panel width>1k, if RGB layer needs HFLIP fail mdp comp
891 // may not need it if Gfx pre-rotation can handle all flips & rotations
Saurabh Shahcad57772014-12-01 14:19:51 -0800892 MDPVersion& mdpHw = MDPVersion::getInstance();
Sushil Chauhanfda00fc2014-03-20 11:08:41 -0700893 int transform = (layer->flags & HWC_COLOR_FILL) ? 0 : layer->transform;
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530894 if( mdpHw.is8x26() && (ctx->dpyAttr[mDpy].xres > 1024) &&
895 (transform & HWC_TRANSFORM_FLIP_H) && (!isYuvBuffer(hnd)))
896 return false;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800897 }
Saurabh Shahaa236822013-04-24 18:07:26 -0700898
Saurabh Shaha9da08f2013-07-03 13:27:53 -0700899 if(ctx->mAD->isDoable()) {
900 return false;
901 }
902
Saurabh Shahaa236822013-04-24 18:07:26 -0700903 //If all above hard conditions are met we can do full or partial MDP comp.
904 bool ret = false;
905 if(fullMDPComp(ctx, list)) {
906 ret = true;
Sushil Chauhandefd3522014-05-13 18:17:12 -0700907 } else if(fullMDPCompWithPTOR(ctx, list)) {
908 ret = true;
Jeykumar Sankaran24c199d2013-05-24 09:40:36 -0700909 } else if(partialMDPComp(ctx, list)) {
Saurabh Shahaa236822013-04-24 18:07:26 -0700910 ret = true;
911 }
Prabhanjan Kandula21918db2013-11-26 15:51:58 +0530912
Saurabh Shahaa236822013-04-24 18:07:26 -0700913 return ret;
914}
915
916bool MDPComp::fullMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -0700917
918 if(sSimulationFlags & MDPCOMP_AVOID_FULL_MDP)
919 return false;
920
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700921 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
922 for(int i = 0; i < numAppLayers; i++) {
923 hwc_layer_1_t* layer = &list->hwLayers[i];
Jeykumar Sankaran880da832014-04-18 10:22:35 -0700924 if(not mCurrentFrame.drop[i] and
925 not isSupportedForMDPComp(ctx, layer)) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700926 ALOGD_IF(isDebug(), "%s: Unsupported layer in list",__FUNCTION__);
927 return false;
928 }
929 }
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800930
Raj Kamalb5f0b4a2015-04-08 15:10:37 +0530931 if(!mDpy && isSecondaryConnected(ctx) &&
932 (qdutils::MDPVersion::getInstance().is8x16() ||
933 qdutils::MDPVersion::getInstance().is8x26() ||
934 qdutils::MDPVersion::getInstance().is8x39()) &&
935 isYuvPresent(ctx, HWC_DISPLAY_VIRTUAL)) {
936 ALOGD_IF(isDebug(), "%s: YUV layer present on secondary", __FUNCTION__);
937 return false;
938 }
939
Saurabh Shahaa236822013-04-24 18:07:26 -0700940 mCurrentFrame.fbCount = 0;
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700941 memcpy(&mCurrentFrame.isFBComposed, &mCurrentFrame.drop,
942 sizeof(mCurrentFrame.isFBComposed));
943 mCurrentFrame.mdpCount = mCurrentFrame.layerCount - mCurrentFrame.fbCount -
944 mCurrentFrame.dropCount;
Saurabh Shahaa236822013-04-24 18:07:26 -0700945
Raj Kamal389d6e32014-08-04 14:43:24 +0530946 if(sEnableYUVsplit){
Saurabh Shah3d4b8042013-12-10 15:19:17 -0800947 adjustForSourceSplit(ctx, list);
radhakrishnac9a67412013-09-25 17:40:42 +0530948 }
949
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800950 if(!postHeuristicsHandling(ctx, list)) {
951 ALOGD_IF(isDebug(), "post heuristic handling failed");
952 reset(ctx);
Saurabh Shah8c5c8522013-08-29 17:32:49 -0700953 return false;
954 }
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -0700955 ALOGD_IF(sSimulationFlags,"%s: FULL_MDP_COMP SUCCEEDED",
956 __FUNCTION__);
Saurabh Shahaa236822013-04-24 18:07:26 -0700957 return true;
958}
959
Sushil Chauhandefd3522014-05-13 18:17:12 -0700960/* Full MDP Composition with Peripheral Tiny Overlap Removal.
961 * MDP bandwidth limitations can be avoided, if the overlap region
962 * covered by the smallest layer at a higher z-order, gets composed
963 * by Copybit on a render buffer, which can be queued to MDP.
964 */
965bool MDPComp::fullMDPCompWithPTOR(hwc_context_t *ctx,
966 hwc_display_contents_1_t* list) {
967
968 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Arun Kumar K.R00b84792015-03-27 11:28:36 -0700969 // PTOR does not qualify when there are layers dropped, but if
970 // dropped layer is only a cursor, PTOR could qualify
971 const int numNonCursorLayers = numAppLayers - mCurrentFrame.dropCount;
Sushil Chauhandefd3522014-05-13 18:17:12 -0700972 const int stagesForMDP = min(sMaxPipesPerMixer,
973 ctx->mOverlay->availablePipes(mDpy, Overlay::MIXER_DEFAULT));
974
975 // Hard checks where we cannot use this mode
Sushil Chauhanbfc2de02014-07-24 11:52:58 -0700976 if (mDpy || !ctx->mCopyBit[mDpy]) {
Sushil Chauhandefd3522014-05-13 18:17:12 -0700977 ALOGD_IF(isDebug(), "%s: Feature not supported!", __FUNCTION__);
978 return false;
979 }
980
Arun Kumar K.R00b84792015-03-27 11:28:36 -0700981 // Frame level checks - consider PTOR in case of dropCount only if the cursor
982 // layer is dropped, otherwise bail out of PTOR
Sushil Chauhandefd3522014-05-13 18:17:12 -0700983 if ((numAppLayers > stagesForMDP) || isSkipPresent(ctx, mDpy) ||
Arun Kumar K.R00b84792015-03-27 11:28:36 -0700984 isYuvPresent(ctx, mDpy) || isSecurePresent(ctx, mDpy) ||
985 (mCurrentFrame.dropCount - (int)isCursorPresent(ctx, mDpy))) {
Sushil Chauhandefd3522014-05-13 18:17:12 -0700986 ALOGD_IF(isDebug(), "%s: Frame not supported!", __FUNCTION__);
987 return false;
988 }
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -0700989 // MDP comp checks
990 for(int i = 0; i < numAppLayers; i++) {
Sushil Chauhandefd3522014-05-13 18:17:12 -0700991 hwc_layer_1_t* layer = &list->hwLayers[i];
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -0700992 if(not isSupportedForMDPComp(ctx, layer)) {
993 ALOGD_IF(isDebug(), "%s: Unsupported layer in list",__FUNCTION__);
994 return false;
Sushil Chauhandefd3522014-05-13 18:17:12 -0700995 }
996 }
997
Raj Kamalb5f0b4a2015-04-08 15:10:37 +0530998 if(!mDpy && isSecondaryConnected(ctx) &&
999 (qdutils::MDPVersion::getInstance().is8x16() ||
1000 qdutils::MDPVersion::getInstance().is8x26() ||
1001 qdutils::MDPVersion::getInstance().is8x39()) &&
1002 isYuvPresent(ctx, HWC_DISPLAY_VIRTUAL)) {
1003 ALOGD_IF(isDebug(), "%s: YUV layer present on secondary", __FUNCTION__);
1004 return false;
1005 }
1006
Sushil Chauhandefd3522014-05-13 18:17:12 -07001007 /* We cannot use this composition mode, if:
1008 1. A below layer needs scaling.
1009 2. Overlap is not peripheral to display.
1010 3. Overlap or a below layer has 90 degree transform.
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001011 4. Overlap area > (1/3 * FrameBuffer) area, based on Perf inputs.
Sushil Chauhandefd3522014-05-13 18:17:12 -07001012 */
1013
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001014 int minLayerIndex[MAX_PTOR_LAYERS] = { -1, -1};
1015 hwc_rect_t overlapRect[MAX_PTOR_LAYERS];
1016 memset(overlapRect, 0, sizeof(overlapRect));
1017 int layerPixelCount, minPixelCount = 0;
1018 int numPTORLayersFound = 0;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001019 for (int i = numNonCursorLayers - 1; (i >= 0 &&
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001020 numPTORLayersFound < MAX_PTOR_LAYERS); i--) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001021 hwc_layer_1_t* layer = &list->hwLayers[i];
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001022 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
Sushil Chauhandefd3522014-05-13 18:17:12 -07001023 hwc_rect_t dispFrame = layer->displayFrame;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001024 layerPixelCount = (crop.right - crop.left) * (crop.bottom - crop.top);
1025 // PTOR layer should be peripheral and cannot have transform
1026 if (!isPeripheral(dispFrame, ctx->mViewFrame[mDpy]) ||
1027 has90Transform(layer)) {
1028 continue;
1029 }
1030 if((3 * (layerPixelCount + minPixelCount)) >
1031 ((int)ctx->dpyAttr[mDpy].xres * (int)ctx->dpyAttr[mDpy].yres)) {
1032 // Overlap area > (1/3 * FrameBuffer) area, based on Perf inputs.
1033 continue;
1034 }
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001035 bool found = false;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001036 for (int j = i-1; j >= 0; j--) {
1037 // Check if the layers below this layer qualifies for PTOR comp
1038 hwc_layer_1_t* layer = &list->hwLayers[j];
1039 hwc_rect_t disFrame = layer->displayFrame;
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001040 // Layer below PTOR is intersecting and has 90 degree transform or
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001041 // needs scaling cannot be supported.
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001042 if (isValidRect(getIntersection(dispFrame, disFrame))) {
1043 if (has90Transform(layer) || needsScaling(layer)) {
1044 found = false;
1045 break;
1046 }
1047 found = true;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001048 }
1049 }
1050 // Store the minLayer Index
1051 if(found) {
1052 minLayerIndex[numPTORLayersFound] = i;
1053 overlapRect[numPTORLayersFound] = list->hwLayers[i].displayFrame;
1054 minPixelCount += layerPixelCount;
1055 numPTORLayersFound++;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001056 }
1057 }
1058
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001059 // No overlap layers
1060 if (!numPTORLayersFound)
1061 return false;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001062
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001063 // Store the displayFrame and the sourceCrops of the layers
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001064 hwc_rect_t displayFrame[numNonCursorLayers];
1065 hwc_rect_t sourceCrop[numNonCursorLayers];
1066 for(int i = 0; i < numNonCursorLayers; i++) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001067 hwc_layer_1_t* layer = &list->hwLayers[i];
1068 displayFrame[i] = layer->displayFrame;
1069 sourceCrop[i] = integerizeSourceCrop(layer->sourceCropf);
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001070 }
Sushil Chauhandefd3522014-05-13 18:17:12 -07001071
Prabhanjan Kandula9889a202014-09-04 21:50:35 +05301072 /**
1073 * It's possible that 2 PTOR layers might have overlapping.
1074 * In such case, remove the intersection(again if peripheral)
1075 * from the lower PTOR layer to avoid overlapping.
1076 * If intersection is not on peripheral then compromise
1077 * by reducing number of PTOR layers.
1078 **/
1079 hwc_rect_t commonRect = getIntersection(overlapRect[0], overlapRect[1]);
1080 if(isValidRect(commonRect)) {
1081 overlapRect[1] = deductRect(overlapRect[1], commonRect);
1082 list->hwLayers[minLayerIndex[1]].displayFrame = overlapRect[1];
1083 }
1084
1085 ctx->mPtorInfo.count = numPTORLayersFound;
1086 for(int i = 0; i < MAX_PTOR_LAYERS; i++) {
1087 ctx->mPtorInfo.layerIndex[i] = minLayerIndex[i];
1088 }
1089
1090 if (!ctx->mCopyBit[mDpy]->prepareOverlap(ctx, list)) {
1091 // reset PTOR
1092 ctx->mPtorInfo.count = 0;
1093 if(isValidRect(commonRect)) {
1094 // If PTORs are intersecting restore displayframe of PTOR[1]
1095 // before returning, as we have modified it above.
1096 list->hwLayers[minLayerIndex[1]].displayFrame =
1097 displayFrame[minLayerIndex[1]];
1098 }
1099 return false;
1100 }
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001101 private_handle_t *renderBuf = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
1102 Whf layerWhf[numPTORLayersFound]; // To store w,h,f of PTOR layers
1103
Xu Yangcda012c2014-07-30 21:57:21 +08001104 // Store the blending mode, planeAlpha, and transform of PTOR layers
1105 int32_t blending[numPTORLayersFound];
1106 uint8_t planeAlpha[numPTORLayersFound];
1107 uint32_t transform[numPTORLayersFound];
1108
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001109 for(int j = 0; j < numPTORLayersFound; j++) {
1110 int index = ctx->mPtorInfo.layerIndex[j];
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001111
1112 // Update src crop of PTOR layer
1113 hwc_layer_1_t* layer = &list->hwLayers[index];
1114 layer->sourceCropf.left = (float)ctx->mPtorInfo.displayFrame[j].left;
1115 layer->sourceCropf.top = (float)ctx->mPtorInfo.displayFrame[j].top;
1116 layer->sourceCropf.right = (float)ctx->mPtorInfo.displayFrame[j].right;
1117 layer->sourceCropf.bottom =(float)ctx->mPtorInfo.displayFrame[j].bottom;
1118
1119 // Store & update w, h, format of PTOR layer
1120 private_handle_t *hnd = (private_handle_t *)layer->handle;
1121 Whf whf(hnd->width, hnd->height, hnd->format, hnd->size);
1122 layerWhf[j] = whf;
1123 hnd->width = renderBuf->width;
1124 hnd->height = renderBuf->height;
1125 hnd->format = renderBuf->format;
1126
Xu Yangcda012c2014-07-30 21:57:21 +08001127 // Store & update blending mode, planeAlpha and transform of PTOR layer
1128 blending[j] = layer->blending;
1129 planeAlpha[j] = layer->planeAlpha;
1130 transform[j] = layer->transform;
1131 layer->blending = HWC_BLENDING_NONE;
1132 layer->planeAlpha = 0xFF;
1133 layer->transform = 0;
1134
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001135 // Remove overlap from crop & displayFrame of below layers
1136 for (int i = 0; i < index && index !=-1; i++) {
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001137 layer = &list->hwLayers[i];
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001138 if(!isValidRect(getIntersection(layer->displayFrame,
1139 overlapRect[j]))) {
1140 continue;
1141 }
1142 // Update layer attributes
1143 hwc_rect_t srcCrop = integerizeSourceCrop(layer->sourceCropf);
1144 hwc_rect_t destRect = deductRect(layer->displayFrame,
Dileep Kumar Reddi72058b82014-11-11 16:03:03 +05301145 getIntersection(layer->displayFrame, overlapRect[j]));
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001146 qhwc::calculate_crop_rects(srcCrop, layer->displayFrame, destRect,
1147 layer->transform);
1148 layer->sourceCropf.left = (float)srcCrop.left;
1149 layer->sourceCropf.top = (float)srcCrop.top;
1150 layer->sourceCropf.right = (float)srcCrop.right;
1151 layer->sourceCropf.bottom = (float)srcCrop.bottom;
1152 }
Sushil Chauhandefd3522014-05-13 18:17:12 -07001153 }
1154
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001155 mCurrentFrame.mdpCount = numNonCursorLayers;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001156 mCurrentFrame.fbCount = 0;
1157 mCurrentFrame.fbZ = -1;
1158
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001159 for (int j = 0; j < numNonCursorLayers; j++) {
Dileep Kumar Reddi72058b82014-11-11 16:03:03 +05301160 if(isValidRect(list->hwLayers[j].displayFrame)) {
1161 mCurrentFrame.isFBComposed[j] = false;
1162 } else {
1163 mCurrentFrame.mdpCount--;
1164 mCurrentFrame.drop[j] = true;
1165 }
1166 }
Sushil Chauhandefd3522014-05-13 18:17:12 -07001167
1168 bool result = postHeuristicsHandling(ctx, list);
1169
1170 // Restore layer attributes
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001171 for(int i = 0; i < numNonCursorLayers; i++) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001172 hwc_layer_1_t* layer = &list->hwLayers[i];
1173 layer->displayFrame = displayFrame[i];
1174 layer->sourceCropf.left = (float)sourceCrop[i].left;
1175 layer->sourceCropf.top = (float)sourceCrop[i].top;
1176 layer->sourceCropf.right = (float)sourceCrop[i].right;
1177 layer->sourceCropf.bottom = (float)sourceCrop[i].bottom;
1178 }
1179
Xu Yangcda012c2014-07-30 21:57:21 +08001180 // Restore w,h,f, blending attributes, and transform of PTOR layers
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001181 for (int i = 0; i < numPTORLayersFound; i++) {
1182 int idx = ctx->mPtorInfo.layerIndex[i];
Xu Yangcda012c2014-07-30 21:57:21 +08001183 hwc_layer_1_t* layer = &list->hwLayers[idx];
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001184 private_handle_t *hnd = (private_handle_t *)list->hwLayers[idx].handle;
1185 hnd->width = layerWhf[i].w;
1186 hnd->height = layerWhf[i].h;
1187 hnd->format = layerWhf[i].format;
Xu Yangcda012c2014-07-30 21:57:21 +08001188 layer->blending = blending[i];
1189 layer->planeAlpha = planeAlpha[i];
1190 layer->transform = transform[i];
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001191 }
1192
Sushil Chauhandefd3522014-05-13 18:17:12 -07001193 if (!result) {
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001194 // reset PTOR
1195 ctx->mPtorInfo.count = 0;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001196 reset(ctx);
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001197 } else {
1198 ALOGD_IF(isDebug(), "%s: PTOR Indexes: %d and %d", __FUNCTION__,
1199 ctx->mPtorInfo.layerIndex[0], ctx->mPtorInfo.layerIndex[1]);
Sushil Chauhandefd3522014-05-13 18:17:12 -07001200 }
1201
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001202 ALOGD_IF(isDebug(), "%s: Postheuristics %s!", __FUNCTION__,
1203 (result ? "successful" : "failed"));
Sushil Chauhandefd3522014-05-13 18:17:12 -07001204 return result;
1205}
1206
Saurabh Shahaa236822013-04-24 18:07:26 -07001207bool MDPComp::partialMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list)
1208{
radhakrishnac3198ff2015-03-10 17:10:02 +05301209 if(!sEnableMixedMode || !isAlphaPresentinFB(ctx, mDpy)) {
1210 //Mixed mode is disabled/can't be used. No need to even try caching.
Jeykumar Sankaran24c199d2013-05-24 09:40:36 -07001211 return false;
1212 }
1213
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001214 bool ret = false;
Raj Kamal1179d9c2014-10-28 15:31:35 +05301215 if(isSkipPresent(ctx, mDpy) or list->flags & HWC_GEOMETRY_CHANGED) {
1216 //Try load based first
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001217 ret = loadBasedComp(ctx, list) or
Saurabh Shahf2de00f2013-12-11 17:52:53 -08001218 cacheBasedComp(ctx, list);
1219 } else {
1220 ret = cacheBasedComp(ctx, list) or
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001221 loadBasedComp(ctx, list);
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001222 }
1223
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001224 return ret;
1225}
1226
1227bool MDPComp::cacheBasedComp(hwc_context_t *ctx,
1228 hwc_display_contents_1_t* list) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001229 if(sSimulationFlags & MDPCOMP_AVOID_CACHE_MDP)
1230 return false;
1231
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001232 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shahaa236822013-04-24 18:07:26 -07001233 mCurrentFrame.reset(numAppLayers);
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001234 updateLayerCache(ctx, list, mCurrentFrame);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001235
1236 //If an MDP marked layer is unsupported cannot do partial MDP Comp
1237 for(int i = 0; i < numAppLayers; i++) {
1238 if(!mCurrentFrame.isFBComposed[i]) {
1239 hwc_layer_1_t* layer = &list->hwLayers[i];
1240 if(not isSupportedForMDPComp(ctx, layer)) {
1241 ALOGD_IF(isDebug(), "%s: Unsupported layer in list",
1242 __FUNCTION__);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001243 reset(ctx);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001244 return false;
1245 }
1246 }
1247 }
1248
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001249 updateYUV(ctx, list, false /*secure only*/, mCurrentFrame);
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001250 /* mark secure RGB layers for MDP comp */
1251 updateSecureRGB(ctx, list);
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301252 bool ret = markLayersForCaching(ctx, list); //sets up fbZ also
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001253 if(!ret) {
1254 ALOGD_IF(isDebug(),"%s: batching failed, dpy %d",__FUNCTION__, mDpy);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001255 reset(ctx);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001256 return false;
1257 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001258
1259 int mdpCount = mCurrentFrame.mdpCount;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001260
Raj Kamal389d6e32014-08-04 14:43:24 +05301261 if(sEnableYUVsplit){
Saurabh Shah3d4b8042013-12-10 15:19:17 -08001262 adjustForSourceSplit(ctx, list);
radhakrishnac9a67412013-09-25 17:40:42 +05301263 }
1264
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001265 if(!postHeuristicsHandling(ctx, list)) {
1266 ALOGD_IF(isDebug(), "post heuristic handling failed");
1267 reset(ctx);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07001268 return false;
1269 }
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001270 ALOGD_IF(sSimulationFlags,"%s: CACHE_MDP_COMP SUCCEEDED",
1271 __FUNCTION__);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07001272
Saurabh Shahaa236822013-04-24 18:07:26 -07001273 return true;
1274}
1275
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001276bool MDPComp::loadBasedComp(hwc_context_t *ctx,
Saurabh Shahb772ae32013-11-18 15:40:02 -08001277 hwc_display_contents_1_t* list) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001278 if(sSimulationFlags & MDPCOMP_AVOID_LOAD_MDP)
1279 return false;
1280
Arun Kumar K.R2aa44c62014-01-21 23:08:28 -08001281 if(not isLoadBasedCompDoable(ctx)) {
Saurabh Shahf2de00f2013-12-11 17:52:53 -08001282 return false;
1283 }
1284
Saurabh Shahb772ae32013-11-18 15:40:02 -08001285 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001286 const int numNonDroppedLayers = numAppLayers - mCurrentFrame.dropCount;
1287 const int stagesForMDP = min(sMaxPipesPerMixer,
1288 ctx->mOverlay->availablePipes(mDpy, Overlay::MIXER_DEFAULT));
Saurabh Shahf2de00f2013-12-11 17:52:53 -08001289
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001290 int mdpBatchSize = stagesForMDP - 1; //1 stage for FB
1291 int fbBatchSize = numNonDroppedLayers - mdpBatchSize;
1292 int lastMDPSupportedIndex = numAppLayers;
1293 int dropCount = 0;
Saurabh Shahb772ae32013-11-18 15:40:02 -08001294
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001295 //Find the minimum MDP batch size
1296 for(int i = 0; i < numAppLayers;i++) {
1297 if(mCurrentFrame.drop[i]) {
1298 dropCount++;
Jeykumar Sankaran846e2792014-01-23 21:59:58 -08001299 continue;
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001300 }
1301 hwc_layer_1_t* layer = &list->hwLayers[i];
1302 if(not isSupportedForMDPComp(ctx, layer)) {
1303 lastMDPSupportedIndex = i;
1304 mdpBatchSize = min(i - dropCount, stagesForMDP - 1);
1305 fbBatchSize = numNonDroppedLayers - mdpBatchSize;
Jeykumar Sankaran846e2792014-01-23 21:59:58 -08001306 break;
Saurabh Shahb772ae32013-11-18 15:40:02 -08001307 }
Saurabh Shahb772ae32013-11-18 15:40:02 -08001308 }
1309
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001310 ALOGD_IF(isDebug(), "%s:Before optimizing fbBatch, mdpbatch %d, fbbatch %d "
1311 "dropped %d", __FUNCTION__, mdpBatchSize, fbBatchSize,
1312 mCurrentFrame.dropCount);
1313
1314 //Start at a point where the fb batch should at least have 2 layers, for
1315 //this mode to be justified.
1316 while(fbBatchSize < 2) {
1317 ++fbBatchSize;
1318 --mdpBatchSize;
Jeykumar Sankaran846e2792014-01-23 21:59:58 -08001319 }
Saurabh Shahb772ae32013-11-18 15:40:02 -08001320
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001321 //If there are no layers for MDP, this mode doesnt make sense.
1322 if(mdpBatchSize < 1) {
1323 ALOGD_IF(isDebug(), "%s: No MDP layers after optimizing for fbBatch",
1324 __FUNCTION__);
Saurabh Shahb772ae32013-11-18 15:40:02 -08001325 return false;
1326 }
1327
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001328 mCurrentFrame.reset(numAppLayers);
1329
1330 //Try with successively smaller mdp batch sizes until we succeed or reach 1
1331 while(mdpBatchSize > 0) {
1332 //Mark layers for MDP comp
1333 int mdpBatchLeft = mdpBatchSize;
1334 for(int i = 0; i < lastMDPSupportedIndex and mdpBatchLeft; i++) {
1335 if(mCurrentFrame.drop[i]) {
1336 continue;
1337 }
1338 mCurrentFrame.isFBComposed[i] = false;
1339 --mdpBatchLeft;
1340 }
1341
1342 mCurrentFrame.fbZ = mdpBatchSize;
1343 mCurrentFrame.fbCount = fbBatchSize;
1344 mCurrentFrame.mdpCount = mdpBatchSize;
1345
1346 ALOGD_IF(isDebug(), "%s:Trying with: mdpbatch %d fbbatch %d dropped %d",
1347 __FUNCTION__, mdpBatchSize, fbBatchSize,
1348 mCurrentFrame.dropCount);
1349
1350 if(postHeuristicsHandling(ctx, list)) {
1351 ALOGD_IF(isDebug(), "%s: Postheuristics handling succeeded",
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001352 __FUNCTION__);
1353 ALOGD_IF(sSimulationFlags,"%s: LOAD_MDP_COMP SUCCEEDED",
1354 __FUNCTION__);
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001355 return true;
1356 }
1357
1358 reset(ctx);
1359 --mdpBatchSize;
1360 ++fbBatchSize;
1361 }
1362
1363 return false;
Saurabh Shahb772ae32013-11-18 15:40:02 -08001364}
1365
Arun Kumar K.R2aa44c62014-01-21 23:08:28 -08001366bool MDPComp::isLoadBasedCompDoable(hwc_context_t *ctx) {
Prabhanjan Kandula3dbbd882013-12-11 14:43:46 +05301367 if(mDpy or isSecurePresent(ctx, mDpy) or
1368 isYuvPresent(ctx, mDpy)) {
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001369 return false;
1370 }
1371 return true;
1372}
1373
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001374bool MDPComp::canPartialUpdate(hwc_context_t *ctx,
1375 hwc_display_contents_1_t* list){
1376 if(!qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() ||
1377 isSkipPresent(ctx, mDpy) || (list->flags & HWC_GEOMETRY_CHANGED) ||
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001378 isCursorPresent(ctx, mDpy) || !sIsPartialUpdateActive || mDpy) {
1379 // On Async position update, the ROI becomes invalid, hence disable PU
1380 // when cursor is present
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001381 return false;
1382 }
Jeykumar Sankaran4dd10ab2014-07-02 12:23:09 -07001383 if(ctx->listStats[mDpy].secureUI)
1384 return false;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001385 return true;
1386}
1387
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001388bool MDPComp::tryVideoOnly(hwc_context_t *ctx,
1389 hwc_display_contents_1_t* list) {
1390 const bool secureOnly = true;
1391 return videoOnlyComp(ctx, list, not secureOnly) or
1392 videoOnlyComp(ctx, list, secureOnly);
1393}
1394
1395bool MDPComp::videoOnlyComp(hwc_context_t *ctx,
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001396 hwc_display_contents_1_t* list, bool secureOnly) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001397 if(sSimulationFlags & MDPCOMP_AVOID_VIDEO_ONLY)
1398 return false;
Praveena Pachipulusu47346c22014-12-04 11:06:41 +05301399
Saurabh Shahaa236822013-04-24 18:07:26 -07001400 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Praveena Pachipulusu47346c22014-12-04 11:06:41 +05301401 if(!isSecurePresent(ctx, mDpy)) {
1402 /* Bail out if we are processing only secured video layers
1403 * and we dont have any */
1404 if(secureOnly) {
1405 ALOGD_IF(isDebug(),"%s: No Secure Video Layers", __FUNCTION__);
1406 return false;
1407 }
1408 /* No Idle fall back for secure video layers and if there is only
1409 * single layer being composed. */
1410 if(sIdleFallBack && (ctx->listStats[mDpy].numAppLayers > 1)) {
1411 ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
1412 return false;
1413 }
1414 }
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001415
Saurabh Shahaa236822013-04-24 18:07:26 -07001416 mCurrentFrame.reset(numAppLayers);
Jeykumar Sankaraneb3a5e22014-04-08 16:07:55 -07001417 mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001418 updateYUV(ctx, list, secureOnly, mCurrentFrame);
Saurabh Shah4fdde762013-04-30 18:47:33 -07001419 int mdpCount = mCurrentFrame.mdpCount;
Saurabh Shahaa236822013-04-24 18:07:26 -07001420
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001421 if(!isYuvPresent(ctx, mDpy) or (mdpCount == 0)) {
1422 reset(ctx);
Saurabh Shahaa236822013-04-24 18:07:26 -07001423 return false;
1424 }
1425
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001426 if(mCurrentFrame.fbCount)
1427 mCurrentFrame.fbZ = mCurrentFrame.mdpCount;
Saurabh Shah4fdde762013-04-30 18:47:33 -07001428
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05001429 if(sEnableYUVsplit || needs3DComposition(ctx, mDpy)){
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001430 adjustForSourceSplit(ctx, list);
1431 }
1432
1433 if(!postHeuristicsHandling(ctx, list)) {
1434 ALOGD_IF(isDebug(), "post heuristic handling failed");
Justin Philip37ab9a82015-01-06 11:55:12 +05301435 if(errno == ENOBUFS) {
1436 ALOGD_IF(isDebug(), "SMP Allocation failed");
1437 //On SMP allocation failure in video only comp add padding round
1438 ctx->isPaddingRound = true;
1439 }
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001440 reset(ctx);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07001441 return false;
1442 }
1443
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001444 ALOGD_IF(sSimulationFlags,"%s: VIDEO_ONLY_COMP SUCCEEDED",
1445 __FUNCTION__);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001446 return true;
1447}
1448
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001449/* if tryFullFrame fails, try to push all video and secure RGB layers to MDP */
1450bool MDPComp::tryMDPOnlyLayers(hwc_context_t *ctx,
1451 hwc_display_contents_1_t* list) {
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001452 // Fall back to video only composition, if AIV video mode is enabled
1453 if(ctx->listStats[mDpy].mAIVVideoMode) {
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07001454 ALOGD_IF(isDebug(), "%s: AIV Video Mode enabled dpy %d",
1455 __FUNCTION__, mDpy);
1456 return false;
1457 }
1458
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05001459 // No MDP composition for 3D
1460 if(needs3DComposition(ctx,mDpy))
1461 return false;
1462
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001463 const bool secureOnly = true;
1464 return mdpOnlyLayersComp(ctx, list, not secureOnly) or
1465 mdpOnlyLayersComp(ctx, list, secureOnly);
1466
1467}
1468
1469bool MDPComp::mdpOnlyLayersComp(hwc_context_t *ctx,
1470 hwc_display_contents_1_t* list, bool secureOnly) {
1471
1472 if(sSimulationFlags & MDPCOMP_AVOID_MDP_ONLY_LAYERS)
1473 return false;
1474
Praveena Pachipulusu47346c22014-12-04 11:06:41 +05301475 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
1476 if(!isSecurePresent(ctx, mDpy) && !ctx->listStats[mDpy].secureUI) {
1477 /* Bail out if we are processing only secured video/ui layers
1478 * and we dont have any */
1479 if(secureOnly) {
1480 ALOGD_IF(isDebug(), "%s: No secure video/ui layers");
1481 return false;
1482 }
1483 /* No Idle fall back for secure video/ui layers and if there is only
1484 * single layer being composed. */
1485 if(sIdleFallBack && (ctx->listStats[mDpy].numAppLayers > 1)) {
1486 ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
1487 return false;
1488 }
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001489 }
1490
Tatenda Chipeperekwa95675a72014-12-15 17:06:43 -08001491 /* Bail out if we dont have any secure RGB layers */
1492 if (!ctx->listStats[mDpy].secureRGBCount) {
1493 reset(ctx);
1494 return false;
1495 }
1496
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001497 mCurrentFrame.reset(numAppLayers);
1498 mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
1499
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001500 updateYUV(ctx, list, secureOnly, mCurrentFrame);
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001501 /* mark secure RGB layers for MDP comp */
1502 updateSecureRGB(ctx, list);
1503
1504 if(mCurrentFrame.mdpCount == 0) {
1505 reset(ctx);
1506 return false;
1507 }
1508
1509 /* find the maximum batch of layers to be marked for framebuffer */
1510 bool ret = markLayersForCaching(ctx, list); //sets up fbZ also
1511 if(!ret) {
1512 ALOGD_IF(isDebug(),"%s: batching failed, dpy %d",__FUNCTION__, mDpy);
1513 reset(ctx);
1514 return false;
1515 }
1516
1517 if(sEnableYUVsplit){
1518 adjustForSourceSplit(ctx, list);
1519 }
1520
1521 if(!postHeuristicsHandling(ctx, list)) {
1522 ALOGD_IF(isDebug(), "post heuristic handling failed");
1523 reset(ctx);
1524 return false;
1525 }
1526
1527 ALOGD_IF(sSimulationFlags,"%s: MDP_ONLY_LAYERS_COMP SUCCEEDED",
1528 __FUNCTION__);
1529 return true;
1530}
1531
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001532/* Checks for conditions where YUV layers cannot be bypassed */
1533bool MDPComp::isYUVDoable(hwc_context_t* ctx, hwc_layer_1_t* layer) {
Ramkumar Radhakrishnana70981a2013-08-28 11:33:53 -07001534 if(isSkipLayer(layer)) {
Saurabh Shahe2474082013-05-15 16:32:13 -07001535 ALOGD_IF(isDebug(), "%s: Video marked SKIP dpy %d", __FUNCTION__, mDpy);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001536 return false;
1537 }
1538
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08001539 if(has90Transform(layer) && !canUseRotator(ctx, mDpy)) {
Amara Venkata Mastan Manoj Kumar9d373c02013-08-20 14:30:09 -07001540 ALOGD_IF(isDebug(), "%s: no free DMA pipe",__FUNCTION__);
1541 return false;
1542 }
1543
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001544 if(isSecuring(ctx, layer)) {
1545 ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
1546 return false;
1547 }
1548
Saurabh Shah4fdde762013-04-30 18:47:33 -07001549 if(!isValidDimension(ctx, layer)) {
1550 ALOGD_IF(isDebug(), "%s: Buffer is of invalid width",
1551 __FUNCTION__);
1552 return false;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001553 }
Saurabh Shah4fdde762013-04-30 18:47:33 -07001554
Naseer Ahmeddc61a972013-07-10 17:50:54 -04001555 if(layer->planeAlpha < 0xFF) {
1556 ALOGD_IF(isDebug(), "%s: Cannot handle YUV layer with plane alpha\
1557 in video only mode",
1558 __FUNCTION__);
1559 return false;
1560 }
1561
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001562 return true;
1563}
1564
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001565/* Checks for conditions where Secure RGB layers cannot be bypassed */
1566bool MDPComp::isSecureRGBDoable(hwc_context_t* ctx, hwc_layer_1_t* layer) {
1567 if(isSkipLayer(layer)) {
1568 ALOGD_IF(isDebug(), "%s: Secure RGB layer marked SKIP dpy %d",
1569 __FUNCTION__, mDpy);
1570 return false;
1571 }
1572
1573 if(isSecuring(ctx, layer)) {
1574 ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
1575 return false;
1576 }
1577
1578 if(not isSupportedForMDPComp(ctx, layer)) {
1579 ALOGD_IF(isDebug(), "%s: Unsupported secure RGB layer",
1580 __FUNCTION__);
1581 return false;
1582 }
1583 return true;
1584}
1585
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301586/* starts at fromIndex and check for each layer to find
1587 * if it it has overlapping with any Updating layer above it in zorder
1588 * till the end of the batch. returns true if it finds any intersection */
1589bool MDPComp::canPushBatchToTop(const hwc_display_contents_1_t* list,
1590 int fromIndex, int toIndex) {
1591 for(int i = fromIndex; i < toIndex; i++) {
1592 if(mCurrentFrame.isFBComposed[i] && !mCurrentFrame.drop[i]) {
1593 if(intersectingUpdatingLayers(list, i+1, toIndex, i)) {
1594 return false;
1595 }
1596 }
1597 }
1598 return true;
1599}
1600
1601/* Checks if given layer at targetLayerIndex has any
1602 * intersection with all the updating layers in beween
1603 * fromIndex and toIndex. Returns true if it finds intersectiion */
1604bool MDPComp::intersectingUpdatingLayers(const hwc_display_contents_1_t* list,
1605 int fromIndex, int toIndex, int targetLayerIndex) {
1606 for(int i = fromIndex; i <= toIndex; i++) {
1607 if(!mCurrentFrame.isFBComposed[i]) {
1608 if(areLayersIntersecting(&list->hwLayers[i],
1609 &list->hwLayers[targetLayerIndex])) {
1610 return true;
1611 }
1612 }
1613 }
1614 return false;
1615}
1616
1617int MDPComp::getBatch(hwc_display_contents_1_t* list,
1618 int& maxBatchStart, int& maxBatchEnd,
1619 int& maxBatchCount) {
1620 int i = 0;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301621 int fbZOrder =-1;
Jeykumar Sankaran9502f352014-01-20 12:25:32 -08001622 int droppedLayerCt = 0;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301623 while (i < mCurrentFrame.layerCount) {
1624 int batchCount = 0;
1625 int batchStart = i;
1626 int batchEnd = i;
Jeykumar Sankaran9502f352014-01-20 12:25:32 -08001627 /* Adjust batch Z order with the dropped layers so far */
1628 int fbZ = batchStart - droppedLayerCt;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301629 int firstZReverseIndex = -1;
Prabhanjan Kandula0ed2cc92013-12-06 12:39:04 +05301630 int updatingLayersAbove = 0;//Updating layer count in middle of batch
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301631 while(i < mCurrentFrame.layerCount) {
1632 if(!mCurrentFrame.isFBComposed[i]) {
1633 if(!batchCount) {
1634 i++;
1635 break;
1636 }
1637 updatingLayersAbove++;
1638 i++;
1639 continue;
1640 } else {
1641 if(mCurrentFrame.drop[i]) {
1642 i++;
Jeykumar Sankaran9502f352014-01-20 12:25:32 -08001643 droppedLayerCt++;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301644 continue;
1645 } else if(updatingLayersAbove <= 0) {
1646 batchCount++;
1647 batchEnd = i;
1648 i++;
1649 continue;
1650 } else { //Layer is FBComposed, not a drop & updatingLayer > 0
1651
1652 // We have a valid updating layer already. If layer-i not
1653 // have overlapping with all updating layers in between
1654 // batch-start and i, then we can add layer i to batch.
1655 if(!intersectingUpdatingLayers(list, batchStart, i-1, i)) {
1656 batchCount++;
1657 batchEnd = i;
1658 i++;
1659 continue;
1660 } else if(canPushBatchToTop(list, batchStart, i)) {
1661 //If All the non-updating layers with in this batch
1662 //does not have intersection with the updating layers
1663 //above in z-order, then we can safely move the batch to
1664 //higher z-order. Increment fbZ as it is moving up.
1665 if( firstZReverseIndex < 0) {
1666 firstZReverseIndex = i;
1667 }
1668 batchCount++;
1669 batchEnd = i;
1670 fbZ += updatingLayersAbove;
1671 i++;
1672 updatingLayersAbove = 0;
1673 continue;
1674 } else {
1675 //both failed.start the loop again from here.
1676 if(firstZReverseIndex >= 0) {
1677 i = firstZReverseIndex;
1678 }
1679 break;
1680 }
1681 }
1682 }
1683 }
1684 if(batchCount > maxBatchCount) {
1685 maxBatchCount = batchCount;
1686 maxBatchStart = batchStart;
1687 maxBatchEnd = batchEnd;
1688 fbZOrder = fbZ;
1689 }
1690 }
1691 return fbZOrder;
1692}
1693
1694bool MDPComp::markLayersForCaching(hwc_context_t* ctx,
1695 hwc_display_contents_1_t* list) {
1696 /* Idea is to keep as many non-updating(cached) layers in FB and
1697 * send rest of them through MDP. This is done in 2 steps.
1698 * 1. Find the maximum contiguous batch of non-updating layers.
1699 * 2. See if we can improve this batch size for caching by adding
1700 * opaque layers around the batch, if they don't have
1701 * any overlapping with the updating layers in between.
1702 * NEVER mark an updating layer for caching.
1703 * But cached ones can be marked for MDP */
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001704
1705 int maxBatchStart = -1;
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001706 int maxBatchEnd = -1;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001707 int maxBatchCount = 0;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301708 int fbZ = -1;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001709
Saurabh Shahd53bc5f2014-02-05 10:17:43 -08001710 /* Nothing is cached. No batching needed */
1711 if(mCurrentFrame.fbCount == 0) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001712 return true;
Saurabh Shahaa236822013-04-24 18:07:26 -07001713 }
Saurabh Shahd53bc5f2014-02-05 10:17:43 -08001714
1715 /* No MDP comp layers, try to use other comp modes */
1716 if(mCurrentFrame.mdpCount == 0) {
1717 return false;
Saurabh Shahaa236822013-04-24 18:07:26 -07001718 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001719
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301720 fbZ = getBatch(list, maxBatchStart, maxBatchEnd, maxBatchCount);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001721
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301722 /* reset rest of the layers lying inside ROI for MDP comp */
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001723 for(int i = 0; i < mCurrentFrame.layerCount; i++) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001724 hwc_layer_1_t* layer = &list->hwLayers[i];
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001725 if((i < maxBatchStart || i > maxBatchEnd) &&
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301726 mCurrentFrame.isFBComposed[i]){
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001727 if(!mCurrentFrame.drop[i]){
1728 //If an unsupported layer is being attempted to
1729 //be pulled out we should fail
1730 if(not isSupportedForMDPComp(ctx, layer)) {
1731 return false;
1732 }
1733 mCurrentFrame.isFBComposed[i] = false;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001734 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001735 }
1736 }
1737
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301738 // update the frame data
1739 mCurrentFrame.fbZ = fbZ;
1740 mCurrentFrame.fbCount = maxBatchCount;
Saurabh Shahaa236822013-04-24 18:07:26 -07001741 mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001742 mCurrentFrame.fbCount - mCurrentFrame.dropCount;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001743
1744 ALOGD_IF(isDebug(),"%s: cached count: %d",__FUNCTION__,
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301745 mCurrentFrame.fbCount);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001746
1747 return true;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001748}
Saurabh Shah85234ec2013-04-12 17:09:00 -07001749
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001750void MDPComp::updateLayerCache(hwc_context_t* ctx,
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001751 hwc_display_contents_1_t* list, FrameInfo& frame) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001752 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001753 int fbCount = 0;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001754
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001755 for(int i = 0; i < numAppLayers; i++) {
1756 if (mCachedFrame.hnd[i] == list->hwLayers[i].handle) {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001757 if(!frame.drop[i])
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001758 fbCount++;
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001759 frame.isFBComposed[i] = true;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001760 } else {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001761 frame.isFBComposed[i] = false;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001762 }
1763 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001764
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001765 frame.fbCount = fbCount;
1766 frame.mdpCount = frame.layerCount - frame.fbCount
1767 - frame.dropCount;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001768
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001769 ALOGD_IF(isDebug(),"%s: MDP count: %d FB count %d drop count: %d",
1770 __FUNCTION__, frame.mdpCount, frame.fbCount, frame.dropCount);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001771}
1772
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001773// drop other non-AIV layers from external display list.
1774void MDPComp::dropNonAIVLayers(hwc_context_t* ctx,
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07001775 hwc_display_contents_1_t* list) {
1776 for (size_t i = 0; i < (size_t)ctx->listStats[mDpy].numAppLayers; i++) {
1777 hwc_layer_1_t * layer = &list->hwLayers[i];
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001778 if(!(isAIVVideoLayer(layer) || isAIVCCLayer(layer))) {
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07001779 mCurrentFrame.dropCount++;
1780 mCurrentFrame.drop[i] = true;
1781 }
1782 }
1783 mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
1784 mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
1785 mCurrentFrame.fbCount - mCurrentFrame.dropCount;
1786 ALOGD_IF(isDebug(),"%s: fb count: %d mdp count %d drop count %d",
1787 __FUNCTION__, mCurrentFrame.fbCount, mCurrentFrame.mdpCount,
1788 mCurrentFrame.dropCount);
1789}
1790
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001791void MDPComp::updateYUV(hwc_context_t* ctx, hwc_display_contents_1_t* list,
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001792 bool secureOnly, FrameInfo& frame) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001793 int nYuvCount = ctx->listStats[mDpy].yuvCount;
1794 for(int index = 0;index < nYuvCount; index++){
1795 int nYuvIndex = ctx->listStats[mDpy].yuvIndices[index];
1796 hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
1797
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001798 if(mCurrentFrame.drop[nYuvIndex]) {
1799 continue;
1800 }
1801
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001802 if(!isYUVDoable(ctx, layer)) {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001803 if(!frame.isFBComposed[nYuvIndex]) {
1804 frame.isFBComposed[nYuvIndex] = true;
1805 frame.fbCount++;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001806 }
1807 } else {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001808 if(frame.isFBComposed[nYuvIndex]) {
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001809 private_handle_t *hnd = (private_handle_t *)layer->handle;
1810 if(!secureOnly || isSecureBuffer(hnd)) {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001811 frame.isFBComposed[nYuvIndex] = false;
1812 frame.fbCount--;
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001813 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001814 }
1815 }
1816 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001817
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001818 frame.mdpCount = frame.layerCount - frame.fbCount - frame.dropCount;
1819 ALOGD_IF(isDebug(),"%s: fb count: %d",__FUNCTION__, frame.fbCount);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001820}
1821
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001822void MDPComp::updateSecureRGB(hwc_context_t* ctx,
1823 hwc_display_contents_1_t* list) {
1824 int nSecureRGBCount = ctx->listStats[mDpy].secureRGBCount;
1825 for(int index = 0;index < nSecureRGBCount; index++){
1826 int nSecureRGBIndex = ctx->listStats[mDpy].secureRGBIndices[index];
1827 hwc_layer_1_t* layer = &list->hwLayers[nSecureRGBIndex];
1828
1829 if(!isSecureRGBDoable(ctx, layer)) {
1830 if(!mCurrentFrame.isFBComposed[nSecureRGBIndex]) {
1831 mCurrentFrame.isFBComposed[nSecureRGBIndex] = true;
1832 mCurrentFrame.fbCount++;
1833 }
1834 } else {
1835 if(mCurrentFrame.isFBComposed[nSecureRGBIndex]) {
1836 mCurrentFrame.isFBComposed[nSecureRGBIndex] = false;
1837 mCurrentFrame.fbCount--;
1838 }
1839 }
1840 }
1841
1842 mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
1843 mCurrentFrame.fbCount - mCurrentFrame.dropCount;
1844 ALOGD_IF(isDebug(),"%s: fb count: %d",__FUNCTION__,
1845 mCurrentFrame.fbCount);
1846}
1847
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001848hwc_rect_t MDPComp::getUpdatingFBRect(hwc_context_t *ctx,
1849 hwc_display_contents_1_t* list){
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001850 hwc_rect_t fbRect = (struct hwc_rect){0, 0, 0, 0};
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001851
1852 /* Update only the region of FB needed for composition */
1853 for(int i = 0; i < mCurrentFrame.layerCount; i++ ) {
1854 if(mCurrentFrame.isFBComposed[i] && !mCurrentFrame.drop[i]) {
1855 hwc_layer_1_t* layer = &list->hwLayers[i];
1856 hwc_rect_t dst = layer->displayFrame;
1857 fbRect = getUnion(fbRect, dst);
1858 }
1859 }
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08001860 trimAgainstROI(ctx, fbRect, fbRect);
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001861 return fbRect;
1862}
1863
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001864bool MDPComp::postHeuristicsHandling(hwc_context_t *ctx,
1865 hwc_display_contents_1_t* list) {
1866
1867 //Capability checks
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08001868 if(!resourceCheck(ctx, list)) {
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001869 ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
1870 return false;
1871 }
1872
1873 //Limitations checks
1874 if(!hwLimitationsCheck(ctx, list)) {
1875 ALOGD_IF(isDebug(), "%s: HW limitations",__FUNCTION__);
1876 return false;
1877 }
1878
Saurabh Shah3d4b8042013-12-10 15:19:17 -08001879 //Configure framebuffer first if applicable
1880 if(mCurrentFrame.fbZ >= 0) {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001881 hwc_rect_t fbRect = getUpdatingFBRect(ctx, list);
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001882 if(!ctx->mFBUpdate[mDpy]->prepare(ctx, list, fbRect, mCurrentFrame.fbZ))
1883 {
Saurabh Shah3d4b8042013-12-10 15:19:17 -08001884 ALOGD_IF(isDebug(), "%s configure framebuffer failed",
1885 __FUNCTION__);
1886 return false;
1887 }
1888 }
1889
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001890 mCurrentFrame.map();
1891
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001892 if(!allocLayerPipes(ctx, list)) {
1893 ALOGD_IF(isDebug(), "%s: Unable to allocate MDP pipes", __FUNCTION__);
Saurabh Shahaa236822013-04-24 18:07:26 -07001894 return false;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001895 }
1896
1897 for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
Saurabh Shahaa236822013-04-24 18:07:26 -07001898 index++) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001899 if(!mCurrentFrame.isFBComposed[index]) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001900 int mdpIndex = mCurrentFrame.layerToMDP[index];
1901 hwc_layer_1_t* layer = &list->hwLayers[index];
1902
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301903 //Leave fbZ for framebuffer. CACHE/GLES layers go here.
1904 if(mdpNextZOrder == mCurrentFrame.fbZ) {
1905 mdpNextZOrder++;
1906 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001907 MdpPipeInfo* cur_pipe = mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
1908 cur_pipe->zOrder = mdpNextZOrder++;
1909
radhakrishnac9a67412013-09-25 17:40:42 +05301910 private_handle_t *hnd = (private_handle_t *)layer->handle;
Raj Kamal389d6e32014-08-04 14:43:24 +05301911 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
radhakrishnac9a67412013-09-25 17:40:42 +05301912 if(configure4k2kYuv(ctx, layer,
1913 mCurrentFrame.mdpToLayer[mdpIndex])
1914 != 0 ){
1915 ALOGD_IF(isDebug(), "%s: Failed to configure split pipes \
1916 for layer %d",__FUNCTION__, index);
1917 return false;
1918 }
1919 else{
1920 mdpNextZOrder++;
1921 }
1922 continue;
1923 }
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05001924 if(needs3DComposition(ctx,mDpy) && get3DFormat(hnd) != HAL_NO_3D) {
1925 mdpNextZOrder++;
1926 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001927 if(configure(ctx, layer, mCurrentFrame.mdpToLayer[mdpIndex]) != 0 ){
1928 ALOGD_IF(isDebug(), "%s: Failed to configure overlay for \
radhakrishnac9a67412013-09-25 17:40:42 +05301929 layer %d",__FUNCTION__, index);
Saurabh Shahaa236822013-04-24 18:07:26 -07001930 return false;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001931 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001932 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001933 }
1934
Saurabh Shaha36be922013-12-16 18:18:39 -08001935 if(!ctx->mOverlay->validateAndSet(mDpy, ctx->dpyAttr[mDpy].fd)) {
1936 ALOGD_IF(isDebug(), "%s: Failed to validate and set overlay for dpy %d"
1937 ,__FUNCTION__, mDpy);
1938 return false;
1939 }
1940
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001941 setRedraw(ctx, list);
Saurabh Shahaa236822013-04-24 18:07:26 -07001942 return true;
1943}
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001944
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08001945bool MDPComp::resourceCheck(hwc_context_t* ctx,
1946 hwc_display_contents_1_t* list) {
Saurabh Shah173f4242013-11-20 09:50:12 -08001947 const bool fbUsed = mCurrentFrame.fbCount;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001948 int cursorInUse = 0;
1949 if(mDpy == HWC_DISPLAY_PRIMARY) {
1950 // check if cursor is in use for primary
1951 cursorInUse = HWCursor::getInstance()->isCursorSet();
1952 }
1953 int maxStages = qdutils::MDPVersion::getInstance().getBlendStages();
1954 // HW Cursor needs one blending stage, account for that in the check below
1955 // On high end targets(8994) has 8 blending stages, HAL is configured to use < 8.
1956 // Make use of the remaining stages for HW Cursor so that the composition
1957 // strategy would not fail due to this limitation.
1958 if (maxStages > sMaxPipesPerMixer) {
1959 cursorInUse = 0;
1960 }
1961 if(mCurrentFrame.mdpCount > (sMaxPipesPerMixer - fbUsed - cursorInUse)) {
Saurabh Shah173f4242013-11-20 09:50:12 -08001962 ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
1963 return false;
1964 }
Saurabh Shahacec8e42014-11-25 11:07:04 -08001965
1966 //Will benefit cases where a video has non-updating background.
1967 if((mDpy > HWC_DISPLAY_PRIMARY) and
1968 (mCurrentFrame.mdpCount > sMaxSecLayers)) {
1969 ALOGD_IF(isDebug(), "%s: Exceeds max secondary pipes",__FUNCTION__);
1970 return false;
1971 }
1972
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08001973 // Init rotCount to number of rotate sessions used by other displays
1974 int rotCount = ctx->mRotMgr->getNumActiveSessions();
1975 // Count the number of rotator sessions required for current display
1976 for (int index = 0; index < mCurrentFrame.layerCount; index++) {
1977 if(!mCurrentFrame.isFBComposed[index]) {
1978 hwc_layer_1_t* layer = &list->hwLayers[index];
1979 private_handle_t *hnd = (private_handle_t *)layer->handle;
1980 if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
1981 rotCount++;
1982 }
1983 }
1984 }
1985 // if number of layers to rotate exceeds max rotator sessions, bail out.
1986 if(rotCount > RotMgr::MAX_ROT_SESS) {
1987 ALOGD_IF(isDebug(), "%s: Exceeds max rotator sessions %d",
1988 __FUNCTION__, mDpy);
1989 return false;
1990 }
Saurabh Shah173f4242013-11-20 09:50:12 -08001991 return true;
1992}
1993
Prabhanjan Kandula21918db2013-11-26 15:51:58 +05301994bool MDPComp::hwLimitationsCheck(hwc_context_t* ctx,
1995 hwc_display_contents_1_t* list) {
1996
1997 //A-family hw limitation:
1998 //If a layer need alpha scaling, MDP can not support.
1999 if(ctx->mMDP.version < qdutils::MDSS_V5) {
2000 for(int i = 0; i < mCurrentFrame.layerCount; ++i) {
2001 if(!mCurrentFrame.isFBComposed[i] &&
2002 isAlphaScaled( &list->hwLayers[i])) {
2003 ALOGD_IF(isDebug(), "%s:frame needs alphaScaling",__FUNCTION__);
2004 return false;
2005 }
2006 }
2007 }
2008
2009 // On 8x26 & 8974 hw, we have a limitation of downscaling+blending.
2010 //If multiple layers requires downscaling and also they are overlapping
2011 //fall back to GPU since MDSS can not handle it.
2012 if(qdutils::MDPVersion::getInstance().is8x74v2() ||
2013 qdutils::MDPVersion::getInstance().is8x26()) {
2014 for(int i = 0; i < mCurrentFrame.layerCount-1; ++i) {
2015 hwc_layer_1_t* botLayer = &list->hwLayers[i];
2016 if(!mCurrentFrame.isFBComposed[i] &&
2017 isDownscaleRequired(botLayer)) {
2018 //if layer-i is marked for MDP and needs downscaling
2019 //check if any MDP layer on top of i & overlaps with layer-i
2020 for(int j = i+1; j < mCurrentFrame.layerCount; ++j) {
2021 hwc_layer_1_t* topLayer = &list->hwLayers[j];
2022 if(!mCurrentFrame.isFBComposed[j] &&
2023 isDownscaleRequired(topLayer)) {
2024 hwc_rect_t r = getIntersection(botLayer->displayFrame,
2025 topLayer->displayFrame);
2026 if(isValidRect(r))
2027 return false;
2028 }
2029 }
2030 }
2031 }
2032 }
2033 return true;
2034}
2035
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002036static bool validForCursor(hwc_context_t* ctx, int dpy, hwc_layer_1_t* layer) {
2037 private_handle_t *hnd = (private_handle_t *)layer->handle;
2038 hwc_rect dst = layer->displayFrame;
2039 hwc_rect src = integerizeSourceCrop(layer->sourceCropf);
2040 int srcW = src.right - src.left;
2041 int srcH = src.bottom - src.top;
2042 int dstW = dst.right - dst.left;
2043 int dstH = dst.bottom - dst.top;
2044 qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
2045 uint32_t maxCursorSize = mdpVersion.getMaxCursorSize();
2046 uint32_t numHwCursors = mdpVersion.getCursorPipes();
2047 bool primarySplit = isDisplaySplit(ctx, HWC_DISPLAY_PRIMARY);
2048 uint32_t cursorPipesNeeded = 1; // One cursor pipe needed(default)
2049 bool ret = false;
2050
2051 if(dpy > HWC_DISPLAY_PRIMARY) {
2052 // Cursor not supported on secondary displays, as it involves scaling
2053 // in most of the cases
2054 return false;
2055 } else if (isSkipLayer(layer)) {
2056 return false;
2057 // Checks for HW limitation
2058 } else if (numHwCursors == 0 || maxCursorSize <= 0) {
2059 return false;
2060 } else if (needsScaling(layer)) {
2061 return false;
2062 } else if (layer->transform != 0) {
2063 return false;
2064 } else if (hnd->format != HAL_PIXEL_FORMAT_RGBA_8888) {
2065 return false;
2066 } else if (srcW > (int)maxCursorSize || srcH > (int)maxCursorSize) {
2067 return false;
2068 }
2069
2070 if (isDisplaySplit(ctx, dpy) && !mdpVersion.isSrcSplit()) {
2071 // In case of split display with no srcSplit, the driver allocates two
2072 // pipes to support async position update across mixers, hence
2073 // need to account for that here.
2074 cursorPipesNeeded = 2;
2075 }
2076 if (cursorPipesNeeded <= numHwCursors) {
2077 ret = true;
2078 }
2079 return ret;
2080}
2081
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08002082// Checks only if videos or single layer(RGB) is updating
2083// which is used for setting dynamic fps or perf hint for single
2084// layer video playback
2085bool MDPComp::onlyVideosUpdating(hwc_context_t *ctx,
2086 hwc_display_contents_1_t* list) {
2087 bool support = false;
2088 FrameInfo frame;
2089 frame.reset(mCurrentFrame.layerCount);
2090 memset(&frame.drop, 0, sizeof(frame.drop));
2091 frame.dropCount = 0;
2092 ALOGD_IF(isDebug(), "%s: Update Cache and YUVInfo", __FUNCTION__);
2093 updateLayerCache(ctx, list, frame);
2094 updateYUV(ctx, list, false /*secure only*/, frame);
2095 // There are only updating YUV layers or there is single RGB
2096 // Layer(Youtube)
2097 if((ctx->listStats[mDpy].yuvCount == frame.mdpCount) ||
2098 (frame.layerCount == 1)) {
2099 support = true;
2100 }
2101 return support;
2102}
2103
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302104void MDPComp::setDynRefreshRate(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
2105 //For primary display, set the dynamic refreshrate
2106 if(!mDpy && qdutils::MDPVersion::getInstance().isDynFpsSupported() &&
2107 ctx->mUseMetaDataRefreshRate) {
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302108 uint32_t refreshRate = ctx->dpyAttr[mDpy].refreshRate;
2109 MDPVersion& mdpHw = MDPVersion::getInstance();
2110 if(sIdleFallBack) {
2111 //Set minimum panel refresh rate during idle timeout
2112 refreshRate = mdpHw.getMinFpsSupported();
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08002113 } else if(onlyVideosUpdating(ctx, list)) {
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302114 //Set the new fresh rate, if there is only one updating YUV layer
2115 //or there is one single RGB layer with this request
2116 refreshRate = ctx->listStats[mDpy].refreshRateRequest;
2117 }
2118 setRefreshRate(ctx, mDpy, refreshRate);
2119 }
2120}
2121
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002122int MDPComp::prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002123 int ret = 0;
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07002124 char property[PROPERTY_VALUE_MAX];
2125
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002126 if(!list) {
2127 ALOGE("%s: Invalid list", __FUNCTION__);
Raj Kamal4393eaa2014-06-06 13:45:20 +05302128 mCachedFrame.reset();
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002129 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Raj Kamal4393eaa2014-06-06 13:45:20 +05302130 return -1;
2131 }
2132
2133 const int numLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shah286cf122014-09-08 14:13:08 -07002134 if(mDpy == HWC_DISPLAY_PRIMARY) {
2135 sSimulationFlags = 0;
2136 if(property_get("debug.hwc.simulate", property, NULL) > 0) {
2137 int currentFlags = atoi(property);
2138 if(currentFlags != sSimulationFlags) {
2139 sSimulationFlags = currentFlags;
2140 ALOGI("%s: Simulation Flag read: 0x%x (%d)", __FUNCTION__,
2141 sSimulationFlags, sSimulationFlags);
2142 }
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07002143 }
2144 }
Ramkumar Radhakrishnanc5893f12013-06-06 19:43:53 -07002145
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302146 //reset old data
2147 mCurrentFrame.reset(numLayers);
2148 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
2149 mCurrentFrame.dropCount = 0;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002150 mCurrentFrame.hwCursorIndex = -1;
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302151
Raj Kamal9ed3d6b2014-02-07 16:15:17 +05302152 //Do not cache the information for next draw cycle.
2153 if(numLayers > MAX_NUM_APP_LAYERS or (!numLayers)) {
2154 ALOGI("%s: Unsupported layer count for mdp composition",
2155 __FUNCTION__);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002156 mCachedFrame.reset();
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302157#ifdef DYNAMIC_FPS
2158 setDynRefreshRate(ctx, list);
2159#endif
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002160 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002161 return -1;
2162 }
2163
Ramkumar Radhakrishnana70981a2013-08-28 11:33:53 -07002164 // Detect the start of animation and fall back to GPU only once to cache
2165 // all the layers in FB and display FB content untill animation completes.
2166 if(ctx->listStats[mDpy].isDisplayAnimating) {
2167 mCurrentFrame.needsRedraw = false;
2168 if(ctx->mAnimationState[mDpy] == ANIMATION_STOPPED) {
2169 mCurrentFrame.needsRedraw = true;
2170 ctx->mAnimationState[mDpy] = ANIMATION_STARTED;
2171 }
2172 setMDPCompLayerFlags(ctx, list);
2173 mCachedFrame.updateCounts(mCurrentFrame);
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302174#ifdef DYNAMIC_FPS
2175 setDynRefreshRate(ctx, list);
2176#endif
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002177 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Ramkumar Radhakrishnana70981a2013-08-28 11:33:53 -07002178 ret = -1;
2179 return ret;
2180 } else {
2181 ctx->mAnimationState[mDpy] = ANIMATION_STOPPED;
2182 }
2183
Raj Kamalfdfdddf2015-03-16 21:59:25 +05302184 if(!mDpy and !isSecondaryConnected(ctx) and !mPrevModeOn and
2185 mCachedFrame.isSameFrame(ctx,mDpy,list)) {
2186
2187 ALOGD_IF(isDebug(),"%s: Avoid new composition",__FUNCTION__);
2188 mCurrentFrame.needsRedraw = false;
2189 setMDPCompLayerFlags(ctx, list);
2190 mCachedFrame.updateCounts(mCurrentFrame);
2191#ifdef DYNAMIC_FPS
2192 setDynRefreshRate(ctx, list);
2193#endif
2194 return -1;
2195
2196 }
2197
Saurabh Shahb39f8152013-08-22 10:21:44 -07002198 //Hard conditions, if not met, cannot do MDP comp
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002199 if(isFrameDoable(ctx)) {
2200 generateROI(ctx, list);
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07002201 // if AIV Video mode is enabled, drop all non AIV layers from the
2202 // external display list.
2203 if(ctx->listStats[mDpy].mAIVVideoMode) {
2204 dropNonAIVLayers(ctx, list);
2205 }
Saurabh Shahb39f8152013-08-22 10:21:44 -07002206
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002207 // Configure the cursor if present
2208 int topIndex = ctx->listStats[mDpy].numAppLayers - 1;
2209 if(ctx->listStats[mDpy].cursorLayerPresent &&
2210 validForCursor(ctx, mDpy, &(list->hwLayers[topIndex]))) {
2211 if(configHwCursor(ctx->dpyAttr[mDpy].fd, mDpy,
2212 &(list->hwLayers[topIndex]))) {
2213 // As cursor is configured, mark that layer as dropped, so that
2214 // it wont be considered for composition by other strategies.
2215 mCurrentFrame.hwCursorIndex = topIndex;
2216 mCurrentFrame.drop[topIndex] = true;
2217 mCurrentFrame.dropCount++;
2218 }
2219 } else {
2220 // Release the hw cursor
2221 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
2222 }
2223
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07002224 // if tryFullFrame fails, try to push all video and secure RGB layers
2225 // to MDP for composition.
2226 mModeOn = tryFullFrame(ctx, list) || tryMDPOnlyLayers(ctx, list) ||
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07002227 tryVideoOnly(ctx, list);
Raj Kamal4393eaa2014-06-06 13:45:20 +05302228 if(mModeOn) {
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002229 setMDPCompLayerFlags(ctx, list);
2230 } else {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08002231 resetROI(ctx, mDpy);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002232 reset(ctx);
2233 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
2234 mCurrentFrame.dropCount = 0;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002235 // Check if cursor is in use for primary and mark accordingly
2236 if(!mDpy && HWCursor::getInstance()->isCursorSet()) {
2237 int topIndex = ctx->listStats[mDpy].numAppLayers - 1;
2238 hwc_layer_1_t *layer = &(list->hwLayers[topIndex]);
2239 layer->compositionType = HWC_CURSOR_OVERLAY;
2240 }
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002241 ret = -1;
Saurabh Shah286cf122014-09-08 14:13:08 -07002242 ALOGE_IF(sSimulationFlags && (mDpy == HWC_DISPLAY_PRIMARY),
2243 "MDP Composition Strategies Failed");
Saurabh Shahb39f8152013-08-22 10:21:44 -07002244 }
2245 } else {
Dileep Kumar Reddi4070e932014-09-30 09:00:57 +05302246 if ((ctx->mMDP.version == qdutils::MDP_V3_0_5) && ctx->mCopyBit[mDpy] &&
2247 enablePartialUpdateForMDP3) {
2248 generateROI(ctx, list);
2249 for(int i = 0; i < ctx->listStats[mDpy].numAppLayers; i++) {
2250 ctx->copybitDrop[i] = mCurrentFrame.drop[i];
2251 }
2252 }
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002253 ALOGD_IF( isDebug(),"%s: MDP Comp not possible for this frame",
2254 __FUNCTION__);
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002255 // Release the hw cursor
2256 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002257 ret = -1;
Saurabh Shahb39f8152013-08-22 10:21:44 -07002258 }
Saurabh Shahb39f8152013-08-22 10:21:44 -07002259
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002260 if(isDebug()) {
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002261 ALOGD("GEOMETRY change: %d",
2262 (list->flags & HWC_GEOMETRY_CHANGED));
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002263 android::String8 sDump("");
Jeykumar Sankaran6850ac62014-05-27 10:07:26 -07002264 dump(sDump, ctx);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002265 ALOGD("%s",sDump.string());
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002266 }
2267
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07002268#ifdef DYNAMIC_FPS
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302269 setDynRefreshRate(ctx, list);
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07002270#endif
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08002271 setPerfHint(ctx, list);
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07002272
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002273 mCachedFrame.cacheAll(list);
2274 mCachedFrame.updateCounts(mCurrentFrame);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002275 return ret;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002276}
2277
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002278bool MDPComp::allocSplitVGPipes(hwc_context_t *ctx, int index) {
radhakrishnac9a67412013-09-25 17:40:42 +05302279
2280 bool bRet = true;
radhakrishnac9a67412013-09-25 17:40:42 +05302281 int mdpIndex = mCurrentFrame.layerToMDP[index];
2282 PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
2283 info.pipeInfo = new MdpYUVPipeInfo;
2284 info.rot = NULL;
2285 MdpYUVPipeInfo& pipe_info = *(MdpYUVPipeInfo*)info.pipeInfo;
radhakrishnac9a67412013-09-25 17:40:42 +05302286
2287 pipe_info.lIndex = ovutils::OV_INVALID;
2288 pipe_info.rIndex = ovutils::OV_INVALID;
2289
Saurabh Shahc62f3982014-03-05 14:28:26 -08002290 Overlay::PipeSpecs pipeSpecs;
2291 pipeSpecs.formatClass = Overlay::FORMAT_YUV;
2292 pipeSpecs.needsScaling = true;
2293 pipeSpecs.dpy = mDpy;
2294 pipeSpecs.fb = false;
2295
2296 pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
radhakrishnac9a67412013-09-25 17:40:42 +05302297 if(pipe_info.lIndex == ovutils::OV_INVALID){
2298 bRet = false;
2299 ALOGD_IF(isDebug(),"%s: allocating first VG pipe failed",
2300 __FUNCTION__);
2301 }
Saurabh Shahc62f3982014-03-05 14:28:26 -08002302 pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
radhakrishnac9a67412013-09-25 17:40:42 +05302303 if(pipe_info.rIndex == ovutils::OV_INVALID){
2304 bRet = false;
2305 ALOGD_IF(isDebug(),"%s: allocating second VG pipe failed",
2306 __FUNCTION__);
2307 }
2308 return bRet;
2309}
Sushil Chauhandefd3522014-05-13 18:17:12 -07002310
2311int MDPComp::drawOverlap(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
2312 int fd = -1;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002313 if (ctx->mPtorInfo.isActive()) {
2314 fd = ctx->mCopyBit[mDpy]->drawOverlap(ctx, list);
Sushil Chauhandefd3522014-05-13 18:17:12 -07002315 if (fd < 0) {
2316 ALOGD_IF(isDebug(),"%s: failed", __FUNCTION__);
Sushil Chauhandefd3522014-05-13 18:17:12 -07002317 }
2318 }
2319 return fd;
2320}
Arun Kumar K.R2aa44c62014-01-21 23:08:28 -08002321//=============MDPCompNonSplit==================================================
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002322
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002323void MDPCompNonSplit::adjustForSourceSplit(hwc_context_t *ctx,
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302324 hwc_display_contents_1_t* list) {
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002325 //If 4k2k Yuv layer split is possible, and if
2326 //fbz is above 4k2k layer, increment fb zorder by 1
2327 //as we split 4k2k layer and increment zorder for right half
2328 //of the layer
Shalaj Jaina70b4352014-06-15 13:47:47 -07002329 if(!ctx)
2330 return;
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002331 if(mCurrentFrame.fbZ >= 0) {
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302332 for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
2333 index++) {
2334 if(!mCurrentFrame.isFBComposed[index]) {
2335 if(mdpNextZOrder == mCurrentFrame.fbZ) {
2336 mdpNextZOrder++;
2337 }
2338 mdpNextZOrder++;
2339 hwc_layer_1_t* layer = &list->hwLayers[index];
2340 private_handle_t *hnd = (private_handle_t *)layer->handle;
Raj Kamal389d6e32014-08-04 14:43:24 +05302341 if(isYUVSplitNeeded(hnd)) {
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302342 if(mdpNextZOrder <= mCurrentFrame.fbZ)
2343 mCurrentFrame.fbZ += 1;
2344 mdpNextZOrder++;
2345 //As we split 4kx2k yuv layer and program to 2 VG pipes
2346 //(if available) increase mdpcount by 1.
2347 mCurrentFrame.mdpCount++;
2348 }
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002349 }
2350 }
2351 }
radhakrishnac9a67412013-09-25 17:40:42 +05302352}
2353
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002354/*
2355 * Configures pipe(s) for MDP composition
2356 */
Saurabh Shah88e4d272013-09-03 13:31:29 -07002357int MDPCompNonSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002358 PipeLayerPair& PipeLayerPair) {
Saurabh Shah88e4d272013-09-03 13:31:29 -07002359 MdpPipeInfoNonSplit& mdp_info =
2360 *(static_cast<MdpPipeInfoNonSplit*>(PipeLayerPair.pipeInfo));
Justin Philipd6166602014-08-12 13:42:21 +05302361 eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shahacf10202013-02-26 10:15:15 -08002362 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Saurabh Shahacf10202013-02-26 10:15:15 -08002363 eDest dest = mdp_info.index;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002364
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002365 ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipe: %d",
2366 __FUNCTION__, layer, zOrder, dest);
2367
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002368 return configureNonSplit(ctx, layer, mDpy, mdpFlags, zOrder, dest,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002369 &PipeLayerPair.rot);
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002370}
2371
Saurabh Shah88e4d272013-09-03 13:31:29 -07002372bool MDPCompNonSplit::allocLayerPipes(hwc_context_t *ctx,
Saurabh Shahe51f8ca2013-05-06 17:26:16 -07002373 hwc_display_contents_1_t* list) {
Saurabh Shah8cc77712015-03-31 10:48:51 -07002374 for(uint32_t formatType = FORMAT_YUV; formatType < FORMAT_MAX;
2375 formatType++) {
2376 for(int index = 0; index < mCurrentFrame.layerCount; index++) {
2377 if(mCurrentFrame.isFBComposed[index]) continue;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002378
Saurabh Shah8cc77712015-03-31 10:48:51 -07002379 hwc_layer_1_t* layer = &list->hwLayers[index];
2380 private_handle_t *hnd = (private_handle_t *)layer->handle;
2381 if(formatType == FORMAT_YUV && !isYuvBuffer(hnd))
radhakrishnac9a67412013-09-25 17:40:42 +05302382 continue;
Saurabh Shah8cc77712015-03-31 10:48:51 -07002383 if(formatType == FORMAT_RGB && isYuvBuffer(hnd))
2384 continue;
2385
2386 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
2387 if(allocSplitVGPipes(ctx, index)){
2388 continue;
2389 }
radhakrishnac9a67412013-09-25 17:40:42 +05302390 }
radhakrishnac9a67412013-09-25 17:40:42 +05302391
Saurabh Shah8cc77712015-03-31 10:48:51 -07002392 int mdpIndex = mCurrentFrame.layerToMDP[index];
2393 PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
2394 info.pipeInfo = new MdpPipeInfoNonSplit;
2395 info.rot = NULL;
2396 MdpPipeInfoNonSplit& pipe_info =
2397 *(MdpPipeInfoNonSplit*)info.pipeInfo;
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -08002398
Saurabh Shah8cc77712015-03-31 10:48:51 -07002399 Overlay::PipeSpecs pipeSpecs;
2400 pipeSpecs.formatClass = isYuvBuffer(hnd) ?
2401 Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
2402 pipeSpecs.needsScaling = qhwc::needsScaling(layer) or
2403 (qdutils::MDPVersion::getInstance().is8x26() and
2404 ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres > 1024);
2405 pipeSpecs.dpy = mDpy;
2406 pipeSpecs.fb = false;
2407 pipeSpecs.numActiveDisplays = ctx->numActiveDisplays;
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -08002408
Saurabh Shah8cc77712015-03-31 10:48:51 -07002409 pipe_info.index = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahc62f3982014-03-05 14:28:26 -08002410
Saurabh Shah8cc77712015-03-31 10:48:51 -07002411 if(pipe_info.index == ovutils::OV_INVALID) {
2412 ALOGD_IF(isDebug(), "%s: Unable to get pipe for layer %d of "\
2413 "format type %d", __FUNCTION__, index, formatType);
2414 return false;
2415 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002416 }
2417 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002418 return true;
2419}
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002420
radhakrishnac9a67412013-09-25 17:40:42 +05302421int MDPCompNonSplit::configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
2422 PipeLayerPair& PipeLayerPair) {
2423 MdpYUVPipeInfo& mdp_info =
2424 *(static_cast<MdpYUVPipeInfo*>(PipeLayerPair.pipeInfo));
2425 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Justin Philipd6166602014-08-12 13:42:21 +05302426 eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
radhakrishnac9a67412013-09-25 17:40:42 +05302427 eDest lDest = mdp_info.lIndex;
2428 eDest rDest = mdp_info.rIndex;
2429
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002430 return configureSourceSplit(ctx, layer, mDpy, mdpFlagsL, zOrder,
radhakrishnac9a67412013-09-25 17:40:42 +05302431 lDest, rDest, &PipeLayerPair.rot);
2432}
2433
Saurabh Shah88e4d272013-09-03 13:31:29 -07002434bool MDPCompNonSplit::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002435
Raj Kamal4393eaa2014-06-06 13:45:20 +05302436 if(!isEnabled() or !mModeOn) {
2437 ALOGD_IF(isDebug(),"%s: MDP Comp not enabled/configured", __FUNCTION__);
Prabhanjan Kandula08222fc2013-07-10 17:20:59 +05302438 return true;
2439 }
2440
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002441 overlay::Overlay& ov = *ctx->mOverlay;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002442 LayerProp *layerProp = ctx->layerProp[mDpy];
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002443
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002444 int numHwLayers = ctx->listStats[mDpy].numAppLayers;
2445 for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ )
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002446 {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002447 if(mCurrentFrame.isFBComposed[i]) continue;
2448
Naseer Ahmed5b6708a2012-08-02 13:46:08 -07002449 hwc_layer_1_t *layer = &list->hwLayers[i];
Saurabh Shahacf10202013-02-26 10:15:15 -08002450 private_handle_t *hnd = (private_handle_t *)layer->handle;
2451 if(!hnd) {
Sushil Chauhan897a9c32013-07-18 11:09:55 -07002452 if (!(layer->flags & HWC_COLOR_FILL)) {
2453 ALOGE("%s handle null", __FUNCTION__);
2454 return false;
2455 }
2456 // No PLAY for Color layer
2457 layerProp[i].mFlags &= ~HWC_MDPCOMP;
2458 continue;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002459 }
2460
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002461 int mdpIndex = mCurrentFrame.layerToMDP[i];
2462
Raj Kamal389d6e32014-08-04 14:43:24 +05302463 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit)
radhakrishnac9a67412013-09-25 17:40:42 +05302464 {
2465 MdpYUVPipeInfo& pipe_info =
2466 *(MdpYUVPipeInfo*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
2467 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
2468 ovutils::eDest indexL = pipe_info.lIndex;
2469 ovutils::eDest indexR = pipe_info.rIndex;
2470 int fd = hnd->fd;
Praveena Pachipulusud9443c72014-02-17 10:42:28 +05302471 uint32_t offset = (uint32_t)hnd->offset;
radhakrishnac9a67412013-09-25 17:40:42 +05302472 if(rot) {
2473 rot->queueBuffer(fd, offset);
2474 fd = rot->getDstMemId();
2475 offset = rot->getDstOffset();
2476 }
2477 if(indexL != ovutils::OV_INVALID) {
2478 ovutils::eDest destL = (ovutils::eDest)indexL;
2479 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2480 using pipe: %d", __FUNCTION__, layer, hnd, indexL );
2481 if (!ov.queueBuffer(fd, offset, destL)) {
2482 ALOGE("%s: queueBuffer failed for display:%d",
2483 __FUNCTION__, mDpy);
2484 return false;
2485 }
2486 }
2487
2488 if(indexR != ovutils::OV_INVALID) {
2489 ovutils::eDest destR = (ovutils::eDest)indexR;
2490 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2491 using pipe: %d", __FUNCTION__, layer, hnd, indexR );
2492 if (!ov.queueBuffer(fd, offset, destR)) {
2493 ALOGE("%s: queueBuffer failed for display:%d",
2494 __FUNCTION__, mDpy);
2495 return false;
2496 }
2497 }
2498 }
2499 else{
2500 MdpPipeInfoNonSplit& pipe_info =
Saurabh Shah88e4d272013-09-03 13:31:29 -07002501 *(MdpPipeInfoNonSplit*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
radhakrishnac9a67412013-09-25 17:40:42 +05302502 ovutils::eDest dest = pipe_info.index;
2503 if(dest == ovutils::OV_INVALID) {
2504 ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, dest);
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002505 return false;
radhakrishnac9a67412013-09-25 17:40:42 +05302506 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002507
radhakrishnac9a67412013-09-25 17:40:42 +05302508 if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
2509 continue;
2510 }
2511
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002512 int fd = hnd->fd;
2513 uint32_t offset = (uint32_t)hnd->offset;
2514 int index = ctx->mPtorInfo.getPTORArrayIndex(i);
2515 if (!mDpy && (index != -1)) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07002516 hnd = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002517 fd = hnd->fd;
Sushil Chauhan875a92e2014-07-25 12:20:23 -07002518 offset = 0;
Sushil Chauhandefd3522014-05-13 18:17:12 -07002519 }
2520
radhakrishnac9a67412013-09-25 17:40:42 +05302521 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2522 using pipe: %d", __FUNCTION__, layer,
2523 hnd, dest );
2524
radhakrishnac9a67412013-09-25 17:40:42 +05302525 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
2526 if(rot) {
2527 if(!rot->queueBuffer(fd, offset))
2528 return false;
2529 fd = rot->getDstMemId();
2530 offset = rot->getDstOffset();
2531 }
2532
2533 if (!ov.queueBuffer(fd, offset, dest)) {
2534 ALOGE("%s: queueBuffer failed for display:%d ",
2535 __FUNCTION__, mDpy);
2536 return false;
2537 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002538 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002539
2540 layerProp[i].mFlags &= ~HWC_MDPCOMP;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002541 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002542 return true;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002543}
2544
Saurabh Shah88e4d272013-09-03 13:31:29 -07002545//=============MDPCompSplit===================================================
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002546
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002547void MDPCompSplit::adjustForSourceSplit(hwc_context_t *ctx,
radhakrishnac9a67412013-09-25 17:40:42 +05302548 hwc_display_contents_1_t* list){
2549 //if 4kx2k yuv layer is totally present in either in left half
2550 //or right half then try splitting the yuv layer to avoid decimation
radhakrishnac9a67412013-09-25 17:40:42 +05302551 const int lSplit = getLeftSplit(ctx, mDpy);
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302552 if(mCurrentFrame.fbZ >= 0) {
2553 for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
2554 index++) {
2555 if(!mCurrentFrame.isFBComposed[index]) {
2556 if(mdpNextZOrder == mCurrentFrame.fbZ) {
2557 mdpNextZOrder++;
2558 }
2559 mdpNextZOrder++;
2560 hwc_layer_1_t* layer = &list->hwLayers[index];
2561 private_handle_t *hnd = (private_handle_t *)layer->handle;
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002562 if(isYUVSplitNeeded(hnd) ||
2563 (needs3DComposition(ctx,mDpy) &&
2564 get3DFormat(hnd) != HAL_NO_3D)) {
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302565 hwc_rect_t dst = layer->displayFrame;
2566 if((dst.left > lSplit) || (dst.right < lSplit)) {
2567 mCurrentFrame.mdpCount += 1;
2568 }
2569 if(mdpNextZOrder <= mCurrentFrame.fbZ)
2570 mCurrentFrame.fbZ += 1;
2571 mdpNextZOrder++;
2572 }
2573 }
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002574 }
radhakrishnac9a67412013-09-25 17:40:42 +05302575 }
2576}
2577
Saurabh Shah88e4d272013-09-03 13:31:29 -07002578bool MDPCompSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
Saurabh Shahc62f3982014-03-05 14:28:26 -08002579 MdpPipeInfoSplit& pipe_info) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002580
Saurabh Shahc62f3982014-03-05 14:28:26 -08002581 const int lSplit = getLeftSplit(ctx, mDpy);
2582 private_handle_t *hnd = (private_handle_t *)layer->handle;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002583 hwc_rect_t dst = layer->displayFrame;
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002584 pipe_info.lIndex = ovutils::OV_INVALID;
2585 pipe_info.rIndex = ovutils::OV_INVALID;
2586
Saurabh Shahc62f3982014-03-05 14:28:26 -08002587 Overlay::PipeSpecs pipeSpecs;
2588 pipeSpecs.formatClass = isYuvBuffer(hnd) ?
2589 Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
2590 pipeSpecs.needsScaling = qhwc::needsScalingWithSplit(ctx, layer, mDpy);
2591 pipeSpecs.dpy = mDpy;
2592 pipeSpecs.mixer = Overlay::MIXER_LEFT;
2593 pipeSpecs.fb = false;
2594
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08002595 // Acquire pipe only for the updating half
2596 hwc_rect_t l_roi = ctx->listStats[mDpy].lRoi;
2597 hwc_rect_t r_roi = ctx->listStats[mDpy].rRoi;
2598
2599 if (dst.left < lSplit && isValidRect(getIntersection(dst, l_roi))) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002600 pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002601 if(pipe_info.lIndex == ovutils::OV_INVALID)
2602 return false;
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002603 }
2604
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08002605 if(dst.right > lSplit && isValidRect(getIntersection(dst, r_roi))) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002606 pipeSpecs.mixer = Overlay::MIXER_RIGHT;
2607 pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002608 if(pipe_info.rIndex == ovutils::OV_INVALID)
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002609 return false;
2610 }
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002611
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002612 return true;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002613}
2614
Saurabh Shah88e4d272013-09-03 13:31:29 -07002615bool MDPCompSplit::allocLayerPipes(hwc_context_t *ctx,
Saurabh Shahe51f8ca2013-05-06 17:26:16 -07002616 hwc_display_contents_1_t* list) {
Saurabh Shah8cc77712015-03-31 10:48:51 -07002617 for(uint32_t formatType = FORMAT_YUV; formatType < FORMAT_MAX;
2618 formatType++) {
2619 for(int index = 0 ; index < mCurrentFrame.layerCount; index++) {
2620 if(mCurrentFrame.isFBComposed[index]) continue;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002621
Saurabh Shah8cc77712015-03-31 10:48:51 -07002622 hwc_layer_1_t* layer = &list->hwLayers[index];
2623 private_handle_t *hnd = (private_handle_t *)layer->handle;
2624 if(formatType == FORMAT_YUV && !isYuvBuffer(hnd))
2625 continue;
2626 if(formatType == FORMAT_RGB && isYuvBuffer(hnd))
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002627 continue;
2628
Saurabh Shah8cc77712015-03-31 10:48:51 -07002629 hwc_rect_t dst = layer->displayFrame;
2630 const int lSplit = getLeftSplit(ctx, mDpy);
2631 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
2632 if((dst.left > lSplit)||(dst.right < lSplit)){
2633 if(allocSplitVGPipes(ctx, index)){
2634 continue;
2635 }
2636 }
2637 }
2638 //XXX: Check for forced 2D composition
2639 if(needs3DComposition(ctx, mDpy) && get3DFormat(hnd) != HAL_NO_3D)
2640 if(allocSplitVGPipes(ctx,index))
2641 continue;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002642
Saurabh Shah8cc77712015-03-31 10:48:51 -07002643 int mdpIndex = mCurrentFrame.layerToMDP[index];
2644 PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
2645 info.pipeInfo = new MdpPipeInfoSplit;
2646 info.rot = NULL;
2647 MdpPipeInfoSplit& pipe_info = *(MdpPipeInfoSplit*)info.pipeInfo;
2648
2649 if(!acquireMDPPipes(ctx, layer, pipe_info)) {
2650 ALOGD_IF(isDebug(), "%s: Unable to get pipe for layer %d of "\
2651 "format type %d", __FUNCTION__, index, formatType);
2652 return false;
2653 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002654 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002655 }
2656 return true;
2657}
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002658
radhakrishnac9a67412013-09-25 17:40:42 +05302659int MDPCompSplit::configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
2660 PipeLayerPair& PipeLayerPair) {
2661 const int lSplit = getLeftSplit(ctx, mDpy);
2662 hwc_rect_t dst = layer->displayFrame;
2663 if((dst.left > lSplit)||(dst.right < lSplit)){
2664 MdpYUVPipeInfo& mdp_info =
2665 *(static_cast<MdpYUVPipeInfo*>(PipeLayerPair.pipeInfo));
2666 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Justin Philipd6166602014-08-12 13:42:21 +05302667 eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
radhakrishnac9a67412013-09-25 17:40:42 +05302668 eDest lDest = mdp_info.lIndex;
2669 eDest rDest = mdp_info.rIndex;
2670
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002671 return configureSourceSplit(ctx, layer, mDpy, mdpFlagsL, zOrder,
radhakrishnac9a67412013-09-25 17:40:42 +05302672 lDest, rDest, &PipeLayerPair.rot);
2673 }
2674 else{
2675 return configure(ctx, layer, PipeLayerPair);
2676 }
2677}
2678
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002679/*
2680 * Configures pipe(s) for MDP composition
2681 */
Saurabh Shah88e4d272013-09-03 13:31:29 -07002682int MDPCompSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
Saurabh Shah67a38c32013-06-10 16:23:15 -07002683 PipeLayerPair& PipeLayerPair) {
Saurabh Shah88e4d272013-09-03 13:31:29 -07002684 MdpPipeInfoSplit& mdp_info =
2685 *(static_cast<MdpPipeInfoSplit*>(PipeLayerPair.pipeInfo));
Saurabh Shahacf10202013-02-26 10:15:15 -08002686 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Justin Philipd6166602014-08-12 13:42:21 +05302687 eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shahacf10202013-02-26 10:15:15 -08002688 eDest lDest = mdp_info.lIndex;
2689 eDest rDest = mdp_info.rIndex;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002690
2691 ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
Jeykumar Sankaran39305802014-12-12 17:55:57 -08002692 "dest_pipeR: %d",__FUNCTION__, layer, zOrder, lDest, rDest);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002693
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002694 return configureSplit(ctx, layer, mDpy, mdpFlagsL, zOrder, lDest,
Jeykumar Sankaran39305802014-12-12 17:55:57 -08002695 rDest, &PipeLayerPair.rot);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002696}
2697
Saurabh Shah88e4d272013-09-03 13:31:29 -07002698bool MDPCompSplit::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002699
Raj Kamal4393eaa2014-06-06 13:45:20 +05302700 if(!isEnabled() or !mModeOn) {
2701 ALOGD_IF(isDebug(),"%s: MDP Comp not enabled/configured", __FUNCTION__);
Prabhanjan Kandula08222fc2013-07-10 17:20:59 +05302702 return true;
2703 }
2704
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002705 overlay::Overlay& ov = *ctx->mOverlay;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002706 LayerProp *layerProp = ctx->layerProp[mDpy];
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002707
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002708 int numHwLayers = ctx->listStats[mDpy].numAppLayers;
2709 for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ )
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002710 {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002711 if(mCurrentFrame.isFBComposed[i]) continue;
2712
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002713 hwc_layer_1_t *layer = &list->hwLayers[i];
Saurabh Shahacf10202013-02-26 10:15:15 -08002714 private_handle_t *hnd = (private_handle_t *)layer->handle;
2715 if(!hnd) {
2716 ALOGE("%s handle null", __FUNCTION__);
2717 return false;
2718 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002719
2720 if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
2721 continue;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002722 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002723
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002724 int mdpIndex = mCurrentFrame.layerToMDP[i];
2725
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002726 if((isYUVSplitNeeded(hnd) && sEnableYUVsplit) ||
2727 (needs3DComposition(ctx, mDpy) && get3DFormat(hnd) != HAL_NO_3D))
radhakrishnac9a67412013-09-25 17:40:42 +05302728 {
2729 MdpYUVPipeInfo& pipe_info =
2730 *(MdpYUVPipeInfo*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
2731 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
2732 ovutils::eDest indexL = pipe_info.lIndex;
2733 ovutils::eDest indexR = pipe_info.rIndex;
2734 int fd = hnd->fd;
Praveena Pachipulusud9443c72014-02-17 10:42:28 +05302735 uint32_t offset = (uint32_t)hnd->offset;
radhakrishnac9a67412013-09-25 17:40:42 +05302736 if(rot) {
2737 rot->queueBuffer(fd, offset);
2738 fd = rot->getDstMemId();
2739 offset = rot->getDstOffset();
2740 }
2741 if(indexL != ovutils::OV_INVALID) {
2742 ovutils::eDest destL = (ovutils::eDest)indexL;
2743 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2744 using pipe: %d", __FUNCTION__, layer, hnd, indexL );
2745 if (!ov.queueBuffer(fd, offset, destL)) {
2746 ALOGE("%s: queueBuffer failed for display:%d",
2747 __FUNCTION__, mDpy);
2748 return false;
2749 }
2750 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002751
radhakrishnac9a67412013-09-25 17:40:42 +05302752 if(indexR != ovutils::OV_INVALID) {
2753 ovutils::eDest destR = (ovutils::eDest)indexR;
2754 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2755 using pipe: %d", __FUNCTION__, layer, hnd, indexR );
2756 if (!ov.queueBuffer(fd, offset, destR)) {
2757 ALOGE("%s: queueBuffer failed for display:%d",
2758 __FUNCTION__, mDpy);
2759 return false;
2760 }
Saurabh Shaha9da08f2013-07-03 13:27:53 -07002761 }
2762 }
radhakrishnac9a67412013-09-25 17:40:42 +05302763 else{
2764 MdpPipeInfoSplit& pipe_info =
2765 *(MdpPipeInfoSplit*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
2766 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
Saurabh Shaha9da08f2013-07-03 13:27:53 -07002767
radhakrishnac9a67412013-09-25 17:40:42 +05302768 ovutils::eDest indexL = pipe_info.lIndex;
2769 ovutils::eDest indexR = pipe_info.rIndex;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002770
radhakrishnac9a67412013-09-25 17:40:42 +05302771 int fd = hnd->fd;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002772 uint32_t offset = (uint32_t)hnd->offset;
2773 int index = ctx->mPtorInfo.getPTORArrayIndex(i);
2774 if (!mDpy && (index != -1)) {
2775 hnd = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
2776 fd = hnd->fd;
Sushil Chauhan875a92e2014-07-25 12:20:23 -07002777 offset = 0;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002778 }
radhakrishnac9a67412013-09-25 17:40:42 +05302779
Tatenda Chipeperekwa88fe6352014-04-14 10:36:06 -07002780 if(ctx->mAD->draw(ctx, fd, offset)) {
2781 fd = ctx->mAD->getDstFd();
2782 offset = ctx->mAD->getDstOffset();
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002783 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002784
radhakrishnac9a67412013-09-25 17:40:42 +05302785 if(rot) {
2786 rot->queueBuffer(fd, offset);
2787 fd = rot->getDstMemId();
2788 offset = rot->getDstOffset();
2789 }
2790
2791 //************* play left mixer **********
2792 if(indexL != ovutils::OV_INVALID) {
2793 ovutils::eDest destL = (ovutils::eDest)indexL;
2794 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2795 using pipe: %d", __FUNCTION__, layer, hnd, indexL );
2796 if (!ov.queueBuffer(fd, offset, destL)) {
2797 ALOGE("%s: queueBuffer failed for left mixer",
2798 __FUNCTION__);
2799 return false;
2800 }
2801 }
2802
2803 //************* play right mixer **********
2804 if(indexR != ovutils::OV_INVALID) {
2805 ovutils::eDest destR = (ovutils::eDest)indexR;
2806 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2807 using pipe: %d", __FUNCTION__, layer, hnd, indexR );
2808 if (!ov.queueBuffer(fd, offset, destR)) {
2809 ALOGE("%s: queueBuffer failed for right mixer",
2810 __FUNCTION__);
2811 return false;
2812 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002813 }
2814 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002815
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002816 layerProp[i].mFlags &= ~HWC_MDPCOMP;
2817 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002818
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002819 return true;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002820}
Saurabh Shahab47c692014-02-12 18:45:57 -08002821
2822//================MDPCompSrcSplit==============================================
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08002823
2824bool MDPCompSrcSplit::validateAndApplyROI(hwc_context_t *ctx,
2825 hwc_display_contents_1_t* list) {
2826 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
2827 hwc_rect_t visibleRect = ctx->listStats[mDpy].lRoi;
2828
2829 for(int i = numAppLayers - 1; i >= 0; i--) {
2830 if(!isValidRect(visibleRect)) {
2831 mCurrentFrame.drop[i] = true;
2832 mCurrentFrame.dropCount++;
2833 continue;
2834 }
2835
2836 const hwc_layer_1_t* layer = &list->hwLayers[i];
2837 hwc_rect_t dstRect = layer->displayFrame;
2838 hwc_rect_t res = getIntersection(visibleRect, dstRect);
2839
2840 if(!isValidRect(res)) {
2841 mCurrentFrame.drop[i] = true;
2842 mCurrentFrame.dropCount++;
2843 } else {
2844 /* Reset frame ROI when any layer which needs scaling also needs ROI
2845 * cropping */
2846 if(!isSameRect(res, dstRect) && needsScaling (layer)) {
2847 ALOGI("%s: Resetting ROI due to scaling", __FUNCTION__);
2848 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
2849 mCurrentFrame.dropCount = 0;
2850 return false;
2851 }
2852
2853 /* deduct any opaque region from visibleRect */
2854 if (layer->blending == HWC_BLENDING_NONE &&
2855 layer->planeAlpha == 0xFF)
2856 visibleRect = deductRect(visibleRect, res);
2857 }
2858 }
2859 return true;
2860}
2861
2862/*
2863 * HW Limitation: ping pong split can always split the ping pong output
2864 * equally across two DSI's. So the ROI programmed should be of equal width
2865 * for both the halves
2866 */
2867void MDPCompSrcSplit::generateROI(hwc_context_t *ctx,
2868 hwc_display_contents_1_t* list) {
2869 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
2870
2871
2872 if(!canPartialUpdate(ctx, list))
2873 return;
2874
2875 struct hwc_rect roi = (struct hwc_rect){0, 0, 0, 0};
2876 hwc_rect fullFrame = (struct hwc_rect) {0, 0,(int)ctx->dpyAttr[mDpy].xres,
2877 (int)ctx->dpyAttr[mDpy].yres};
2878
2879 for(int index = 0; index < numAppLayers; index++ ) {
2880 hwc_layer_1_t* layer = &list->hwLayers[index];
2881
2882 // If we have a RGB layer which needs rotation, no partial update
2883 if(!isYuvBuffer((private_handle_t *)layer->handle) && layer->transform)
2884 return;
2885
2886 if ((mCachedFrame.hnd[index] != layer->handle) ||
2887 isYuvBuffer((private_handle_t *)layer->handle)) {
2888 hwc_rect_t dst = layer->displayFrame;
2889 hwc_rect_t updatingRect = dst;
2890
2891#ifdef QCOM_BSP
2892 if(!needsScaling(layer) && !layer->transform)
2893 {
2894 hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
2895 int x_off = dst.left - src.left;
2896 int y_off = dst.top - src.top;
2897 updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
2898 }
2899#endif
2900
2901 roi = getUnion(roi, updatingRect);
2902 }
2903 }
2904
2905 /* No layer is updating. Still SF wants a refresh.*/
2906 if(!isValidRect(roi))
2907 return;
2908
2909 roi = expandROIFromMidPoint(roi, fullFrame);
2910
2911 hwc_rect lFrame = fullFrame;
2912 lFrame.right /= 2;
2913 hwc_rect lRoi = getIntersection(roi, lFrame);
2914
2915 // Align ROI coordinates to panel restrictions
2916 lRoi = getSanitizeROI(lRoi, lFrame);
2917
2918 hwc_rect rFrame = fullFrame;
2919 rFrame.left = lFrame.right;
2920 hwc_rect rRoi = getIntersection(roi, rFrame);
2921
2922 // Align ROI coordinates to panel restrictions
2923 rRoi = getSanitizeROI(rRoi, rFrame);
2924
2925 roi = getUnion(lRoi, rRoi);
2926
2927 ctx->listStats[mDpy].lRoi = roi;
2928 if(!validateAndApplyROI(ctx, list))
2929 resetROI(ctx, mDpy);
2930
2931 ALOGD_IF(isDebug(),"%s: generated ROI: [%d, %d, %d, %d] [%d, %d, %d, %d]",
2932 __FUNCTION__,
2933 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
2934 ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom,
2935 ctx->listStats[mDpy].rRoi.left, ctx->listStats[mDpy].rRoi.top,
2936 ctx->listStats[mDpy].rRoi.right, ctx->listStats[mDpy].rRoi.bottom);
2937}
2938
Saurabh Shahab47c692014-02-12 18:45:57 -08002939bool MDPCompSrcSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
Saurabh Shahc62f3982014-03-05 14:28:26 -08002940 MdpPipeInfoSplit& pipe_info) {
Saurabh Shahab47c692014-02-12 18:45:57 -08002941 private_handle_t *hnd = (private_handle_t *)layer->handle;
2942 hwc_rect_t dst = layer->displayFrame;
2943 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
2944 pipe_info.lIndex = ovutils::OV_INVALID;
2945 pipe_info.rIndex = ovutils::OV_INVALID;
2946
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08002947 if(qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() && !mDpy)
2948 trimAgainstROI(ctx,crop, dst);
2949
Saurabh Shahab47c692014-02-12 18:45:57 -08002950 //If 2 pipes are staged on a single stage of a mixer, then the left pipe
2951 //should have a higher priority than the right one. Pipe priorities are
2952 //starting with VG0, VG1 ... , RGB0 ..., DMA1
Saurabh Shahab47c692014-02-12 18:45:57 -08002953
Saurabh Shahc62f3982014-03-05 14:28:26 -08002954 Overlay::PipeSpecs pipeSpecs;
2955 pipeSpecs.formatClass = isYuvBuffer(hnd) ?
2956 Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
2957 pipeSpecs.needsScaling = qhwc::needsScaling(layer);
2958 pipeSpecs.dpy = mDpy;
2959 pipeSpecs.fb = false;
2960
Saurabh Shahab47c692014-02-12 18:45:57 -08002961 //1 pipe by default for a layer
Saurabh Shahc62f3982014-03-05 14:28:26 -08002962 pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahab47c692014-02-12 18:45:57 -08002963 if(pipe_info.lIndex == ovutils::OV_INVALID) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002964 return false;
Saurabh Shahab47c692014-02-12 18:45:57 -08002965 }
2966
Saurabh Shahea7a01d2014-05-22 17:45:36 -07002967 /* Use 2 pipes IF
2968 a) Layer's crop width is > 2048 or
2969 b) Layer's dest width > 2048 or
2970 c) On primary, driver has indicated with caps to split always. This is
2971 based on an empirically derived value of panel height. Applied only
2972 if the layer's width is > mixer's width
2973 */
2974
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +05302975 MDPVersion& mdpHw = MDPVersion::getInstance();
Saurabh Shahea7a01d2014-05-22 17:45:36 -07002976 bool primarySplitAlways = (mDpy == HWC_DISPLAY_PRIMARY) and
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +05302977 mdpHw.isSrcSplitAlways();
Saurabh Shah514759d2014-11-11 18:02:24 -08002978 const uint32_t lSplit = getLeftSplit(ctx, mDpy);
2979 const uint32_t dstWidth = dst.right - dst.left;
2980 const uint32_t dstHeight = dst.bottom - dst.top;
Saurabh Shah05f4e222015-02-05 14:36:22 -08002981 uint32_t cropWidth = has90Transform(layer) ? crop.bottom - crop.top :
Saurabh Shah189f23d2014-09-26 17:21:00 -07002982 crop.right - crop.left;
Saurabh Shah05f4e222015-02-05 14:36:22 -08002983 uint32_t cropHeight = has90Transform(layer) ? crop.right - crop.left :
Saurabh Shah514759d2014-11-11 18:02:24 -08002984 crop.bottom - crop.top;
2985 //Approximation to actual clock, ignoring the common factors in pipe and
2986 //mixer cases like line_time
2987 const uint32_t layerClock = getLayerClock(dstWidth, dstHeight, cropHeight);
2988 const uint32_t mixerClock = lSplit;
Saurabh Shahea7a01d2014-05-22 17:45:36 -07002989
Saurabh Shah05f4e222015-02-05 14:36:22 -08002990 const uint32_t downscale = getRotDownscale(ctx, layer);
2991 if(downscale) {
2992 cropWidth /= downscale;
2993 cropHeight /= downscale;
2994 }
2995
Jeykumar Sankaran39305802014-12-12 17:55:57 -08002996 if(dstWidth > mdpHw.getMaxPipeWidth() or
2997 cropWidth > mdpHw.getMaxPipeWidth() or
Saurabh Shah514759d2014-11-11 18:02:24 -08002998 (primarySplitAlways and
2999 (cropWidth > lSplit or layerClock > mixerClock))) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08003000 pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahab47c692014-02-12 18:45:57 -08003001 if(pipe_info.rIndex == ovutils::OV_INVALID) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08003002 return false;
Saurabh Shahdd8237a2014-02-28 14:29:09 -08003003 }
3004
Jeykumar Sankaran89e23ab2015-01-28 15:57:46 -08003005 if(ctx->mOverlay->needsPrioritySwap(pipe_info.lIndex,
3006 pipe_info.rIndex)) {
Saurabh Shahdd8237a2014-02-28 14:29:09 -08003007 qhwc::swap(pipe_info.lIndex, pipe_info.rIndex);
Saurabh Shahab47c692014-02-12 18:45:57 -08003008 }
3009 }
3010
3011 return true;
3012}
3013
Saurabh Shahab47c692014-02-12 18:45:57 -08003014int MDPCompSrcSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
3015 PipeLayerPair& PipeLayerPair) {
3016 private_handle_t *hnd = (private_handle_t *)layer->handle;
3017 if(!hnd) {
3018 ALOGE("%s: layer handle is NULL", __FUNCTION__);
3019 return -1;
3020 }
3021 MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
3022 MdpPipeInfoSplit& mdp_info =
3023 *(static_cast<MdpPipeInfoSplit*>(PipeLayerPair.pipeInfo));
3024 Rotator **rot = &PipeLayerPair.rot;
3025 eZorder z = static_cast<eZorder>(mdp_info.zOrder);
Saurabh Shahab47c692014-02-12 18:45:57 -08003026 eDest lDest = mdp_info.lIndex;
3027 eDest rDest = mdp_info.rIndex;
3028 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
3029 hwc_rect_t dst = layer->displayFrame;
3030 int transform = layer->transform;
3031 eTransform orient = static_cast<eTransform>(transform);
Saurabh Shahab47c692014-02-12 18:45:57 -08003032 int rotFlags = ROT_FLAGS_NONE;
Sushil Chauhan65e26302015-01-14 10:48:57 -08003033 uint32_t format = ovutils::getMdpFormat(hnd->format, hnd->flags);
Saurabh Shahab47c692014-02-12 18:45:57 -08003034 Whf whf(getWidth(hnd), getHeight(hnd), format, hnd->size);
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05003035 eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shahab47c692014-02-12 18:45:57 -08003036
3037 ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
3038 "dest_pipeR: %d",__FUNCTION__, layer, z, lDest, rDest);
3039
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08003040 if(qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() && !mDpy) {
3041 /* MDP driver crops layer coordinates against ROI in Non-Split
3042 * and Split MDP comp. But HWC needs to crop them for source split.
3043 * Reason: 1) Source split is efficient only when the final effective
3044 * load is distributed evenly across mixers.
3045 * 2) We have to know the effective width of the layer that
3046 * the ROI needs to find the no. of pipes the layer needs.
3047 */
3048 trimAgainstROI(ctx, crop, dst);
3049 }
3050
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05003051 if(needs3DComposition(ctx, mDpy) &&
3052 get3DFormat(hnd) != HAL_NO_3D){
3053 return configure3DVideo(ctx, layer, mDpy, mdpFlags, z, lDest,
3054 rDest, &PipeLayerPair.rot);
3055 }
3056
Saurabh Shahab47c692014-02-12 18:45:57 -08003057 // Handle R/B swap
3058 if (layer->flags & HWC_FORMAT_RB_SWAP) {
3059 if (hnd->format == HAL_PIXEL_FORMAT_RGBA_8888)
3060 whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRA_8888);
3061 else if (hnd->format == HAL_PIXEL_FORMAT_RGBX_8888)
3062 whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
3063 }
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07003064 // update source crop and destination position of AIV video layer.
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07003065 if(ctx->listStats[mDpy].mAIVVideoMode && isYuvBuffer(hnd)) {
3066 updateCoordinates(ctx, crop, dst, mDpy);
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07003067 }
Ramkumar Radhakrishnana5c72872014-08-28 19:04:18 -07003068 /* Calculate the external display position based on MDP downscale,
3069 ActionSafe, and extorientation features. */
3070 calcExtDisplayPosition(ctx, hnd, mDpy, crop, dst, transform, orient);
Saurabh Shahab47c692014-02-12 18:45:57 -08003071
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003072 int downscale = getRotDownscale(ctx, layer);
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003073 setMdpFlags(ctx, layer, mdpFlags, downscale, transform);
Saurabh Shahab47c692014-02-12 18:45:57 -08003074
3075 if(lDest != OV_INVALID && rDest != OV_INVALID) {
3076 //Enable overfetch
Saurabh Shah97e2d802014-04-14 18:03:54 -07003077 setMdpFlags(mdpFlags, OV_MDSS_MDP_DUAL_PIPE);
Saurabh Shahab47c692014-02-12 18:45:57 -08003078 }
3079
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003080 if((has90Transform(layer) or downscale) and isRotationDoable(ctx, hnd)) {
Saurabh Shahab47c692014-02-12 18:45:57 -08003081 (*rot) = ctx->mRotMgr->getNext();
3082 if((*rot) == NULL) return -1;
Saurabh Shah39240c92014-03-31 10:31:42 -07003083 ctx->mLayerRotMap[mDpy]->add(layer, *rot);
Saurabh Shah1bd5b6f2014-05-19 12:23:13 -07003084 //If the video is using a single pipe, enable BWC
3085 if(rDest == OV_INVALID) {
Saurabh Shahcd018352014-11-11 13:54:19 -08003086 BwcPM::setBwc(ctx, mDpy, hnd, crop, dst, transform, downscale,
3087 mdpFlags);
Saurabh Shah1bd5b6f2014-05-19 12:23:13 -07003088 }
Saurabh Shahab47c692014-02-12 18:45:57 -08003089 //Configure rotator for pre-rotation
Saurabh Shah97e2d802014-04-14 18:03:54 -07003090 if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale) < 0) {
Saurabh Shahab47c692014-02-12 18:45:57 -08003091 ALOGE("%s: configRotator failed!", __FUNCTION__);
3092 return -1;
3093 }
Saurabh Shah8ec9b5e2014-06-30 14:37:17 -07003094 updateSource(orient, whf, crop, *rot);
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003095 rotFlags |= ovutils::ROT_PREROTATED;
Saurabh Shahab47c692014-02-12 18:45:57 -08003096 }
3097
3098 //If 2 pipes being used, divide layer into half, crop and dst
3099 hwc_rect_t cropL = crop;
3100 hwc_rect_t cropR = crop;
3101 hwc_rect_t dstL = dst;
3102 hwc_rect_t dstR = dst;
3103 if(lDest != OV_INVALID && rDest != OV_INVALID) {
3104 cropL.right = (crop.right + crop.left) / 2;
3105 cropR.left = cropL.right;
3106 sanitizeSourceCrop(cropL, cropR, hnd);
3107
Saurabh Shahb729b192014-08-15 18:04:24 -07003108 bool cropSwap = false;
Saurabh Shahab47c692014-02-12 18:45:57 -08003109 //Swap crops on H flip since 2 pipes are being used
3110 if((orient & OVERLAY_TRANSFORM_FLIP_H) && (*rot) == NULL) {
3111 hwc_rect_t tmp = cropL;
3112 cropL = cropR;
3113 cropR = tmp;
Saurabh Shahb729b192014-08-15 18:04:24 -07003114 cropSwap = true;
Saurabh Shahab47c692014-02-12 18:45:57 -08003115 }
3116
Saurabh Shahb729b192014-08-15 18:04:24 -07003117 //cropSwap trick: If the src and dst widths are both odd, let us say
3118 //2507, then splitting both into half would cause left width to be 1253
3119 //and right 1254. If crop is swapped because of H flip, this will cause
3120 //left crop width to be 1254, whereas left dst width remains 1253, thus
3121 //inducing a scaling that is unaccounted for. To overcome that we add 1
3122 //to the dst width if there is a cropSwap. So if the original width was
3123 //2507, the left dst width will be 1254. Even if the original width was
3124 //even for ex: 2508, the left dst width will still remain 1254.
3125 dstL.right = (dst.right + dst.left + cropSwap) / 2;
Saurabh Shahab47c692014-02-12 18:45:57 -08003126 dstR.left = dstL.right;
3127 }
3128
3129 //For the mdp, since either we are pre-rotating or MDP does flips
3130 orient = OVERLAY_TRANSFORM_0;
3131 transform = 0;
3132
3133 //configure left pipe
3134 if(lDest != OV_INVALID) {
Saurabh Shah2c8ad052014-08-15 13:27:46 -07003135 PipeArgs pargL(mdpFlags, whf, z,
Saurabh Shahab47c692014-02-12 18:45:57 -08003136 static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
3137 (ovutils::eBlending) getBlending(layer->blending));
3138
3139 if(configMdp(ctx->mOverlay, pargL, orient,
3140 cropL, dstL, metadata, lDest) < 0) {
3141 ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
3142 return -1;
3143 }
3144 }
3145
3146 //configure right pipe
3147 if(rDest != OV_INVALID) {
Saurabh Shah2c8ad052014-08-15 13:27:46 -07003148 PipeArgs pargR(mdpFlags, whf, z,
Saurabh Shahab47c692014-02-12 18:45:57 -08003149 static_cast<eRotFlags>(rotFlags),
3150 layer->planeAlpha,
3151 (ovutils::eBlending) getBlending(layer->blending));
3152 if(configMdp(ctx->mOverlay, pargR, orient,
3153 cropR, dstR, metadata, rDest) < 0) {
3154 ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
3155 return -1;
3156 }
3157 }
3158
3159 return 0;
3160}
3161
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -08003162bool MDPComp::getPartialUpdatePref(hwc_context_t *ctx) {
3163 Locker::Autolock _l(ctx->mDrawLock);
3164 const int fbNum = Overlay::getFbForDpy(Overlay::DPY_PRIMARY);
3165 char path[MAX_SYSFS_FILE_PATH];
3166 snprintf (path, sizeof(path), "sys/class/graphics/fb%d/dyn_pu", fbNum);
3167 int fd = open(path, O_RDONLY);
3168 if(fd < 0) {
3169 ALOGE("%s: Failed to open sysfd node: %s", __FUNCTION__, path);
3170 return -1;
3171 }
3172 char value[4];
3173 ssize_t size_read = read(fd, value, sizeof(value)-1);
3174 if(size_read <= 0) {
3175 ALOGE("%s: Failed to read sysfd node: %s", __FUNCTION__, path);
3176 close(fd);
3177 return -1;
3178 }
3179 close(fd);
3180 value[size_read] = '\0';
3181 return atoi(value);
3182}
3183
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003184int MDPComp::setPartialUpdatePref(hwc_context_t *ctx, bool enable) {
3185 Locker::Autolock _l(ctx->mDrawLock);
3186 const int fbNum = Overlay::getFbForDpy(Overlay::DPY_PRIMARY);
3187 char path[MAX_SYSFS_FILE_PATH];
3188 snprintf (path, sizeof(path), "sys/class/graphics/fb%d/dyn_pu", fbNum);
3189 int fd = open(path, O_WRONLY);
3190 if(fd < 0) {
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -08003191 ALOGE("%s: Failed to open sysfd node: %s", __FUNCTION__, path);
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003192 return -1;
3193 }
3194 char value[4];
3195 snprintf(value, sizeof(value), "%d", (int)enable);
3196 ssize_t ret = write(fd, value, strlen(value));
3197 if(ret <= 0) {
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -08003198 ALOGE("%s: Failed to write to sysfd nodes: %s", __FUNCTION__, path);
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003199 close(fd);
3200 return -1;
3201 }
3202 close(fd);
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003203 return 0;
3204}
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08003205
3206bool MDPComp::loadPerfLib() {
3207 char perfLibPath[PROPERTY_VALUE_MAX] = {0};
3208 bool success = false;
3209 if((property_get("ro.vendor.extension_library", perfLibPath, NULL) <= 0)) {
3210 ALOGE("vendor library not set in ro.vendor.extension_library");
3211 return false;
3212 }
3213
3214 sLibPerfHint = dlopen(perfLibPath, RTLD_NOW);
3215 if(sLibPerfHint) {
3216 *(void **)&sPerfLockAcquire = dlsym(sLibPerfHint, "perf_lock_acq");
3217 *(void **)&sPerfLockRelease = dlsym(sLibPerfHint, "perf_lock_rel");
3218 if (!sPerfLockAcquire || !sPerfLockRelease) {
3219 ALOGE("Failed to load symbols for perfLock");
3220 dlclose(sLibPerfHint);
3221 sLibPerfHint = NULL;
3222 return false;
3223 }
3224 success = true;
3225 ALOGI("Successfully Loaded perf hint API's");
3226 } else {
3227 ALOGE("Failed to open %s : %s", perfLibPath, dlerror());
3228 }
3229 return success;
3230}
3231
3232void MDPComp::setPerfHint(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
3233 if ((sPerfHintWindow < 0) || mDpy || !sLibPerfHint) {
3234 return;
3235 }
3236 static int count = sPerfHintWindow;
3237 static int perflockFlag = 0;
3238
3239 /* Send hint to mpctl when single layer is updated
3240 * for a successful number of windows. Hint release
3241 * happens immediately upon multiple layer update.
3242 */
3243 if (onlyVideosUpdating(ctx, list)) {
3244 if(count) {
3245 count--;
3246 }
3247 } else {
3248 if (perflockFlag) {
3249 perflockFlag = 0;
3250 sPerfLockRelease(sPerfLockHandle);
3251 }
3252 count = sPerfHintWindow;
3253 }
3254 if (count == 0 && !perflockFlag) {
3255 int perfHint = 0x4501; // 45-display layer hint, 01-Enable
3256 sPerfLockHandle = sPerfLockAcquire(0 /*handle*/, 0/*duration*/,
3257 &perfHint, sizeof(perfHint)/sizeof(int));
Arun Kumar K.R8b927022015-02-24 12:34:21 -08003258 if(sPerfLockHandle > 0) {
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08003259 perflockFlag = 1;
3260 }
3261 }
3262}
3263
Naseer Ahmed7c958d42012-07-31 18:57:03 -07003264}; //namespace
3265