blob: b6193959b3f6a868cc51174ee610e68c9d4df937 [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 Shah88e4d272013-09-03 13:31:29 -070059MDPComp* MDPComp::getObject(hwc_context_t *ctx, const int& dpy) {
Saurabh Shah60e8bde2014-04-30 14:46:03 -070060 if(qdutils::MDPVersion::getInstance().isSrcSplit()) {
61 sSrcSplitEnabled = true;
62 return new MDPCompSrcSplit(dpy);
63 } else if(isDisplaySplit(ctx, dpy)) {
Saurabh Shah88e4d272013-09-03 13:31:29 -070064 return new MDPCompSplit(dpy);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -080065 }
Saurabh Shah88e4d272013-09-03 13:31:29 -070066 return new MDPCompNonSplit(dpy);
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -080067}
68
Jeykumar Sankaran85977e32013-02-25 17:06:08 -080069MDPComp::MDPComp(int dpy):mDpy(dpy){};
70
Jeykumar Sankaran6850ac62014-05-27 10:07:26 -070071void MDPComp::dump(android::String8& buf, hwc_context_t *ctx)
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -080072{
Jeykumar Sankaran3c6bb042013-08-15 14:01:04 -070073 if(mCurrentFrame.layerCount > MAX_NUM_APP_LAYERS)
74 return;
75
Jeykumar Sankaran85977e32013-02-25 17:06:08 -080076 dumpsys_log(buf,"HWC Map for Dpy: %s \n",
Jeykumar Sankaran27dee262013-08-01 17:09:54 -070077 (mDpy == 0) ? "\"PRIMARY\"" :
78 (mDpy == 1) ? "\"EXTERNAL\"" : "\"VIRTUAL\"");
Saurabh Shahe9bc60f2013-08-29 12:58:06 -070079 dumpsys_log(buf,"CURR_FRAME: layerCount:%2d mdpCount:%2d "
Arun Kumar K.R00b84792015-03-27 11:28:36 -070080 "fbCount:%2d dropCount:%2d\n", mCurrentFrame.layerCount,
81 mCurrentFrame.mdpCount, mCurrentFrame.fbCount, mCurrentFrame.dropCount);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -080082 dumpsys_log(buf,"needsFBRedraw:%3s pipesUsed:%2d MaxPipesPerMixer: %d \n",
83 (mCurrentFrame.needsRedraw? "YES" : "NO"),
84 mCurrentFrame.mdpCount, sMaxPipesPerMixer);
Jeykumar Sankaran6850ac62014-05-27 10:07:26 -070085 if(isDisplaySplit(ctx, mDpy)) {
86 dumpsys_log(buf, "Programmed ROI's: Left: [%d, %d, %d, %d] "
87 "Right: [%d, %d, %d, %d] \n",
88 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
89 ctx->listStats[mDpy].lRoi.right,
90 ctx->listStats[mDpy].lRoi.bottom,
91 ctx->listStats[mDpy].rRoi.left,ctx->listStats[mDpy].rRoi.top,
92 ctx->listStats[mDpy].rRoi.right,
93 ctx->listStats[mDpy].rRoi.bottom);
94 } else {
95 dumpsys_log(buf, "Programmed ROI: [%d, %d, %d, %d] \n",
96 ctx->listStats[mDpy].lRoi.left,ctx->listStats[mDpy].lRoi.top,
97 ctx->listStats[mDpy].lRoi.right,
98 ctx->listStats[mDpy].lRoi.bottom);
99 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800100 dumpsys_log(buf," --------------------------------------------- \n");
101 dumpsys_log(buf," listIdx | cached? | mdpIndex | comptype | Z \n");
102 dumpsys_log(buf," --------------------------------------------- \n");
103 for(int index = 0; index < mCurrentFrame.layerCount; index++ )
104 dumpsys_log(buf," %7d | %7s | %8d | %9s | %2d \n",
105 index,
106 (mCurrentFrame.isFBComposed[index] ? "YES" : "NO"),
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700107 mCurrentFrame.layerToMDP[index],
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800108 (mCurrentFrame.isFBComposed[index] ?
Arun Kumar K.R00b84792015-03-27 11:28:36 -0700109 (mCurrentFrame.drop[index] ?
110 ((mCurrentFrame.hwCursorIndex == index) ? "CURSOR": "DROP"):
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700111 (mCurrentFrame.needsRedraw ? "GLES" : "CACHE")) : "MDP"),
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800112 (mCurrentFrame.isFBComposed[index] ? mCurrentFrame.fbZ :
113 mCurrentFrame.mdpToLayer[mCurrentFrame.layerToMDP[index]].pipeInfo->zOrder));
114 dumpsys_log(buf,"\n");
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800115}
116
117bool MDPComp::init(hwc_context_t *ctx) {
118
119 if(!ctx) {
120 ALOGE("%s: Invalid hwc context!!",__FUNCTION__);
121 return false;
122 }
123
Saurabh Shah59562ff2014-09-30 16:13:12 -0700124 char property[PROPERTY_VALUE_MAX] = {0};
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800125
126 sEnabled = false;
Dileep Kumar Reddid8e601d2014-10-28 18:20:43 +0530127 if((ctx->mMDP.version >= qdutils::MDP_V4_0) &&
128 (property_get("persist.hwc.mdpcomp.enable", property, NULL) > 0) &&
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800129 (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
130 (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800131 sEnabled = true;
132 }
133
Jeykumar Sankaran24c199d2013-05-24 09:40:36 -0700134 sEnableMixedMode = true;
135 if((property_get("debug.mdpcomp.mixedmode.disable", property, NULL) > 0) &&
136 (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
137 (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
138 sEnableMixedMode = false;
139 }
140
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700141 qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
142
Saurabh Shah2fd8a252014-12-05 13:49:53 -0800143 sMaxPipesPerMixer = (int)mdpVersion.getBlendStages();
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700144 if(property_get("persist.hwc.mdpcomp.maxpermixer", property, "-1") > 0) {
Saurabh Shah85234ec2013-04-12 17:09:00 -0700145 int val = atoi(property);
146 if(val >= 0)
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700147 sMaxPipesPerMixer = min(val, sMaxPipesPerMixer);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800148 }
149
Saurabh Shahacec8e42014-11-25 11:07:04 -0800150 /* Maximum layers allowed to use MDP on secondary panels. If property
151 * doesn't exist, default to 1. Using the property it can be set to 0 or
152 * more.
153 */
154 if(property_get("persist.hwc.maxseclayers", property, "1") > 0) {
155 int val = atoi(property);
156 sMaxSecLayers = (val >= 0) ? val : 1;
157 sMaxSecLayers = min(sMaxSecLayers, sMaxPipesPerMixer);
158 }
159
Naseer Ahmedf40f2c82013-08-14 16:42:40 -0400160 if(ctx->mMDP.panel != MIPI_CMD_PANEL) {
Saurabh Shah59562ff2014-09-30 16:13:12 -0700161 sIdleInvalidator = IdleInvalidator::getInstance();
162 if(sIdleInvalidator->init(timeout_handler, ctx) < 0) {
163 delete sIdleInvalidator;
164 sIdleInvalidator = NULL;
Naseer Ahmedf40f2c82013-08-14 16:42:40 -0400165 }
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800166 }
radhakrishnac9a67412013-09-25 17:40:42 +0530167
Saurabh Shah7c727642014-06-02 15:47:14 -0700168 if(!qdutils::MDPVersion::getInstance().isSrcSplit() &&
Saurabh Shahc46cf9d2014-07-02 15:22:34 -0700169 !qdutils::MDPVersion::getInstance().isRotDownscaleEnabled() &&
Saurabh Shah7c727642014-06-02 15:47:14 -0700170 property_get("persist.mdpcomp.4k2kSplit", property, "0") > 0 &&
171 (!strncmp(property, "1", PROPERTY_VALUE_MAX) ||
172 !strncasecmp(property,"true", PROPERTY_VALUE_MAX))) {
Raj Kamal389d6e32014-08-04 14:43:24 +0530173 sEnableYUVsplit = true;
radhakrishnac9a67412013-09-25 17:40:42 +0530174 }
Sushil Chauhandefd3522014-05-13 18:17:12 -0700175
Dileep Kumar Reddic6ef3472014-09-24 19:07:08 +0530176 bool defaultPTOR = false;
177 //Enable PTOR when "persist.hwc.ptor.enable" is not defined for
178 //8x16 and 8x39 targets by default
179 if((property_get("persist.hwc.ptor.enable", property, NULL) <= 0) &&
180 (qdutils::MDPVersion::getInstance().is8x16() ||
181 qdutils::MDPVersion::getInstance().is8x39())) {
182 defaultPTOR = true;
183 }
184
185 if (defaultPTOR || (!strncasecmp(property, "true", PROPERTY_VALUE_MAX)) ||
186 (!strncmp(property, "1", PROPERTY_VALUE_MAX ))) {
Sushil Chauhandefd3522014-05-13 18:17:12 -0700187 ctx->mCopyBit[HWC_DISPLAY_PRIMARY] = new CopyBit(ctx,
188 HWC_DISPLAY_PRIMARY);
189 }
190
Dileep Kumar Reddi4070e932014-09-30 09:00:57 +0530191 if((property_get("persist.mdp3.partialUpdate", property, NULL) <= 0) &&
192 (ctx->mMDP.version == qdutils::MDP_V3_0_5)) {
193 enablePartialUpdateForMDP3 = true;
194 }
195
196 if(!enablePartialUpdateForMDP3 &&
197 (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
198 (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
199 enablePartialUpdateForMDP3 = true;
200 }
201
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -0800202 sIsPartialUpdateActive = getPartialUpdatePref(ctx);
203
Arun Kumar K.R299bcda2014-12-18 19:36:40 -0800204 if(property_get("persist.mdpcomp_perfhint", property, "-1") > 0) {
205 int val = atoi(property);
206 if(val > 0 && loadPerfLib()) {
207 sPerfHintWindow = val;
208 ALOGI("PerfHintWindow = %d", sPerfHintWindow);
209 }
210 }
211
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700212 return true;
213}
214
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800215void MDPComp::reset(hwc_context_t *ctx) {
216 const int numLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shah2a4eb1b2013-07-22 16:33:23 -0700217 mCurrentFrame.reset(numLayers);
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800218 ctx->mOverlay->clear(mDpy);
219 ctx->mLayerRotMap[mDpy]->clear();
Saurabh Shah2a4eb1b2013-07-22 16:33:23 -0700220}
221
Raj Kamal4393eaa2014-06-06 13:45:20 +0530222void MDPComp::reset() {
Raj Kamalfdfdddf2015-03-16 21:59:25 +0530223 mPrevModeOn = mModeOn;
Raj Kamal4393eaa2014-06-06 13:45:20 +0530224 mModeOn = false;
225}
226
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700227void MDPComp::timeout_handler(void *udata) {
228 struct hwc_context_t* ctx = (struct hwc_context_t*)(udata);
Raj Kamalfdfdddf2015-03-16 21:59:25 +0530229 bool handleTimeout = false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700230
231 if(!ctx) {
232 ALOGE("%s: received empty data in timer callback", __FUNCTION__);
233 return;
234 }
Raj Kamal58b31a02014-12-16 15:53:53 +0530235
236 ctx->mDrawLock.lock();
Raj Kamalfdfdddf2015-03-16 21:59:25 +0530237
238 /* Handle timeout event only if the previous composition
239 on any display is MDP or MIXED*/
240 for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
241 if(ctx->mMDPComp[i])
242 handleTimeout =
243 ctx->mMDPComp[i]->isMDPComp() || handleTimeout;
244 }
245
246 if(!handleTimeout) {
Ramkumar Radhakrishnan92abb4f2014-02-06 21:31:29 -0800247 ALOGD_IF(isDebug(), "%s:Do not handle this timeout", __FUNCTION__);
Raj Kamal58b31a02014-12-16 15:53:53 +0530248 ctx->mDrawLock.unlock();
Ramkumar Radhakrishnan92abb4f2014-02-06 21:31:29 -0800249 return;
250 }
Jesse Hall3be78d92012-08-21 15:12:23 -0700251 if(!ctx->proc) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700252 ALOGE("%s: HWC proc not registered", __FUNCTION__);
Raj Kamal58b31a02014-12-16 15:53:53 +0530253 ctx->mDrawLock.unlock();
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700254 return;
255 }
256 sIdleFallBack = true;
Raj Kamal58b31a02014-12-16 15:53:53 +0530257 ctx->mDrawLock.unlock();
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700258 /* Trigger SF to redraw the current frame */
Jesse Hall3be78d92012-08-21 15:12:23 -0700259 ctx->proc->invalidate(ctx->proc);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700260}
261
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700262void MDPComp::setMaxPipesPerMixer(const uint32_t value) {
263 qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
Saurabh Shah2fd8a252014-12-05 13:49:53 -0800264 uint32_t maxSupported = (int)mdpVersion.getBlendStages();
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700265 if(value > maxSupported) {
266 ALOGW("%s: Input exceeds max value supported. Setting to"
267 "max value: %d", __FUNCTION__, maxSupported);
268 }
269 sMaxPipesPerMixer = min(value, maxSupported);
270}
271
Saurabh Shah59562ff2014-09-30 16:13:12 -0700272void MDPComp::setIdleTimeout(const uint32_t& timeout) {
273 enum { ONE_REFRESH_PERIOD_MS = 17, ONE_BILLION_MS = 1000000000 };
274
275 if(sIdleInvalidator) {
276 if(timeout <= ONE_REFRESH_PERIOD_MS) {
277 //If the specified timeout is < 1 draw cycle worth, "virtually"
278 //disable idle timeout. The ideal way for clients to disable
279 //timeout is to set it to 0
280 sIdleInvalidator->setIdleTimeout(ONE_BILLION_MS);
281 ALOGI("Disabled idle timeout");
282 return;
283 }
284 sIdleInvalidator->setIdleTimeout(timeout);
285 ALOGI("Idle timeout set to %u", timeout);
286 } else {
287 ALOGW("Cannot set idle timeout, IdleInvalidator not enabled");
288 }
289}
290
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800291void MDPComp::setMDPCompLayerFlags(hwc_context_t *ctx,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800292 hwc_display_contents_1_t* list) {
293 LayerProp *layerProp = ctx->layerProp[mDpy];
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800294
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800295 for(int index = 0; index < ctx->listStats[mDpy].numAppLayers; index++) {
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800296 hwc_layer_1_t* layer = &(list->hwLayers[index]);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800297 if(!mCurrentFrame.isFBComposed[index]) {
298 layerProp[index].mFlags |= HWC_MDPCOMP;
299 layer->compositionType = HWC_OVERLAY;
300 layer->hints |= HWC_HINT_CLEAR_FB;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800301 } else {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700302 /* Drop the layer when its already present in FB OR when it lies
303 * outside frame's ROI */
304 if(!mCurrentFrame.needsRedraw || mCurrentFrame.drop[index]) {
Arun Kumar K.R00b84792015-03-27 11:28:36 -0700305 if(index == mCurrentFrame.hwCursorIndex) {
306 layer->compositionType = HWC_CURSOR_OVERLAY;
307 } else {
308 layer->compositionType = HWC_OVERLAY;
309 }
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700310 }
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800311 }
312 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700313}
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500314
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800315void MDPComp::setRedraw(hwc_context_t *ctx,
316 hwc_display_contents_1_t* list) {
317 mCurrentFrame.needsRedraw = false;
318 if(!mCachedFrame.isSameFrame(mCurrentFrame, list) ||
319 (list->flags & HWC_GEOMETRY_CHANGED) ||
320 isSkipPresent(ctx, mDpy)) {
321 mCurrentFrame.needsRedraw = true;
322 }
323}
324
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800325MDPComp::FrameInfo::FrameInfo() {
Saurabh Shahf7fad542014-08-14 10:11:36 -0700326 memset(&mdpToLayer, 0, sizeof(mdpToLayer));
Saurabh Shahaa236822013-04-24 18:07:26 -0700327 reset(0);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800328}
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800329
Saurabh Shahaa236822013-04-24 18:07:26 -0700330void MDPComp::FrameInfo::reset(const int& numLayers) {
Jeykumar Sankaranbe93e272014-06-19 18:15:57 -0700331 for(int i = 0 ; i < MAX_NUM_BLEND_STAGES; i++ ) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800332 if(mdpToLayer[i].pipeInfo) {
333 delete mdpToLayer[i].pipeInfo;
334 mdpToLayer[i].pipeInfo = NULL;
335 //We dont own the rotator
336 mdpToLayer[i].rot = NULL;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800337 }
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800338 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800339
340 memset(&mdpToLayer, 0, sizeof(mdpToLayer));
341 memset(&layerToMDP, -1, sizeof(layerToMDP));
Saurabh Shahaa236822013-04-24 18:07:26 -0700342 memset(&isFBComposed, 1, sizeof(isFBComposed));
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800343
Saurabh Shahaa236822013-04-24 18:07:26 -0700344 layerCount = numLayers;
345 fbCount = numLayers;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800346 mdpCount = 0;
Saurabh Shah2f3895f2013-05-02 10:13:31 -0700347 needsRedraw = true;
Saurabh Shahd53bc5f2014-02-05 10:17:43 -0800348 fbZ = -1;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800349}
350
Saurabh Shahaa236822013-04-24 18:07:26 -0700351void MDPComp::FrameInfo::map() {
352 // populate layer and MDP maps
353 int mdpIdx = 0;
354 for(int idx = 0; idx < layerCount; idx++) {
355 if(!isFBComposed[idx]) {
356 mdpToLayer[mdpIdx].listIndex = idx;
357 layerToMDP[idx] = mdpIdx++;
358 }
359 }
360}
361
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800362MDPComp::LayerCache::LayerCache() {
363 reset();
364}
365
366void MDPComp::LayerCache::reset() {
Saurabh Shahaa236822013-04-24 18:07:26 -0700367 memset(&hnd, 0, sizeof(hnd));
Prabhanjan Kandula2243aa62013-10-24 12:58:55 +0530368 memset(&isFBComposed, true, sizeof(isFBComposed));
369 memset(&drop, false, sizeof(drop));
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800370 layerCount = 0;
Saurabh Shahaa236822013-04-24 18:07:26 -0700371}
372
373void MDPComp::LayerCache::cacheAll(hwc_display_contents_1_t* list) {
Praveena Pachipulusud9443c72014-02-17 10:42:28 +0530374 const int numAppLayers = (int)list->numHwLayers - 1;
Saurabh Shahaa236822013-04-24 18:07:26 -0700375 for(int i = 0; i < numAppLayers; i++) {
376 hnd[i] = list->hwLayers[i].handle;
377 }
378}
379
380void MDPComp::LayerCache::updateCounts(const FrameInfo& curFrame) {
Saurabh Shahaa236822013-04-24 18:07:26 -0700381 layerCount = curFrame.layerCount;
Prabhanjan Kandula2243aa62013-10-24 12:58:55 +0530382 memcpy(&isFBComposed, &curFrame.isFBComposed, sizeof(isFBComposed));
383 memcpy(&drop, &curFrame.drop, sizeof(drop));
384}
385
Jeykumar Sankaran988d3682013-11-15 11:57:16 -0800386bool MDPComp::LayerCache::isSameFrame(const FrameInfo& curFrame,
387 hwc_display_contents_1_t* list) {
Prabhanjan Kandula2243aa62013-10-24 12:58:55 +0530388 if(layerCount != curFrame.layerCount)
389 return false;
390 for(int i = 0; i < curFrame.layerCount; i++) {
391 if((curFrame.isFBComposed[i] != isFBComposed[i]) ||
392 (curFrame.drop[i] != drop[i])) {
393 return false;
394 }
Jeykumar Sankaran988d3682013-11-15 11:57:16 -0800395 if(curFrame.isFBComposed[i] &&
396 (hnd[i] != list->hwLayers[i].handle)){
397 return false;
398 }
Prabhanjan Kandula2243aa62013-10-24 12:58:55 +0530399 }
400 return true;
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800401}
402
Raj Kamalfdfdddf2015-03-16 21:59:25 +0530403bool MDPComp::LayerCache::isSameFrame(hwc_context_t *ctx, int dpy,
404 hwc_display_contents_1_t* list) {
405
406 if(layerCount != ctx->listStats[dpy].numAppLayers)
407 return false;
408
409 if((list->flags & HWC_GEOMETRY_CHANGED) ||
410 isSkipPresent(ctx, dpy)) {
411 return false;
412 }
413
414 for(int i = 0; i < layerCount; i++) {
415 if(hnd[i] != list->hwLayers[i].handle)
416 return false;
417 }
418
419 return true;
420}
421
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700422bool MDPComp::isSupportedForMDPComp(hwc_context_t *ctx, hwc_layer_1_t* layer) {
423 private_handle_t *hnd = (private_handle_t *)layer->handle;
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800424 if((has90Transform(layer) and (not isRotationDoable(ctx, hnd))) ||
Raj Kamal1179d9c2014-10-28 15:31:35 +0530425 (not isValidDimension(ctx,layer)) ||
426 isSkipLayer(layer)) {
427 //More conditions here, sRGB+Blend etc
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700428 return false;
429 }
430 return true;
431}
432
Sravan Kumar D.V.Nad5d9292013-04-24 14:23:04 +0530433bool MDPComp::isValidDimension(hwc_context_t *ctx, hwc_layer_1_t *layer) {
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800434 private_handle_t *hnd = (private_handle_t *)layer->handle;
435
436 if(!hnd) {
Sushil Chauhan897a9c32013-07-18 11:09:55 -0700437 if (layer->flags & HWC_COLOR_FILL) {
438 // Color layer
439 return true;
440 }
Ramkumar Radhakrishnan0cabf212014-09-08 20:07:49 -0700441 ALOGD_IF(isDebug(), "%s: layer handle is NULL", __FUNCTION__);
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800442 return false;
443 }
444
Naseer Ahmede850a802013-09-06 13:12:52 -0400445 //XXX: Investigate doing this with pixel phase on MDSS
Naseer Ahmede77f8082013-10-10 13:42:48 -0400446 if(!isSecureBuffer(hnd) && isNonIntegralSourceCrop(layer->sourceCropf))
Naseer Ahmede850a802013-09-06 13:12:52 -0400447 return false;
448
Saurabh Shah62e1d732013-09-17 10:44:05 -0700449 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
Saurabh Shah4fdde762013-04-30 18:47:33 -0700450 hwc_rect_t dst = layer->displayFrame;
Saurabh Shahb6810df2014-06-17 16:00:22 -0700451 bool rotated90 = (bool)(layer->transform & HAL_TRANSFORM_ROT_90);
Saurabh Shahe28a4022014-06-13 11:41:13 -0700452 int crop_w = rotated90 ? crop.bottom - crop.top : crop.right - crop.left;
453 int crop_h = rotated90 ? crop.right - crop.left : crop.bottom - crop.top;
Saurabh Shah4fdde762013-04-30 18:47:33 -0700454 int dst_w = dst.right - dst.left;
455 int dst_h = dst.bottom - dst.top;
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800456 float w_scale = ((float)crop_w / (float)dst_w);
457 float h_scale = ((float)crop_h / (float)dst_h);
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530458 MDPVersion& mdpHw = MDPVersion::getInstance();
Saurabh Shah4fdde762013-04-30 18:47:33 -0700459
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800460 /* Workaround for MDP HW limitation in DSI command mode panels where
461 * FPS will not go beyond 30 if buffers on RGB pipes are of width or height
462 * less than 5 pixels
Sravan Kumar D.V.Nad5d9292013-04-24 14:23:04 +0530463 * There also is a HW limilation in MDP, minimum block size is 2x2
464 * Fallback to GPU if height is less than 2.
465 */
Saurabh Shah189f23d2014-09-26 17:21:00 -0700466 if(mdpHw.hasMinCropWidthLimitation() and (crop_w < 5 or crop_h < 5))
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800467 return false;
468
Ramkumar Radhakrishnan1a763e92015-03-19 16:46:46 -0700469 /* crop_w and crop_h should be even for yuv layer, so fallback to GPU for
470 * those cases
471 */
472 if(isYuvBuffer(hnd) && (crop_w < 2 || crop_h < 2)) {
473 return false;
474 }
475
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800476 if((w_scale > 1.0f) || (h_scale > 1.0f)) {
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530477 const uint32_t maxMDPDownscale = mdpHw.getMaxMDPDownscale();
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800478 const float w_dscale = w_scale;
479 const float h_dscale = h_scale;
480
Jeykumar Sankaran1706a772013-11-27 12:55:19 -0800481 if(ctx->mMDP.version >= qdutils::MDSS_V5) {
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700482
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530483 if(!mdpHw.supportsDecimation()) {
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700484 /* On targets that doesnt support Decimation (eg.,8x26)
485 * maximum downscale support is overlay pipe downscale.
486 */
Jeykumar Sankaran39305802014-12-12 17:55:57 -0800487 if(crop_w > (int) mdpHw.getMaxPipeWidth() ||
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530488 w_dscale > maxMDPDownscale ||
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700489 h_dscale > maxMDPDownscale)
Jeykumar Sankaran1706a772013-11-27 12:55:19 -0800490 return false;
491 } else {
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700492 // Decimation on macrotile format layers is not supported.
493 if(isTileRendered(hnd)) {
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530494 /* Bail out if
495 * 1. Src crop > Mixer limit on nonsplit MDPComp
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700496 * 2. exceeds maximum downscale limit
497 */
Jeykumar Sankaran39305802014-12-12 17:55:57 -0800498 if(((crop_w > (int) mdpHw.getMaxPipeWidth()) &&
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530499 !sSrcSplitEnabled) ||
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700500 w_dscale > maxMDPDownscale ||
501 h_dscale > maxMDPDownscale) {
502 return false;
503 }
504 } else if(w_dscale > 64 || h_dscale > 64)
Jeykumar Sankaran1706a772013-11-27 12:55:19 -0800505 return false;
506 }
507 } else { //A-family
Manoj Kumar AVM8cbbf7c2014-03-11 01:15:31 -0700508 if(w_dscale > maxMDPDownscale || h_dscale > maxMDPDownscale)
Saurabh Shah4fdde762013-04-30 18:47:33 -0700509 return false;
510 }
Saurabh Shah4fdde762013-04-30 18:47:33 -0700511 }
512
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800513 if((w_scale < 1.0f) || (h_scale < 1.0f)) {
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530514 const uint32_t upscale = mdpHw.getMaxMDPUpscale();
Jeykumar Sankaran6cd8e7e2014-01-13 16:01:05 -0800515 const float w_uscale = 1.0f / w_scale;
516 const float h_uscale = 1.0f / h_scale;
517
518 if(w_uscale > upscale || h_uscale > upscale)
519 return false;
520 }
521
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800522 return true;
523}
524
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800525bool MDPComp::isFrameDoable(hwc_context_t *ctx) {
Saurabh Shahaa236822013-04-24 18:07:26 -0700526 bool ret = true;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800527
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800528 if(!isEnabled()) {
529 ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
Saurabh Shahaa236822013-04-24 18:07:26 -0700530 ret = false;
Raj Kamal068f4572014-04-14 16:14:06 +0530531 } else if((qdutils::MDPVersion::getInstance().is8x26() ||
Prabhanjan Kandula958ffa92014-05-12 14:56:56 +0530532 qdutils::MDPVersion::getInstance().is8x16() ||
533 qdutils::MDPVersion::getInstance().is8x39()) &&
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800534 ctx->mVideoTransFlag &&
535 isSecondaryConnected(ctx)) {
Saurabh Shahd4e65852013-06-17 11:33:53 -0700536 //1 Padding round to shift pipes across mixers
537 ALOGD_IF(isDebug(),"%s: MDP Comp. video transition padding round",
538 __FUNCTION__);
539 ret = false;
Raj Kamalc0d34242015-03-17 20:53:14 +0530540 } else if((qdutils::MDPVersion::getInstance().is8x26() ||
541 qdutils::MDPVersion::getInstance().is8x16() ||
542 qdutils::MDPVersion::getInstance().is8x39()) &&
543 !mDpy && isSecondaryAnimating(ctx) &&
544 isYuvPresent(ctx,HWC_DISPLAY_VIRTUAL)) {
545 ALOGD_IF(isDebug(),"%s: Display animation in progress",
546 __FUNCTION__);
547 ret = false;
Ramkumar Radhakrishnanf26fe9e2014-09-09 13:47:54 -0700548 } else if(qdutils::MDPVersion::getInstance().getTotalPipes() < 8) {
549 /* TODO: freeing up all the resources only for the targets having total
550 number of pipes < 8. Need to analyze number of VIG pipes used
551 for primary in previous draw cycle and accordingly decide
552 whether to fall back to full GPU comp or video only comp
553 */
554 if(isSecondaryConfiguring(ctx)) {
555 ALOGD_IF( isDebug(),"%s: External Display connection is pending",
556 __FUNCTION__);
557 ret = false;
558 } else if(ctx->isPaddingRound) {
559 ALOGD_IF(isDebug(), "%s: padding round invoked for dpy %d",
560 __FUNCTION__,mDpy);
561 ret = false;
562 }
Tatenda Chipeperekwadc8d7082014-11-04 16:41:50 -0800563 } else if (ctx->isDMAStateChanging) {
564 // Bail out if a padding round has been invoked in order to switch DMA
565 // state to block mode. We need this to cater for the case when a layer
566 // requires rotation in the current frame.
567 ALOGD_IF(isDebug(), "%s: padding round invoked to switch DMA state",
568 __FUNCTION__);
569 return false;
Saurabh Shah0ceeb6a2013-04-23 10:46:07 -0700570 }
Tatenda Chipeperekwadc8d7082014-11-04 16:41:50 -0800571
Saurabh Shahaa236822013-04-24 18:07:26 -0700572 return ret;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800573}
574
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800575void MDPCompNonSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect &crop,
576 hwc_rect &dst) {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800577 hwc_rect_t roi = ctx->listStats[mDpy].lRoi;
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800578 dst = getIntersection(dst, roi);
579 crop = dst;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800580}
581
582/* 1) Identify layers that are not visible or lying outside the updating ROI and
583 * drop them from composition.
584 * 2) If we have a scaling layer which needs cropping against generated
585 * ROI, reset ROI to full resolution. */
586bool MDPCompNonSplit::validateAndApplyROI(hwc_context_t *ctx,
587 hwc_display_contents_1_t* list) {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700588 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800589 hwc_rect_t visibleRect = ctx->listStats[mDpy].lRoi;
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800590
591 for(int i = numAppLayers - 1; i >= 0; i--){
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800592 if(!isValidRect(visibleRect)) {
593 mCurrentFrame.drop[i] = true;
594 mCurrentFrame.dropCount++;
Jeykumar Sankaran0b961452014-01-21 17:26:12 -0800595 continue;
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800596 }
597
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700598 const hwc_layer_1_t* layer = &list->hwLayers[i];
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700599 hwc_rect_t dstRect = layer->displayFrame;
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800600 hwc_rect_t res = getIntersection(visibleRect, dstRect);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700601
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700602 if(!isValidRect(res)) {
603 mCurrentFrame.drop[i] = true;
604 mCurrentFrame.dropCount++;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800605 } else {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700606 /* Reset frame ROI when any layer which needs scaling also needs ROI
607 * cropping */
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800608 if(!isSameRect(res, dstRect) && needsScaling (layer)) {
Arpita Banerjeed8965982013-11-08 17:27:33 -0800609 ALOGI("%s: Resetting ROI due to scaling", __FUNCTION__);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700610 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
611 mCurrentFrame.dropCount = 0;
612 return false;
613 }
Jeykumar Sankaran862d87c2013-11-08 16:47:26 -0800614
Jeykumar Sankaran0b961452014-01-21 17:26:12 -0800615 /* deduct any opaque region from visibleRect */
radhakrishna4efbdd62014-11-03 13:19:27 +0530616 if (layer->blending == HWC_BLENDING_NONE &&
617 layer->planeAlpha == 0xFF)
Jeykumar Sankaran0b961452014-01-21 17:26:12 -0800618 visibleRect = deductRect(visibleRect, res);
619 }
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700620 }
621 return true;
622}
623
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800624/* Calculate ROI for the frame by accounting all the layer's dispalyFrame which
625 * are updating. If DirtyRegion is applicable, calculate it by accounting all
626 * the changing layer's dirtyRegion. */
627void MDPCompNonSplit::generateROI(hwc_context_t *ctx,
628 hwc_display_contents_1_t* list) {
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700629 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800630 if(!canPartialUpdate(ctx, list))
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700631 return;
632
633 struct hwc_rect roi = (struct hwc_rect){0, 0, 0, 0};
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800634 hwc_rect fullFrame = (struct hwc_rect) {0, 0,(int)ctx->dpyAttr[mDpy].xres,
635 (int)ctx->dpyAttr[mDpy].yres};
636
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700637 for(int index = 0; index < numAppLayers; index++ ) {
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800638 hwc_layer_1_t* layer = &list->hwLayers[index];
639 if ((mCachedFrame.hnd[index] != layer->handle) ||
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800640 isYuvBuffer((private_handle_t *)layer->handle)) {
Jeykumar Sankaran455678c2014-05-30 10:22:38 -0700641 hwc_rect_t dst = layer->displayFrame;
642 hwc_rect_t updatingRect = dst;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800643
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800644#ifdef QCOM_BSP
Dileep Kumar Reddi7399d5c2014-12-31 18:01:19 +0530645 if(!needsScaling(layer) && !layer->transform &&
646 (!isYuvBuffer((private_handle_t *)layer->handle)))
Jeykumar Sankaran455678c2014-05-30 10:22:38 -0700647 {
648 hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
649 int x_off = dst.left - src.left;
650 int y_off = dst.top - src.top;
651 updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
652 }
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800653#endif
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800654
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800655 roi = getUnion(roi, updatingRect);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700656 }
657 }
658
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800659 /* No layer is updating. Still SF wants a refresh.*/
660 if(!isValidRect(roi))
661 return;
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800662
663 // Align ROI coordinates to panel restrictions
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800664 roi = getSanitizeROI(roi, fullFrame);
Jeykumar Sankaran7c852382014-02-26 18:26:58 -0800665
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800666 ctx->listStats[mDpy].lRoi = roi;
667 if(!validateAndApplyROI(ctx, list))
668 resetROI(ctx, mDpy);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700669
670 ALOGD_IF(isDebug(),"%s: generated ROI: [%d, %d, %d, %d]", __FUNCTION__,
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800671 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
672 ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom);
673}
674
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800675void MDPCompSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect &crop,
676 hwc_rect &dst) {
677 hwc_rect roi = getUnion(ctx->listStats[mDpy].lRoi,
678 ctx->listStats[mDpy].rRoi);
679 hwc_rect tmpDst = getIntersection(dst, roi);
680 if(!isSameRect(dst, tmpDst)) {
681 crop.left = crop.left + (tmpDst.left - dst.left);
682 crop.top = crop.top + (tmpDst.top - dst.top);
683 crop.right = crop.left + (tmpDst.right - tmpDst.left);
684 crop.bottom = crop.top + (tmpDst.bottom - tmpDst.top);
685 dst = tmpDst;
686 }
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800687}
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -0800688
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800689/* 1) Identify layers that are not visible or lying outside BOTH the updating
690 * ROI's and drop them from composition. If a layer is spanning across both
691 * the halves of the screen but needed by only ROI, the non-contributing
692 * half will not be programmed for MDP.
693 * 2) If we have a scaling layer which needs cropping against generated
694 * ROI, reset ROI to full resolution. */
695bool MDPCompSplit::validateAndApplyROI(hwc_context_t *ctx,
696 hwc_display_contents_1_t* list) {
697
698 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
699
700 hwc_rect_t visibleRectL = ctx->listStats[mDpy].lRoi;
701 hwc_rect_t visibleRectR = ctx->listStats[mDpy].rRoi;
702
703 for(int i = numAppLayers - 1; i >= 0; i--){
704 if(!isValidRect(visibleRectL) && !isValidRect(visibleRectR))
705 {
706 mCurrentFrame.drop[i] = true;
707 mCurrentFrame.dropCount++;
708 continue;
709 }
710
711 const hwc_layer_1_t* layer = &list->hwLayers[i];
712 hwc_rect_t dstRect = layer->displayFrame;
713
714 hwc_rect_t l_res = getIntersection(visibleRectL, dstRect);
715 hwc_rect_t r_res = getIntersection(visibleRectR, dstRect);
716 hwc_rect_t res = getUnion(l_res, r_res);
717
718 if(!isValidRect(l_res) && !isValidRect(r_res)) {
719 mCurrentFrame.drop[i] = true;
720 mCurrentFrame.dropCount++;
721 } else {
722 /* Reset frame ROI when any layer which needs scaling also needs ROI
723 * cropping */
724 if(!isSameRect(res, dstRect) && needsScaling (layer)) {
725 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
726 mCurrentFrame.dropCount = 0;
727 return false;
728 }
729
radhakrishna4efbdd62014-11-03 13:19:27 +0530730 if (layer->blending == HWC_BLENDING_NONE &&
731 layer->planeAlpha == 0xFF) {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800732 visibleRectL = deductRect(visibleRectL, l_res);
733 visibleRectR = deductRect(visibleRectR, r_res);
734 }
735 }
736 }
737 return true;
738}
739/* Calculate ROI for the frame by accounting all the layer's dispalyFrame which
740 * are updating. If DirtyRegion is applicable, calculate it by accounting all
741 * the changing layer's dirtyRegion. */
742void MDPCompSplit::generateROI(hwc_context_t *ctx,
743 hwc_display_contents_1_t* list) {
744 if(!canPartialUpdate(ctx, list))
745 return;
746
747 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
748 int lSplit = getLeftSplit(ctx, mDpy);
749
750 int hw_h = (int)ctx->dpyAttr[mDpy].yres;
751 int hw_w = (int)ctx->dpyAttr[mDpy].xres;
752
753 struct hwc_rect l_frame = (struct hwc_rect){0, 0, lSplit, hw_h};
754 struct hwc_rect r_frame = (struct hwc_rect){lSplit, 0, hw_w, hw_h};
755
756 struct hwc_rect l_roi = (struct hwc_rect){0, 0, 0, 0};
757 struct hwc_rect r_roi = (struct hwc_rect){0, 0, 0, 0};
758
759 for(int index = 0; index < numAppLayers; index++ ) {
760 hwc_layer_1_t* layer = &list->hwLayers[index];
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800761 private_handle_t *hnd = (private_handle_t *)layer->handle;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800762 if ((mCachedFrame.hnd[index] != layer->handle) ||
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800763 isYuvBuffer(hnd)) {
Jeykumar Sankaran71e597c2014-05-07 16:23:14 -0700764 hwc_rect_t dst = layer->displayFrame;
765 hwc_rect_t updatingRect = dst;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800766
767#ifdef QCOM_BSP
768 if(!needsScaling(layer) && !layer->transform)
Jeykumar Sankaran71e597c2014-05-07 16:23:14 -0700769 {
770 hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
771 int x_off = dst.left - src.left;
772 int y_off = dst.top - src.top;
773 updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
774 }
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800775#endif
776
777 hwc_rect_t l_dst = getIntersection(l_frame, updatingRect);
778 if(isValidRect(l_dst))
779 l_roi = getUnion(l_roi, l_dst);
780
781 hwc_rect_t r_dst = getIntersection(r_frame, updatingRect);
782 if(isValidRect(r_dst))
783 r_roi = getUnion(r_roi, r_dst);
784 }
785 }
786
Jeykumar Sankarana40a9342014-04-25 09:37:10 -0700787 /* For panels that cannot accept commands in both the interfaces, we cannot
788 * send two ROI's (for each half). We merge them into single ROI and split
789 * them across lSplit for MDP mixer use. The ROI's will be merged again
790 * finally before udpating the panel in the driver. */
791 if(qdutils::MDPVersion::getInstance().needsROIMerge()) {
792 hwc_rect_t temp_roi = getUnion(l_roi, r_roi);
793 l_roi = getIntersection(temp_roi, l_frame);
794 r_roi = getIntersection(temp_roi, r_frame);
795 }
796
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -0800797 /* No layer is updating. Still SF wants a refresh. */
798 if(!isValidRect(l_roi) && !isValidRect(r_roi))
799 return;
800
801 l_roi = getSanitizeROI(l_roi, l_frame);
802 r_roi = getSanitizeROI(r_roi, r_frame);
803
804 ctx->listStats[mDpy].lRoi = l_roi;
805 ctx->listStats[mDpy].rRoi = r_roi;
806
807 if(!validateAndApplyROI(ctx, list))
808 resetROI(ctx, mDpy);
809
810 ALOGD_IF(isDebug(),"%s: generated L_ROI: [%d, %d, %d, %d]"
811 "R_ROI: [%d, %d, %d, %d]", __FUNCTION__,
812 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
813 ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom,
814 ctx->listStats[mDpy].rRoi.left, ctx->listStats[mDpy].rRoi.top,
815 ctx->listStats[mDpy].rRoi.right, ctx->listStats[mDpy].rRoi.bottom);
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700816}
817
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800818/* Checks for conditions where all the layers marked for MDP comp cannot be
819 * bypassed. On such conditions we try to bypass atleast YUV layers */
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800820bool MDPComp::tryFullFrame(hwc_context_t *ctx,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800821 hwc_display_contents_1_t* list){
822
Saurabh Shahaa236822013-04-24 18:07:26 -0700823 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -0800824
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -0700825 // Fall back to video only composition, if AIV video mode is enabled
826 if(ctx->listStats[mDpy].mAIVVideoMode) {
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -0700827 ALOGD_IF(isDebug(), "%s: AIV Video Mode enabled dpy %d",
828 __FUNCTION__, mDpy);
829 return false;
830 }
831
Praveena Pachipulusu47346c22014-12-04 11:06:41 +0530832 /* No Idle fall back if secure display or secure RGB layers are present
833 * or if there is only a single layer being composed */
834 if(sIdleFallBack && !ctx->listStats[mDpy].secureUI &&
835 !ctx->listStats[mDpy].secureRGBCount &&
836 (ctx->listStats[mDpy].numAppLayers > 1)) {
Saurabh Shah2d998a92013-05-14 17:55:58 -0700837 ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
838 return false;
839 }
840
Raj Kamalc0d34242015-03-17 20:53:14 +0530841 if(!mDpy && isSecondaryAnimating(ctx) &&
842 (isYuvPresent(ctx,HWC_DISPLAY_EXTERNAL) ||
843 isYuvPresent(ctx,HWC_DISPLAY_VIRTUAL)) ) {
844 ALOGD_IF(isDebug(),"%s: Display animation in progress",
845 __FUNCTION__);
846 return false;
847 }
848
Ramkumar Radhakrishnanf26fe9e2014-09-09 13:47:54 -0700849 // if secondary is configuring or Padding round, fall back to video only
850 // composition and release all assigned non VIG pipes from primary.
851 if(isSecondaryConfiguring(ctx)) {
852 ALOGD_IF( isDebug(),"%s: External Display connection is pending",
853 __FUNCTION__);
854 return false;
855 } else if(ctx->isPaddingRound) {
856 ALOGD_IF(isDebug(), "%s: padding round invoked for dpy %d",
857 __FUNCTION__,mDpy);
858 return false;
859 }
860
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -0500861 // No MDP composition for 3D
862 if(needs3DComposition(ctx, mDpy))
863 return false;
864
Tatenda Chipeperekwacb2a2432014-08-06 17:45:58 -0700865 // check for action safe flag and MDP scaling mode which requires scaling.
Ramkumar Radhakrishnan4af1ef02013-12-12 11:53:08 -0800866 if(ctx->dpyAttr[mDpy].mActionSafePresent
Tatenda Chipeperekwacb2a2432014-08-06 17:45:58 -0700867 || ctx->dpyAttr[mDpy].mMDPScalingMode) {
Ramkumar Radhakrishnan4af1ef02013-12-12 11:53:08 -0800868 ALOGD_IF(isDebug(), "%s: Scaling needed for this frame",__FUNCTION__);
869 return false;
870 }
871
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800872 for(int i = 0; i < numAppLayers; ++i) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800873 hwc_layer_1_t* layer = &list->hwLayers[i];
874 private_handle_t *hnd = (private_handle_t *)layer->handle;
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -0800875
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -0800876 if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700877 if(!canUseRotator(ctx, mDpy)) {
878 ALOGD_IF(isDebug(), "%s: Can't use rotator for dpy %d",
879 __FUNCTION__, mDpy);
Amara Venkata Mastan Manoj Kumar9d373c02013-08-20 14:30:09 -0700880 return false;
881 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800882 }
Prabhanjan Kandula9fb032a2013-06-18 17:37:22 +0530883
884 //For 8x26 with panel width>1k, if RGB layer needs HFLIP fail mdp comp
885 // may not need it if Gfx pre-rotation can handle all flips & rotations
Saurabh Shahcad57772014-12-01 14:19:51 -0800886 MDPVersion& mdpHw = MDPVersion::getInstance();
Sushil Chauhanfda00fc2014-03-20 11:08:41 -0700887 int transform = (layer->flags & HWC_COLOR_FILL) ? 0 : layer->transform;
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +0530888 if( mdpHw.is8x26() && (ctx->dpyAttr[mDpy].xres > 1024) &&
889 (transform & HWC_TRANSFORM_FLIP_H) && (!isYuvBuffer(hnd)))
890 return false;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800891 }
Saurabh Shahaa236822013-04-24 18:07:26 -0700892
Saurabh Shaha9da08f2013-07-03 13:27:53 -0700893 if(ctx->mAD->isDoable()) {
894 return false;
895 }
896
Saurabh Shahaa236822013-04-24 18:07:26 -0700897 //If all above hard conditions are met we can do full or partial MDP comp.
898 bool ret = false;
899 if(fullMDPComp(ctx, list)) {
900 ret = true;
Sushil Chauhandefd3522014-05-13 18:17:12 -0700901 } else if(fullMDPCompWithPTOR(ctx, list)) {
902 ret = true;
Jeykumar Sankaran24c199d2013-05-24 09:40:36 -0700903 } else if(partialMDPComp(ctx, list)) {
Saurabh Shahaa236822013-04-24 18:07:26 -0700904 ret = true;
905 }
Prabhanjan Kandula21918db2013-11-26 15:51:58 +0530906
Saurabh Shahaa236822013-04-24 18:07:26 -0700907 return ret;
908}
909
910bool MDPComp::fullMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -0700911
912 if(sSimulationFlags & MDPCOMP_AVOID_FULL_MDP)
913 return false;
914
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700915 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
916 for(int i = 0; i < numAppLayers; i++) {
917 hwc_layer_1_t* layer = &list->hwLayers[i];
Jeykumar Sankaran880da832014-04-18 10:22:35 -0700918 if(not mCurrentFrame.drop[i] and
919 not isSupportedForMDPComp(ctx, layer)) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -0700920 ALOGD_IF(isDebug(), "%s: Unsupported layer in list",__FUNCTION__);
921 return false;
922 }
923 }
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800924
Saurabh Shahaa236822013-04-24 18:07:26 -0700925 mCurrentFrame.fbCount = 0;
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -0700926 memcpy(&mCurrentFrame.isFBComposed, &mCurrentFrame.drop,
927 sizeof(mCurrentFrame.isFBComposed));
928 mCurrentFrame.mdpCount = mCurrentFrame.layerCount - mCurrentFrame.fbCount -
929 mCurrentFrame.dropCount;
Saurabh Shahaa236822013-04-24 18:07:26 -0700930
Raj Kamal389d6e32014-08-04 14:43:24 +0530931 if(sEnableYUVsplit){
Saurabh Shah3d4b8042013-12-10 15:19:17 -0800932 adjustForSourceSplit(ctx, list);
radhakrishnac9a67412013-09-25 17:40:42 +0530933 }
934
Saurabh Shahdf4741d2013-12-12 16:40:28 -0800935 if(!postHeuristicsHandling(ctx, list)) {
936 ALOGD_IF(isDebug(), "post heuristic handling failed");
937 reset(ctx);
Saurabh Shah8c5c8522013-08-29 17:32:49 -0700938 return false;
939 }
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -0700940 ALOGD_IF(sSimulationFlags,"%s: FULL_MDP_COMP SUCCEEDED",
941 __FUNCTION__);
Saurabh Shahaa236822013-04-24 18:07:26 -0700942 return true;
943}
944
Sushil Chauhandefd3522014-05-13 18:17:12 -0700945/* Full MDP Composition with Peripheral Tiny Overlap Removal.
946 * MDP bandwidth limitations can be avoided, if the overlap region
947 * covered by the smallest layer at a higher z-order, gets composed
948 * by Copybit on a render buffer, which can be queued to MDP.
949 */
950bool MDPComp::fullMDPCompWithPTOR(hwc_context_t *ctx,
951 hwc_display_contents_1_t* list) {
952
953 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Arun Kumar K.R00b84792015-03-27 11:28:36 -0700954 // PTOR does not qualify when there are layers dropped, but if
955 // dropped layer is only a cursor, PTOR could qualify
956 const int numNonCursorLayers = numAppLayers - mCurrentFrame.dropCount;
Sushil Chauhandefd3522014-05-13 18:17:12 -0700957 const int stagesForMDP = min(sMaxPipesPerMixer,
958 ctx->mOverlay->availablePipes(mDpy, Overlay::MIXER_DEFAULT));
959
960 // Hard checks where we cannot use this mode
Sushil Chauhanbfc2de02014-07-24 11:52:58 -0700961 if (mDpy || !ctx->mCopyBit[mDpy]) {
Sushil Chauhandefd3522014-05-13 18:17:12 -0700962 ALOGD_IF(isDebug(), "%s: Feature not supported!", __FUNCTION__);
963 return false;
964 }
965
Arun Kumar K.R00b84792015-03-27 11:28:36 -0700966 // Frame level checks - consider PTOR in case of dropCount only if the cursor
967 // layer is dropped, otherwise bail out of PTOR
Sushil Chauhandefd3522014-05-13 18:17:12 -0700968 if ((numAppLayers > stagesForMDP) || isSkipPresent(ctx, mDpy) ||
Arun Kumar K.R00b84792015-03-27 11:28:36 -0700969 isYuvPresent(ctx, mDpy) || isSecurePresent(ctx, mDpy) ||
970 (mCurrentFrame.dropCount - (int)isCursorPresent(ctx, mDpy))) {
Sushil Chauhandefd3522014-05-13 18:17:12 -0700971 ALOGD_IF(isDebug(), "%s: Frame not supported!", __FUNCTION__);
972 return false;
973 }
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -0700974 // MDP comp checks
975 for(int i = 0; i < numAppLayers; i++) {
Sushil Chauhandefd3522014-05-13 18:17:12 -0700976 hwc_layer_1_t* layer = &list->hwLayers[i];
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -0700977 if(not isSupportedForMDPComp(ctx, layer)) {
978 ALOGD_IF(isDebug(), "%s: Unsupported layer in list",__FUNCTION__);
979 return false;
Sushil Chauhandefd3522014-05-13 18:17:12 -0700980 }
981 }
982
Sushil Chauhandefd3522014-05-13 18:17:12 -0700983 /* We cannot use this composition mode, if:
984 1. A below layer needs scaling.
985 2. Overlap is not peripheral to display.
986 3. Overlap or a below layer has 90 degree transform.
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -0700987 4. Overlap area > (1/3 * FrameBuffer) area, based on Perf inputs.
Sushil Chauhandefd3522014-05-13 18:17:12 -0700988 */
989
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -0700990 int minLayerIndex[MAX_PTOR_LAYERS] = { -1, -1};
991 hwc_rect_t overlapRect[MAX_PTOR_LAYERS];
992 memset(overlapRect, 0, sizeof(overlapRect));
993 int layerPixelCount, minPixelCount = 0;
994 int numPTORLayersFound = 0;
Arun Kumar K.R00b84792015-03-27 11:28:36 -0700995 for (int i = numNonCursorLayers - 1; (i >= 0 &&
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -0700996 numPTORLayersFound < MAX_PTOR_LAYERS); i--) {
Sushil Chauhandefd3522014-05-13 18:17:12 -0700997 hwc_layer_1_t* layer = &list->hwLayers[i];
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -0700998 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
Sushil Chauhandefd3522014-05-13 18:17:12 -0700999 hwc_rect_t dispFrame = layer->displayFrame;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001000 layerPixelCount = (crop.right - crop.left) * (crop.bottom - crop.top);
1001 // PTOR layer should be peripheral and cannot have transform
1002 if (!isPeripheral(dispFrame, ctx->mViewFrame[mDpy]) ||
1003 has90Transform(layer)) {
1004 continue;
1005 }
1006 if((3 * (layerPixelCount + minPixelCount)) >
1007 ((int)ctx->dpyAttr[mDpy].xres * (int)ctx->dpyAttr[mDpy].yres)) {
1008 // Overlap area > (1/3 * FrameBuffer) area, based on Perf inputs.
1009 continue;
1010 }
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001011 bool found = false;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001012 for (int j = i-1; j >= 0; j--) {
1013 // Check if the layers below this layer qualifies for PTOR comp
1014 hwc_layer_1_t* layer = &list->hwLayers[j];
1015 hwc_rect_t disFrame = layer->displayFrame;
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001016 // Layer below PTOR is intersecting and has 90 degree transform or
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001017 // needs scaling cannot be supported.
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001018 if (isValidRect(getIntersection(dispFrame, disFrame))) {
1019 if (has90Transform(layer) || needsScaling(layer)) {
1020 found = false;
1021 break;
1022 }
1023 found = true;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001024 }
1025 }
1026 // Store the minLayer Index
1027 if(found) {
1028 minLayerIndex[numPTORLayersFound] = i;
1029 overlapRect[numPTORLayersFound] = list->hwLayers[i].displayFrame;
1030 minPixelCount += layerPixelCount;
1031 numPTORLayersFound++;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001032 }
1033 }
1034
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001035 // No overlap layers
1036 if (!numPTORLayersFound)
1037 return false;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001038
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001039 // Store the displayFrame and the sourceCrops of the layers
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001040 hwc_rect_t displayFrame[numNonCursorLayers];
1041 hwc_rect_t sourceCrop[numNonCursorLayers];
1042 for(int i = 0; i < numNonCursorLayers; i++) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001043 hwc_layer_1_t* layer = &list->hwLayers[i];
1044 displayFrame[i] = layer->displayFrame;
1045 sourceCrop[i] = integerizeSourceCrop(layer->sourceCropf);
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001046 }
Sushil Chauhandefd3522014-05-13 18:17:12 -07001047
Prabhanjan Kandula9889a202014-09-04 21:50:35 +05301048 /**
1049 * It's possible that 2 PTOR layers might have overlapping.
1050 * In such case, remove the intersection(again if peripheral)
1051 * from the lower PTOR layer to avoid overlapping.
1052 * If intersection is not on peripheral then compromise
1053 * by reducing number of PTOR layers.
1054 **/
1055 hwc_rect_t commonRect = getIntersection(overlapRect[0], overlapRect[1]);
1056 if(isValidRect(commonRect)) {
1057 overlapRect[1] = deductRect(overlapRect[1], commonRect);
1058 list->hwLayers[minLayerIndex[1]].displayFrame = overlapRect[1];
1059 }
1060
1061 ctx->mPtorInfo.count = numPTORLayersFound;
1062 for(int i = 0; i < MAX_PTOR_LAYERS; i++) {
1063 ctx->mPtorInfo.layerIndex[i] = minLayerIndex[i];
1064 }
1065
1066 if (!ctx->mCopyBit[mDpy]->prepareOverlap(ctx, list)) {
1067 // reset PTOR
1068 ctx->mPtorInfo.count = 0;
1069 if(isValidRect(commonRect)) {
1070 // If PTORs are intersecting restore displayframe of PTOR[1]
1071 // before returning, as we have modified it above.
1072 list->hwLayers[minLayerIndex[1]].displayFrame =
1073 displayFrame[minLayerIndex[1]];
1074 }
1075 return false;
1076 }
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001077 private_handle_t *renderBuf = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
1078 Whf layerWhf[numPTORLayersFound]; // To store w,h,f of PTOR layers
1079
Xu Yangcda012c2014-07-30 21:57:21 +08001080 // Store the blending mode, planeAlpha, and transform of PTOR layers
1081 int32_t blending[numPTORLayersFound];
1082 uint8_t planeAlpha[numPTORLayersFound];
1083 uint32_t transform[numPTORLayersFound];
1084
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001085 for(int j = 0; j < numPTORLayersFound; j++) {
1086 int index = ctx->mPtorInfo.layerIndex[j];
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001087
1088 // Update src crop of PTOR layer
1089 hwc_layer_1_t* layer = &list->hwLayers[index];
1090 layer->sourceCropf.left = (float)ctx->mPtorInfo.displayFrame[j].left;
1091 layer->sourceCropf.top = (float)ctx->mPtorInfo.displayFrame[j].top;
1092 layer->sourceCropf.right = (float)ctx->mPtorInfo.displayFrame[j].right;
1093 layer->sourceCropf.bottom =(float)ctx->mPtorInfo.displayFrame[j].bottom;
1094
1095 // Store & update w, h, format of PTOR layer
1096 private_handle_t *hnd = (private_handle_t *)layer->handle;
1097 Whf whf(hnd->width, hnd->height, hnd->format, hnd->size);
1098 layerWhf[j] = whf;
1099 hnd->width = renderBuf->width;
1100 hnd->height = renderBuf->height;
1101 hnd->format = renderBuf->format;
1102
Xu Yangcda012c2014-07-30 21:57:21 +08001103 // Store & update blending mode, planeAlpha and transform of PTOR layer
1104 blending[j] = layer->blending;
1105 planeAlpha[j] = layer->planeAlpha;
1106 transform[j] = layer->transform;
1107 layer->blending = HWC_BLENDING_NONE;
1108 layer->planeAlpha = 0xFF;
1109 layer->transform = 0;
1110
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001111 // Remove overlap from crop & displayFrame of below layers
1112 for (int i = 0; i < index && index !=-1; i++) {
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001113 layer = &list->hwLayers[i];
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001114 if(!isValidRect(getIntersection(layer->displayFrame,
1115 overlapRect[j]))) {
1116 continue;
1117 }
1118 // Update layer attributes
1119 hwc_rect_t srcCrop = integerizeSourceCrop(layer->sourceCropf);
1120 hwc_rect_t destRect = deductRect(layer->displayFrame,
Dileep Kumar Reddi72058b82014-11-11 16:03:03 +05301121 getIntersection(layer->displayFrame, overlapRect[j]));
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001122 qhwc::calculate_crop_rects(srcCrop, layer->displayFrame, destRect,
1123 layer->transform);
1124 layer->sourceCropf.left = (float)srcCrop.left;
1125 layer->sourceCropf.top = (float)srcCrop.top;
1126 layer->sourceCropf.right = (float)srcCrop.right;
1127 layer->sourceCropf.bottom = (float)srcCrop.bottom;
1128 }
Sushil Chauhandefd3522014-05-13 18:17:12 -07001129 }
1130
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001131 mCurrentFrame.mdpCount = numNonCursorLayers;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001132 mCurrentFrame.fbCount = 0;
1133 mCurrentFrame.fbZ = -1;
1134
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001135 for (int j = 0; j < numNonCursorLayers; j++) {
Dileep Kumar Reddi72058b82014-11-11 16:03:03 +05301136 if(isValidRect(list->hwLayers[j].displayFrame)) {
1137 mCurrentFrame.isFBComposed[j] = false;
1138 } else {
1139 mCurrentFrame.mdpCount--;
1140 mCurrentFrame.drop[j] = true;
1141 }
1142 }
Sushil Chauhandefd3522014-05-13 18:17:12 -07001143
1144 bool result = postHeuristicsHandling(ctx, list);
1145
1146 // Restore layer attributes
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001147 for(int i = 0; i < numNonCursorLayers; i++) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07001148 hwc_layer_1_t* layer = &list->hwLayers[i];
1149 layer->displayFrame = displayFrame[i];
1150 layer->sourceCropf.left = (float)sourceCrop[i].left;
1151 layer->sourceCropf.top = (float)sourceCrop[i].top;
1152 layer->sourceCropf.right = (float)sourceCrop[i].right;
1153 layer->sourceCropf.bottom = (float)sourceCrop[i].bottom;
1154 }
1155
Xu Yangcda012c2014-07-30 21:57:21 +08001156 // Restore w,h,f, blending attributes, and transform of PTOR layers
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001157 for (int i = 0; i < numPTORLayersFound; i++) {
1158 int idx = ctx->mPtorInfo.layerIndex[i];
Xu Yangcda012c2014-07-30 21:57:21 +08001159 hwc_layer_1_t* layer = &list->hwLayers[idx];
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001160 private_handle_t *hnd = (private_handle_t *)list->hwLayers[idx].handle;
1161 hnd->width = layerWhf[i].w;
1162 hnd->height = layerWhf[i].h;
1163 hnd->format = layerWhf[i].format;
Xu Yangcda012c2014-07-30 21:57:21 +08001164 layer->blending = blending[i];
1165 layer->planeAlpha = planeAlpha[i];
1166 layer->transform = transform[i];
Sushil Chauhan875a92e2014-07-25 12:20:23 -07001167 }
1168
Sushil Chauhandefd3522014-05-13 18:17:12 -07001169 if (!result) {
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001170 // reset PTOR
1171 ctx->mPtorInfo.count = 0;
Sushil Chauhandefd3522014-05-13 18:17:12 -07001172 reset(ctx);
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001173 } else {
1174 ALOGD_IF(isDebug(), "%s: PTOR Indexes: %d and %d", __FUNCTION__,
1175 ctx->mPtorInfo.layerIndex[0], ctx->mPtorInfo.layerIndex[1]);
Sushil Chauhandefd3522014-05-13 18:17:12 -07001176 }
1177
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07001178 ALOGD_IF(isDebug(), "%s: Postheuristics %s!", __FUNCTION__,
1179 (result ? "successful" : "failed"));
Sushil Chauhandefd3522014-05-13 18:17:12 -07001180 return result;
1181}
1182
Saurabh Shahaa236822013-04-24 18:07:26 -07001183bool MDPComp::partialMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list)
1184{
radhakrishnac3198ff2015-03-10 17:10:02 +05301185 if(!sEnableMixedMode || !isAlphaPresentinFB(ctx, mDpy)) {
1186 //Mixed mode is disabled/can't be used. No need to even try caching.
Jeykumar Sankaran24c199d2013-05-24 09:40:36 -07001187 return false;
1188 }
1189
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001190 bool ret = false;
Raj Kamal1179d9c2014-10-28 15:31:35 +05301191 if(isSkipPresent(ctx, mDpy) or list->flags & HWC_GEOMETRY_CHANGED) {
1192 //Try load based first
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001193 ret = loadBasedComp(ctx, list) or
Saurabh Shahf2de00f2013-12-11 17:52:53 -08001194 cacheBasedComp(ctx, list);
1195 } else {
1196 ret = cacheBasedComp(ctx, list) or
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001197 loadBasedComp(ctx, list);
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001198 }
1199
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001200 return ret;
1201}
1202
1203bool MDPComp::cacheBasedComp(hwc_context_t *ctx,
1204 hwc_display_contents_1_t* list) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001205 if(sSimulationFlags & MDPCOMP_AVOID_CACHE_MDP)
1206 return false;
1207
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001208 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shahaa236822013-04-24 18:07:26 -07001209 mCurrentFrame.reset(numAppLayers);
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001210 updateLayerCache(ctx, list, mCurrentFrame);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001211
1212 //If an MDP marked layer is unsupported cannot do partial MDP Comp
1213 for(int i = 0; i < numAppLayers; i++) {
1214 if(!mCurrentFrame.isFBComposed[i]) {
1215 hwc_layer_1_t* layer = &list->hwLayers[i];
1216 if(not isSupportedForMDPComp(ctx, layer)) {
1217 ALOGD_IF(isDebug(), "%s: Unsupported layer in list",
1218 __FUNCTION__);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001219 reset(ctx);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001220 return false;
1221 }
1222 }
1223 }
1224
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001225 updateYUV(ctx, list, false /*secure only*/, mCurrentFrame);
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001226 /* mark secure RGB layers for MDP comp */
1227 updateSecureRGB(ctx, list);
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301228 bool ret = markLayersForCaching(ctx, list); //sets up fbZ also
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001229 if(!ret) {
1230 ALOGD_IF(isDebug(),"%s: batching failed, dpy %d",__FUNCTION__, mDpy);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001231 reset(ctx);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001232 return false;
1233 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001234
1235 int mdpCount = mCurrentFrame.mdpCount;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001236
Raj Kamal389d6e32014-08-04 14:43:24 +05301237 if(sEnableYUVsplit){
Saurabh Shah3d4b8042013-12-10 15:19:17 -08001238 adjustForSourceSplit(ctx, list);
radhakrishnac9a67412013-09-25 17:40:42 +05301239 }
1240
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001241 if(!postHeuristicsHandling(ctx, list)) {
1242 ALOGD_IF(isDebug(), "post heuristic handling failed");
1243 reset(ctx);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07001244 return false;
1245 }
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001246 ALOGD_IF(sSimulationFlags,"%s: CACHE_MDP_COMP SUCCEEDED",
1247 __FUNCTION__);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07001248
Saurabh Shahaa236822013-04-24 18:07:26 -07001249 return true;
1250}
1251
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001252bool MDPComp::loadBasedComp(hwc_context_t *ctx,
Saurabh Shahb772ae32013-11-18 15:40:02 -08001253 hwc_display_contents_1_t* list) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001254 if(sSimulationFlags & MDPCOMP_AVOID_LOAD_MDP)
1255 return false;
1256
Arun Kumar K.R2aa44c62014-01-21 23:08:28 -08001257 if(not isLoadBasedCompDoable(ctx)) {
Saurabh Shahf2de00f2013-12-11 17:52:53 -08001258 return false;
1259 }
1260
Saurabh Shahb772ae32013-11-18 15:40:02 -08001261 const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001262 const int numNonDroppedLayers = numAppLayers - mCurrentFrame.dropCount;
1263 const int stagesForMDP = min(sMaxPipesPerMixer,
1264 ctx->mOverlay->availablePipes(mDpy, Overlay::MIXER_DEFAULT));
Saurabh Shahf2de00f2013-12-11 17:52:53 -08001265
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001266 int mdpBatchSize = stagesForMDP - 1; //1 stage for FB
1267 int fbBatchSize = numNonDroppedLayers - mdpBatchSize;
1268 int lastMDPSupportedIndex = numAppLayers;
1269 int dropCount = 0;
Saurabh Shahb772ae32013-11-18 15:40:02 -08001270
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001271 //Find the minimum MDP batch size
1272 for(int i = 0; i < numAppLayers;i++) {
1273 if(mCurrentFrame.drop[i]) {
1274 dropCount++;
Jeykumar Sankaran846e2792014-01-23 21:59:58 -08001275 continue;
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001276 }
1277 hwc_layer_1_t* layer = &list->hwLayers[i];
1278 if(not isSupportedForMDPComp(ctx, layer)) {
1279 lastMDPSupportedIndex = i;
1280 mdpBatchSize = min(i - dropCount, stagesForMDP - 1);
1281 fbBatchSize = numNonDroppedLayers - mdpBatchSize;
Jeykumar Sankaran846e2792014-01-23 21:59:58 -08001282 break;
Saurabh Shahb772ae32013-11-18 15:40:02 -08001283 }
Saurabh Shahb772ae32013-11-18 15:40:02 -08001284 }
1285
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001286 ALOGD_IF(isDebug(), "%s:Before optimizing fbBatch, mdpbatch %d, fbbatch %d "
1287 "dropped %d", __FUNCTION__, mdpBatchSize, fbBatchSize,
1288 mCurrentFrame.dropCount);
1289
1290 //Start at a point where the fb batch should at least have 2 layers, for
1291 //this mode to be justified.
1292 while(fbBatchSize < 2) {
1293 ++fbBatchSize;
1294 --mdpBatchSize;
Jeykumar Sankaran846e2792014-01-23 21:59:58 -08001295 }
Saurabh Shahb772ae32013-11-18 15:40:02 -08001296
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001297 //If there are no layers for MDP, this mode doesnt make sense.
1298 if(mdpBatchSize < 1) {
1299 ALOGD_IF(isDebug(), "%s: No MDP layers after optimizing for fbBatch",
1300 __FUNCTION__);
Saurabh Shahb772ae32013-11-18 15:40:02 -08001301 return false;
1302 }
1303
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001304 mCurrentFrame.reset(numAppLayers);
1305
1306 //Try with successively smaller mdp batch sizes until we succeed or reach 1
1307 while(mdpBatchSize > 0) {
1308 //Mark layers for MDP comp
1309 int mdpBatchLeft = mdpBatchSize;
1310 for(int i = 0; i < lastMDPSupportedIndex and mdpBatchLeft; i++) {
1311 if(mCurrentFrame.drop[i]) {
1312 continue;
1313 }
1314 mCurrentFrame.isFBComposed[i] = false;
1315 --mdpBatchLeft;
1316 }
1317
1318 mCurrentFrame.fbZ = mdpBatchSize;
1319 mCurrentFrame.fbCount = fbBatchSize;
1320 mCurrentFrame.mdpCount = mdpBatchSize;
1321
1322 ALOGD_IF(isDebug(), "%s:Trying with: mdpbatch %d fbbatch %d dropped %d",
1323 __FUNCTION__, mdpBatchSize, fbBatchSize,
1324 mCurrentFrame.dropCount);
1325
1326 if(postHeuristicsHandling(ctx, list)) {
1327 ALOGD_IF(isDebug(), "%s: Postheuristics handling succeeded",
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001328 __FUNCTION__);
1329 ALOGD_IF(sSimulationFlags,"%s: LOAD_MDP_COMP SUCCEEDED",
1330 __FUNCTION__);
Saurabh Shahbe7bd322014-02-20 16:18:45 -08001331 return true;
1332 }
1333
1334 reset(ctx);
1335 --mdpBatchSize;
1336 ++fbBatchSize;
1337 }
1338
1339 return false;
Saurabh Shahb772ae32013-11-18 15:40:02 -08001340}
1341
Arun Kumar K.R2aa44c62014-01-21 23:08:28 -08001342bool MDPComp::isLoadBasedCompDoable(hwc_context_t *ctx) {
Prabhanjan Kandula3dbbd882013-12-11 14:43:46 +05301343 if(mDpy or isSecurePresent(ctx, mDpy) or
1344 isYuvPresent(ctx, mDpy)) {
Saurabh Shah8028e3b2013-10-15 12:27:59 -07001345 return false;
1346 }
1347 return true;
1348}
1349
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001350bool MDPComp::canPartialUpdate(hwc_context_t *ctx,
1351 hwc_display_contents_1_t* list){
1352 if(!qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() ||
1353 isSkipPresent(ctx, mDpy) || (list->flags & HWC_GEOMETRY_CHANGED) ||
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001354 isCursorPresent(ctx, mDpy) || !sIsPartialUpdateActive || mDpy) {
1355 // On Async position update, the ROI becomes invalid, hence disable PU
1356 // when cursor is present
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001357 return false;
1358 }
Jeykumar Sankaran4dd10ab2014-07-02 12:23:09 -07001359 if(ctx->listStats[mDpy].secureUI)
1360 return false;
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001361 return true;
1362}
1363
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001364bool MDPComp::tryVideoOnly(hwc_context_t *ctx,
1365 hwc_display_contents_1_t* list) {
1366 const bool secureOnly = true;
1367 return videoOnlyComp(ctx, list, not secureOnly) or
1368 videoOnlyComp(ctx, list, secureOnly);
1369}
1370
1371bool MDPComp::videoOnlyComp(hwc_context_t *ctx,
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001372 hwc_display_contents_1_t* list, bool secureOnly) {
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001373 if(sSimulationFlags & MDPCOMP_AVOID_VIDEO_ONLY)
1374 return false;
Praveena Pachipulusu47346c22014-12-04 11:06:41 +05301375
Saurabh Shahaa236822013-04-24 18:07:26 -07001376 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Praveena Pachipulusu47346c22014-12-04 11:06:41 +05301377 if(!isSecurePresent(ctx, mDpy)) {
1378 /* Bail out if we are processing only secured video layers
1379 * and we dont have any */
1380 if(secureOnly) {
1381 ALOGD_IF(isDebug(),"%s: No Secure Video Layers", __FUNCTION__);
1382 return false;
1383 }
1384 /* No Idle fall back for secure video layers and if there is only
1385 * single layer being composed. */
1386 if(sIdleFallBack && (ctx->listStats[mDpy].numAppLayers > 1)) {
1387 ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
1388 return false;
1389 }
1390 }
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001391
Saurabh Shahaa236822013-04-24 18:07:26 -07001392 mCurrentFrame.reset(numAppLayers);
Jeykumar Sankaraneb3a5e22014-04-08 16:07:55 -07001393 mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001394 updateYUV(ctx, list, secureOnly, mCurrentFrame);
Saurabh Shah4fdde762013-04-30 18:47:33 -07001395 int mdpCount = mCurrentFrame.mdpCount;
Saurabh Shahaa236822013-04-24 18:07:26 -07001396
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001397 if(!isYuvPresent(ctx, mDpy) or (mdpCount == 0)) {
1398 reset(ctx);
Saurabh Shahaa236822013-04-24 18:07:26 -07001399 return false;
1400 }
1401
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001402 if(mCurrentFrame.fbCount)
1403 mCurrentFrame.fbZ = mCurrentFrame.mdpCount;
Saurabh Shah4fdde762013-04-30 18:47:33 -07001404
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05001405 if(sEnableYUVsplit || needs3DComposition(ctx, mDpy)){
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001406 adjustForSourceSplit(ctx, list);
1407 }
1408
1409 if(!postHeuristicsHandling(ctx, list)) {
1410 ALOGD_IF(isDebug(), "post heuristic handling failed");
Justin Philip37ab9a82015-01-06 11:55:12 +05301411 if(errno == ENOBUFS) {
1412 ALOGD_IF(isDebug(), "SMP Allocation failed");
1413 //On SMP allocation failure in video only comp add padding round
1414 ctx->isPaddingRound = true;
1415 }
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001416 reset(ctx);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07001417 return false;
1418 }
1419
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07001420 ALOGD_IF(sSimulationFlags,"%s: VIDEO_ONLY_COMP SUCCEEDED",
1421 __FUNCTION__);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001422 return true;
1423}
1424
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001425/* if tryFullFrame fails, try to push all video and secure RGB layers to MDP */
1426bool MDPComp::tryMDPOnlyLayers(hwc_context_t *ctx,
1427 hwc_display_contents_1_t* list) {
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001428 // Fall back to video only composition, if AIV video mode is enabled
1429 if(ctx->listStats[mDpy].mAIVVideoMode) {
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07001430 ALOGD_IF(isDebug(), "%s: AIV Video Mode enabled dpy %d",
1431 __FUNCTION__, mDpy);
1432 return false;
1433 }
1434
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05001435 // No MDP composition for 3D
1436 if(needs3DComposition(ctx,mDpy))
1437 return false;
1438
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001439 const bool secureOnly = true;
1440 return mdpOnlyLayersComp(ctx, list, not secureOnly) or
1441 mdpOnlyLayersComp(ctx, list, secureOnly);
1442
1443}
1444
1445bool MDPComp::mdpOnlyLayersComp(hwc_context_t *ctx,
1446 hwc_display_contents_1_t* list, bool secureOnly) {
1447
1448 if(sSimulationFlags & MDPCOMP_AVOID_MDP_ONLY_LAYERS)
1449 return false;
1450
Praveena Pachipulusu47346c22014-12-04 11:06:41 +05301451 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
1452 if(!isSecurePresent(ctx, mDpy) && !ctx->listStats[mDpy].secureUI) {
1453 /* Bail out if we are processing only secured video/ui layers
1454 * and we dont have any */
1455 if(secureOnly) {
1456 ALOGD_IF(isDebug(), "%s: No secure video/ui layers");
1457 return false;
1458 }
1459 /* No Idle fall back for secure video/ui layers and if there is only
1460 * single layer being composed. */
1461 if(sIdleFallBack && (ctx->listStats[mDpy].numAppLayers > 1)) {
1462 ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
1463 return false;
1464 }
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001465 }
1466
Tatenda Chipeperekwa95675a72014-12-15 17:06:43 -08001467 /* Bail out if we dont have any secure RGB layers */
1468 if (!ctx->listStats[mDpy].secureRGBCount) {
1469 reset(ctx);
1470 return false;
1471 }
1472
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001473 mCurrentFrame.reset(numAppLayers);
1474 mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
1475
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001476 updateYUV(ctx, list, secureOnly, mCurrentFrame);
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001477 /* mark secure RGB layers for MDP comp */
1478 updateSecureRGB(ctx, list);
1479
1480 if(mCurrentFrame.mdpCount == 0) {
1481 reset(ctx);
1482 return false;
1483 }
1484
1485 /* find the maximum batch of layers to be marked for framebuffer */
1486 bool ret = markLayersForCaching(ctx, list); //sets up fbZ also
1487 if(!ret) {
1488 ALOGD_IF(isDebug(),"%s: batching failed, dpy %d",__FUNCTION__, mDpy);
1489 reset(ctx);
1490 return false;
1491 }
1492
1493 if(sEnableYUVsplit){
1494 adjustForSourceSplit(ctx, list);
1495 }
1496
1497 if(!postHeuristicsHandling(ctx, list)) {
1498 ALOGD_IF(isDebug(), "post heuristic handling failed");
1499 reset(ctx);
1500 return false;
1501 }
1502
1503 ALOGD_IF(sSimulationFlags,"%s: MDP_ONLY_LAYERS_COMP SUCCEEDED",
1504 __FUNCTION__);
1505 return true;
1506}
1507
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001508/* Checks for conditions where YUV layers cannot be bypassed */
1509bool MDPComp::isYUVDoable(hwc_context_t* ctx, hwc_layer_1_t* layer) {
Ramkumar Radhakrishnana70981a2013-08-28 11:33:53 -07001510 if(isSkipLayer(layer)) {
Saurabh Shahe2474082013-05-15 16:32:13 -07001511 ALOGD_IF(isDebug(), "%s: Video marked SKIP dpy %d", __FUNCTION__, mDpy);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001512 return false;
1513 }
1514
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08001515 if(has90Transform(layer) && !canUseRotator(ctx, mDpy)) {
Amara Venkata Mastan Manoj Kumar9d373c02013-08-20 14:30:09 -07001516 ALOGD_IF(isDebug(), "%s: no free DMA pipe",__FUNCTION__);
1517 return false;
1518 }
1519
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001520 if(isSecuring(ctx, layer)) {
1521 ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
1522 return false;
1523 }
1524
Saurabh Shah4fdde762013-04-30 18:47:33 -07001525 if(!isValidDimension(ctx, layer)) {
1526 ALOGD_IF(isDebug(), "%s: Buffer is of invalid width",
1527 __FUNCTION__);
1528 return false;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001529 }
Saurabh Shah4fdde762013-04-30 18:47:33 -07001530
Naseer Ahmeddc61a972013-07-10 17:50:54 -04001531 if(layer->planeAlpha < 0xFF) {
1532 ALOGD_IF(isDebug(), "%s: Cannot handle YUV layer with plane alpha\
1533 in video only mode",
1534 __FUNCTION__);
1535 return false;
1536 }
1537
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001538 return true;
1539}
1540
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001541/* Checks for conditions where Secure RGB layers cannot be bypassed */
1542bool MDPComp::isSecureRGBDoable(hwc_context_t* ctx, hwc_layer_1_t* layer) {
1543 if(isSkipLayer(layer)) {
1544 ALOGD_IF(isDebug(), "%s: Secure RGB layer marked SKIP dpy %d",
1545 __FUNCTION__, mDpy);
1546 return false;
1547 }
1548
1549 if(isSecuring(ctx, layer)) {
1550 ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
1551 return false;
1552 }
1553
1554 if(not isSupportedForMDPComp(ctx, layer)) {
1555 ALOGD_IF(isDebug(), "%s: Unsupported secure RGB layer",
1556 __FUNCTION__);
1557 return false;
1558 }
1559 return true;
1560}
1561
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301562/* starts at fromIndex and check for each layer to find
1563 * if it it has overlapping with any Updating layer above it in zorder
1564 * till the end of the batch. returns true if it finds any intersection */
1565bool MDPComp::canPushBatchToTop(const hwc_display_contents_1_t* list,
1566 int fromIndex, int toIndex) {
1567 for(int i = fromIndex; i < toIndex; i++) {
1568 if(mCurrentFrame.isFBComposed[i] && !mCurrentFrame.drop[i]) {
1569 if(intersectingUpdatingLayers(list, i+1, toIndex, i)) {
1570 return false;
1571 }
1572 }
1573 }
1574 return true;
1575}
1576
1577/* Checks if given layer at targetLayerIndex has any
1578 * intersection with all the updating layers in beween
1579 * fromIndex and toIndex. Returns true if it finds intersectiion */
1580bool MDPComp::intersectingUpdatingLayers(const hwc_display_contents_1_t* list,
1581 int fromIndex, int toIndex, int targetLayerIndex) {
1582 for(int i = fromIndex; i <= toIndex; i++) {
1583 if(!mCurrentFrame.isFBComposed[i]) {
1584 if(areLayersIntersecting(&list->hwLayers[i],
1585 &list->hwLayers[targetLayerIndex])) {
1586 return true;
1587 }
1588 }
1589 }
1590 return false;
1591}
1592
1593int MDPComp::getBatch(hwc_display_contents_1_t* list,
1594 int& maxBatchStart, int& maxBatchEnd,
1595 int& maxBatchCount) {
1596 int i = 0;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301597 int fbZOrder =-1;
Jeykumar Sankaran9502f352014-01-20 12:25:32 -08001598 int droppedLayerCt = 0;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301599 while (i < mCurrentFrame.layerCount) {
1600 int batchCount = 0;
1601 int batchStart = i;
1602 int batchEnd = i;
Jeykumar Sankaran9502f352014-01-20 12:25:32 -08001603 /* Adjust batch Z order with the dropped layers so far */
1604 int fbZ = batchStart - droppedLayerCt;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301605 int firstZReverseIndex = -1;
Prabhanjan Kandula0ed2cc92013-12-06 12:39:04 +05301606 int updatingLayersAbove = 0;//Updating layer count in middle of batch
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301607 while(i < mCurrentFrame.layerCount) {
1608 if(!mCurrentFrame.isFBComposed[i]) {
1609 if(!batchCount) {
1610 i++;
1611 break;
1612 }
1613 updatingLayersAbove++;
1614 i++;
1615 continue;
1616 } else {
1617 if(mCurrentFrame.drop[i]) {
1618 i++;
Jeykumar Sankaran9502f352014-01-20 12:25:32 -08001619 droppedLayerCt++;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301620 continue;
1621 } else if(updatingLayersAbove <= 0) {
1622 batchCount++;
1623 batchEnd = i;
1624 i++;
1625 continue;
1626 } else { //Layer is FBComposed, not a drop & updatingLayer > 0
1627
1628 // We have a valid updating layer already. If layer-i not
1629 // have overlapping with all updating layers in between
1630 // batch-start and i, then we can add layer i to batch.
1631 if(!intersectingUpdatingLayers(list, batchStart, i-1, i)) {
1632 batchCount++;
1633 batchEnd = i;
1634 i++;
1635 continue;
1636 } else if(canPushBatchToTop(list, batchStart, i)) {
1637 //If All the non-updating layers with in this batch
1638 //does not have intersection with the updating layers
1639 //above in z-order, then we can safely move the batch to
1640 //higher z-order. Increment fbZ as it is moving up.
1641 if( firstZReverseIndex < 0) {
1642 firstZReverseIndex = i;
1643 }
1644 batchCount++;
1645 batchEnd = i;
1646 fbZ += updatingLayersAbove;
1647 i++;
1648 updatingLayersAbove = 0;
1649 continue;
1650 } else {
1651 //both failed.start the loop again from here.
1652 if(firstZReverseIndex >= 0) {
1653 i = firstZReverseIndex;
1654 }
1655 break;
1656 }
1657 }
1658 }
1659 }
1660 if(batchCount > maxBatchCount) {
1661 maxBatchCount = batchCount;
1662 maxBatchStart = batchStart;
1663 maxBatchEnd = batchEnd;
1664 fbZOrder = fbZ;
1665 }
1666 }
1667 return fbZOrder;
1668}
1669
1670bool MDPComp::markLayersForCaching(hwc_context_t* ctx,
1671 hwc_display_contents_1_t* list) {
1672 /* Idea is to keep as many non-updating(cached) layers in FB and
1673 * send rest of them through MDP. This is done in 2 steps.
1674 * 1. Find the maximum contiguous batch of non-updating layers.
1675 * 2. See if we can improve this batch size for caching by adding
1676 * opaque layers around the batch, if they don't have
1677 * any overlapping with the updating layers in between.
1678 * NEVER mark an updating layer for caching.
1679 * But cached ones can be marked for MDP */
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001680
1681 int maxBatchStart = -1;
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001682 int maxBatchEnd = -1;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001683 int maxBatchCount = 0;
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301684 int fbZ = -1;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001685
Saurabh Shahd53bc5f2014-02-05 10:17:43 -08001686 /* Nothing is cached. No batching needed */
1687 if(mCurrentFrame.fbCount == 0) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001688 return true;
Saurabh Shahaa236822013-04-24 18:07:26 -07001689 }
Saurabh Shahd53bc5f2014-02-05 10:17:43 -08001690
1691 /* No MDP comp layers, try to use other comp modes */
1692 if(mCurrentFrame.mdpCount == 0) {
1693 return false;
Saurabh Shahaa236822013-04-24 18:07:26 -07001694 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001695
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301696 fbZ = getBatch(list, maxBatchStart, maxBatchEnd, maxBatchCount);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001697
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301698 /* reset rest of the layers lying inside ROI for MDP comp */
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001699 for(int i = 0; i < mCurrentFrame.layerCount; i++) {
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001700 hwc_layer_1_t* layer = &list->hwLayers[i];
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001701 if((i < maxBatchStart || i > maxBatchEnd) &&
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301702 mCurrentFrame.isFBComposed[i]){
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001703 if(!mCurrentFrame.drop[i]){
1704 //If an unsupported layer is being attempted to
1705 //be pulled out we should fail
1706 if(not isSupportedForMDPComp(ctx, layer)) {
1707 return false;
1708 }
1709 mCurrentFrame.isFBComposed[i] = false;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001710 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001711 }
1712 }
1713
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301714 // update the frame data
1715 mCurrentFrame.fbZ = fbZ;
1716 mCurrentFrame.fbCount = maxBatchCount;
Saurabh Shahaa236822013-04-24 18:07:26 -07001717 mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001718 mCurrentFrame.fbCount - mCurrentFrame.dropCount;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001719
1720 ALOGD_IF(isDebug(),"%s: cached count: %d",__FUNCTION__,
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301721 mCurrentFrame.fbCount);
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001722
1723 return true;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001724}
Saurabh Shah85234ec2013-04-12 17:09:00 -07001725
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001726void MDPComp::updateLayerCache(hwc_context_t* ctx,
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001727 hwc_display_contents_1_t* list, FrameInfo& frame) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001728 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001729 int fbCount = 0;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001730
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001731 for(int i = 0; i < numAppLayers; i++) {
1732 if (mCachedFrame.hnd[i] == list->hwLayers[i].handle) {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001733 if(!frame.drop[i])
Jeykumar Sankaran6a9bb9e2013-08-01 14:19:26 -07001734 fbCount++;
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001735 frame.isFBComposed[i] = true;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001736 } else {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001737 frame.isFBComposed[i] = false;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001738 }
1739 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001740
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001741 frame.fbCount = fbCount;
1742 frame.mdpCount = frame.layerCount - frame.fbCount
1743 - frame.dropCount;
Saurabh Shahe9bc60f2013-08-29 12:58:06 -07001744
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001745 ALOGD_IF(isDebug(),"%s: MDP count: %d FB count %d drop count: %d",
1746 __FUNCTION__, frame.mdpCount, frame.fbCount, frame.dropCount);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001747}
1748
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001749// drop other non-AIV layers from external display list.
1750void MDPComp::dropNonAIVLayers(hwc_context_t* ctx,
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07001751 hwc_display_contents_1_t* list) {
1752 for (size_t i = 0; i < (size_t)ctx->listStats[mDpy].numAppLayers; i++) {
1753 hwc_layer_1_t * layer = &list->hwLayers[i];
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001754 if(!(isAIVVideoLayer(layer) || isAIVCCLayer(layer))) {
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07001755 mCurrentFrame.dropCount++;
1756 mCurrentFrame.drop[i] = true;
1757 }
1758 }
1759 mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
1760 mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
1761 mCurrentFrame.fbCount - mCurrentFrame.dropCount;
1762 ALOGD_IF(isDebug(),"%s: fb count: %d mdp count %d drop count %d",
1763 __FUNCTION__, mCurrentFrame.fbCount, mCurrentFrame.mdpCount,
1764 mCurrentFrame.dropCount);
1765}
1766
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001767void MDPComp::updateYUV(hwc_context_t* ctx, hwc_display_contents_1_t* list,
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001768 bool secureOnly, FrameInfo& frame) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001769 int nYuvCount = ctx->listStats[mDpy].yuvCount;
1770 for(int index = 0;index < nYuvCount; index++){
1771 int nYuvIndex = ctx->listStats[mDpy].yuvIndices[index];
1772 hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
1773
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07001774 if(mCurrentFrame.drop[nYuvIndex]) {
1775 continue;
1776 }
1777
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001778 if(!isYUVDoable(ctx, layer)) {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001779 if(!frame.isFBComposed[nYuvIndex]) {
1780 frame.isFBComposed[nYuvIndex] = true;
1781 frame.fbCount++;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001782 }
1783 } else {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001784 if(frame.isFBComposed[nYuvIndex]) {
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001785 private_handle_t *hnd = (private_handle_t *)layer->handle;
1786 if(!secureOnly || isSecureBuffer(hnd)) {
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001787 frame.isFBComposed[nYuvIndex] = false;
1788 frame.fbCount--;
Saurabh Shah90b7b9b2013-09-12 16:36:08 -07001789 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001790 }
1791 }
1792 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001793
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07001794 frame.mdpCount = frame.layerCount - frame.fbCount - frame.dropCount;
1795 ALOGD_IF(isDebug(),"%s: fb count: %d",__FUNCTION__, frame.fbCount);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001796}
1797
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07001798void MDPComp::updateSecureRGB(hwc_context_t* ctx,
1799 hwc_display_contents_1_t* list) {
1800 int nSecureRGBCount = ctx->listStats[mDpy].secureRGBCount;
1801 for(int index = 0;index < nSecureRGBCount; index++){
1802 int nSecureRGBIndex = ctx->listStats[mDpy].secureRGBIndices[index];
1803 hwc_layer_1_t* layer = &list->hwLayers[nSecureRGBIndex];
1804
1805 if(!isSecureRGBDoable(ctx, layer)) {
1806 if(!mCurrentFrame.isFBComposed[nSecureRGBIndex]) {
1807 mCurrentFrame.isFBComposed[nSecureRGBIndex] = true;
1808 mCurrentFrame.fbCount++;
1809 }
1810 } else {
1811 if(mCurrentFrame.isFBComposed[nSecureRGBIndex]) {
1812 mCurrentFrame.isFBComposed[nSecureRGBIndex] = false;
1813 mCurrentFrame.fbCount--;
1814 }
1815 }
1816 }
1817
1818 mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
1819 mCurrentFrame.fbCount - mCurrentFrame.dropCount;
1820 ALOGD_IF(isDebug(),"%s: fb count: %d",__FUNCTION__,
1821 mCurrentFrame.fbCount);
1822}
1823
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001824hwc_rect_t MDPComp::getUpdatingFBRect(hwc_context_t *ctx,
1825 hwc_display_contents_1_t* list){
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001826 hwc_rect_t fbRect = (struct hwc_rect){0, 0, 0, 0};
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001827
1828 /* Update only the region of FB needed for composition */
1829 for(int i = 0; i < mCurrentFrame.layerCount; i++ ) {
1830 if(mCurrentFrame.isFBComposed[i] && !mCurrentFrame.drop[i]) {
1831 hwc_layer_1_t* layer = &list->hwLayers[i];
1832 hwc_rect_t dst = layer->displayFrame;
1833 fbRect = getUnion(fbRect, dst);
1834 }
1835 }
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08001836 trimAgainstROI(ctx, fbRect, fbRect);
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001837 return fbRect;
1838}
1839
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001840bool MDPComp::postHeuristicsHandling(hwc_context_t *ctx,
1841 hwc_display_contents_1_t* list) {
1842
1843 //Capability checks
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08001844 if(!resourceCheck(ctx, list)) {
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001845 ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
1846 return false;
1847 }
1848
1849 //Limitations checks
1850 if(!hwLimitationsCheck(ctx, list)) {
1851 ALOGD_IF(isDebug(), "%s: HW limitations",__FUNCTION__);
1852 return false;
1853 }
1854
Saurabh Shah3d4b8042013-12-10 15:19:17 -08001855 //Configure framebuffer first if applicable
1856 if(mCurrentFrame.fbZ >= 0) {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08001857 hwc_rect_t fbRect = getUpdatingFBRect(ctx, list);
Jeykumar Sankaranc2d78d82014-02-14 14:55:29 -08001858 if(!ctx->mFBUpdate[mDpy]->prepare(ctx, list, fbRect, mCurrentFrame.fbZ))
1859 {
Saurabh Shah3d4b8042013-12-10 15:19:17 -08001860 ALOGD_IF(isDebug(), "%s configure framebuffer failed",
1861 __FUNCTION__);
1862 return false;
1863 }
1864 }
1865
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001866 mCurrentFrame.map();
1867
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001868 if(!allocLayerPipes(ctx, list)) {
1869 ALOGD_IF(isDebug(), "%s: Unable to allocate MDP pipes", __FUNCTION__);
Saurabh Shahaa236822013-04-24 18:07:26 -07001870 return false;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001871 }
1872
1873 for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
Saurabh Shahaa236822013-04-24 18:07:26 -07001874 index++) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001875 if(!mCurrentFrame.isFBComposed[index]) {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001876 int mdpIndex = mCurrentFrame.layerToMDP[index];
1877 hwc_layer_1_t* layer = &list->hwLayers[index];
1878
Prabhanjan Kandula9bd5f642013-09-25 17:00:36 +05301879 //Leave fbZ for framebuffer. CACHE/GLES layers go here.
1880 if(mdpNextZOrder == mCurrentFrame.fbZ) {
1881 mdpNextZOrder++;
1882 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001883 MdpPipeInfo* cur_pipe = mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
1884 cur_pipe->zOrder = mdpNextZOrder++;
1885
radhakrishnac9a67412013-09-25 17:40:42 +05301886 private_handle_t *hnd = (private_handle_t *)layer->handle;
Raj Kamal389d6e32014-08-04 14:43:24 +05301887 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
radhakrishnac9a67412013-09-25 17:40:42 +05301888 if(configure4k2kYuv(ctx, layer,
1889 mCurrentFrame.mdpToLayer[mdpIndex])
1890 != 0 ){
1891 ALOGD_IF(isDebug(), "%s: Failed to configure split pipes \
1892 for layer %d",__FUNCTION__, index);
1893 return false;
1894 }
1895 else{
1896 mdpNextZOrder++;
1897 }
1898 continue;
1899 }
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05001900 if(needs3DComposition(ctx,mDpy) && get3DFormat(hnd) != HAL_NO_3D) {
1901 mdpNextZOrder++;
1902 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001903 if(configure(ctx, layer, mCurrentFrame.mdpToLayer[mdpIndex]) != 0 ){
1904 ALOGD_IF(isDebug(), "%s: Failed to configure overlay for \
radhakrishnac9a67412013-09-25 17:40:42 +05301905 layer %d",__FUNCTION__, index);
Saurabh Shahaa236822013-04-24 18:07:26 -07001906 return false;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001907 }
Saurabh Shahaa236822013-04-24 18:07:26 -07001908 }
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001909 }
1910
Saurabh Shaha36be922013-12-16 18:18:39 -08001911 if(!ctx->mOverlay->validateAndSet(mDpy, ctx->dpyAttr[mDpy].fd)) {
1912 ALOGD_IF(isDebug(), "%s: Failed to validate and set overlay for dpy %d"
1913 ,__FUNCTION__, mDpy);
1914 return false;
1915 }
1916
Saurabh Shahdf4741d2013-12-12 16:40:28 -08001917 setRedraw(ctx, list);
Saurabh Shahaa236822013-04-24 18:07:26 -07001918 return true;
1919}
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08001920
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08001921bool MDPComp::resourceCheck(hwc_context_t* ctx,
1922 hwc_display_contents_1_t* list) {
Saurabh Shah173f4242013-11-20 09:50:12 -08001923 const bool fbUsed = mCurrentFrame.fbCount;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07001924 int cursorInUse = 0;
1925 if(mDpy == HWC_DISPLAY_PRIMARY) {
1926 // check if cursor is in use for primary
1927 cursorInUse = HWCursor::getInstance()->isCursorSet();
1928 }
1929 int maxStages = qdutils::MDPVersion::getInstance().getBlendStages();
1930 // HW Cursor needs one blending stage, account for that in the check below
1931 // On high end targets(8994) has 8 blending stages, HAL is configured to use < 8.
1932 // Make use of the remaining stages for HW Cursor so that the composition
1933 // strategy would not fail due to this limitation.
1934 if (maxStages > sMaxPipesPerMixer) {
1935 cursorInUse = 0;
1936 }
1937 if(mCurrentFrame.mdpCount > (sMaxPipesPerMixer - fbUsed - cursorInUse)) {
Saurabh Shah173f4242013-11-20 09:50:12 -08001938 ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
1939 return false;
1940 }
Saurabh Shahacec8e42014-11-25 11:07:04 -08001941
1942 //Will benefit cases where a video has non-updating background.
1943 if((mDpy > HWC_DISPLAY_PRIMARY) and
1944 (mCurrentFrame.mdpCount > sMaxSecLayers)) {
1945 ALOGD_IF(isDebug(), "%s: Exceeds max secondary pipes",__FUNCTION__);
1946 return false;
1947 }
1948
Ramkumar Radhakrishnan9d20b392013-11-15 19:32:47 -08001949 // Init rotCount to number of rotate sessions used by other displays
1950 int rotCount = ctx->mRotMgr->getNumActiveSessions();
1951 // Count the number of rotator sessions required for current display
1952 for (int index = 0; index < mCurrentFrame.layerCount; index++) {
1953 if(!mCurrentFrame.isFBComposed[index]) {
1954 hwc_layer_1_t* layer = &list->hwLayers[index];
1955 private_handle_t *hnd = (private_handle_t *)layer->handle;
1956 if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
1957 rotCount++;
1958 }
1959 }
1960 }
1961 // if number of layers to rotate exceeds max rotator sessions, bail out.
1962 if(rotCount > RotMgr::MAX_ROT_SESS) {
1963 ALOGD_IF(isDebug(), "%s: Exceeds max rotator sessions %d",
1964 __FUNCTION__, mDpy);
1965 return false;
1966 }
Saurabh Shah173f4242013-11-20 09:50:12 -08001967 return true;
1968}
1969
Prabhanjan Kandula21918db2013-11-26 15:51:58 +05301970bool MDPComp::hwLimitationsCheck(hwc_context_t* ctx,
1971 hwc_display_contents_1_t* list) {
1972
1973 //A-family hw limitation:
1974 //If a layer need alpha scaling, MDP can not support.
1975 if(ctx->mMDP.version < qdutils::MDSS_V5) {
1976 for(int i = 0; i < mCurrentFrame.layerCount; ++i) {
1977 if(!mCurrentFrame.isFBComposed[i] &&
1978 isAlphaScaled( &list->hwLayers[i])) {
1979 ALOGD_IF(isDebug(), "%s:frame needs alphaScaling",__FUNCTION__);
1980 return false;
1981 }
1982 }
1983 }
1984
1985 // On 8x26 & 8974 hw, we have a limitation of downscaling+blending.
1986 //If multiple layers requires downscaling and also they are overlapping
1987 //fall back to GPU since MDSS can not handle it.
1988 if(qdutils::MDPVersion::getInstance().is8x74v2() ||
1989 qdutils::MDPVersion::getInstance().is8x26()) {
1990 for(int i = 0; i < mCurrentFrame.layerCount-1; ++i) {
1991 hwc_layer_1_t* botLayer = &list->hwLayers[i];
1992 if(!mCurrentFrame.isFBComposed[i] &&
1993 isDownscaleRequired(botLayer)) {
1994 //if layer-i is marked for MDP and needs downscaling
1995 //check if any MDP layer on top of i & overlaps with layer-i
1996 for(int j = i+1; j < mCurrentFrame.layerCount; ++j) {
1997 hwc_layer_1_t* topLayer = &list->hwLayers[j];
1998 if(!mCurrentFrame.isFBComposed[j] &&
1999 isDownscaleRequired(topLayer)) {
2000 hwc_rect_t r = getIntersection(botLayer->displayFrame,
2001 topLayer->displayFrame);
2002 if(isValidRect(r))
2003 return false;
2004 }
2005 }
2006 }
2007 }
2008 }
2009 return true;
2010}
2011
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002012static bool validForCursor(hwc_context_t* ctx, int dpy, hwc_layer_1_t* layer) {
2013 private_handle_t *hnd = (private_handle_t *)layer->handle;
2014 hwc_rect dst = layer->displayFrame;
2015 hwc_rect src = integerizeSourceCrop(layer->sourceCropf);
2016 int srcW = src.right - src.left;
2017 int srcH = src.bottom - src.top;
2018 int dstW = dst.right - dst.left;
2019 int dstH = dst.bottom - dst.top;
2020 qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
2021 uint32_t maxCursorSize = mdpVersion.getMaxCursorSize();
2022 uint32_t numHwCursors = mdpVersion.getCursorPipes();
2023 bool primarySplit = isDisplaySplit(ctx, HWC_DISPLAY_PRIMARY);
2024 uint32_t cursorPipesNeeded = 1; // One cursor pipe needed(default)
2025 bool ret = false;
2026
2027 if(dpy > HWC_DISPLAY_PRIMARY) {
2028 // Cursor not supported on secondary displays, as it involves scaling
2029 // in most of the cases
2030 return false;
2031 } else if (isSkipLayer(layer)) {
2032 return false;
2033 // Checks for HW limitation
2034 } else if (numHwCursors == 0 || maxCursorSize <= 0) {
2035 return false;
2036 } else if (needsScaling(layer)) {
2037 return false;
2038 } else if (layer->transform != 0) {
2039 return false;
2040 } else if (hnd->format != HAL_PIXEL_FORMAT_RGBA_8888) {
2041 return false;
2042 } else if (srcW > (int)maxCursorSize || srcH > (int)maxCursorSize) {
2043 return false;
2044 }
2045
2046 if (isDisplaySplit(ctx, dpy) && !mdpVersion.isSrcSplit()) {
2047 // In case of split display with no srcSplit, the driver allocates two
2048 // pipes to support async position update across mixers, hence
2049 // need to account for that here.
2050 cursorPipesNeeded = 2;
2051 }
2052 if (cursorPipesNeeded <= numHwCursors) {
2053 ret = true;
2054 }
2055 return ret;
2056}
2057
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08002058// Checks only if videos or single layer(RGB) is updating
2059// which is used for setting dynamic fps or perf hint for single
2060// layer video playback
2061bool MDPComp::onlyVideosUpdating(hwc_context_t *ctx,
2062 hwc_display_contents_1_t* list) {
2063 bool support = false;
2064 FrameInfo frame;
2065 frame.reset(mCurrentFrame.layerCount);
2066 memset(&frame.drop, 0, sizeof(frame.drop));
2067 frame.dropCount = 0;
2068 ALOGD_IF(isDebug(), "%s: Update Cache and YUVInfo", __FUNCTION__);
2069 updateLayerCache(ctx, list, frame);
2070 updateYUV(ctx, list, false /*secure only*/, frame);
2071 // There are only updating YUV layers or there is single RGB
2072 // Layer(Youtube)
2073 if((ctx->listStats[mDpy].yuvCount == frame.mdpCount) ||
2074 (frame.layerCount == 1)) {
2075 support = true;
2076 }
2077 return support;
2078}
2079
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302080void MDPComp::setDynRefreshRate(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
2081 //For primary display, set the dynamic refreshrate
2082 if(!mDpy && qdutils::MDPVersion::getInstance().isDynFpsSupported() &&
2083 ctx->mUseMetaDataRefreshRate) {
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302084 uint32_t refreshRate = ctx->dpyAttr[mDpy].refreshRate;
2085 MDPVersion& mdpHw = MDPVersion::getInstance();
2086 if(sIdleFallBack) {
2087 //Set minimum panel refresh rate during idle timeout
2088 refreshRate = mdpHw.getMinFpsSupported();
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08002089 } else if(onlyVideosUpdating(ctx, list)) {
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302090 //Set the new fresh rate, if there is only one updating YUV layer
2091 //or there is one single RGB layer with this request
2092 refreshRate = ctx->listStats[mDpy].refreshRateRequest;
2093 }
2094 setRefreshRate(ctx, mDpy, refreshRate);
2095 }
2096}
2097
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002098int MDPComp::prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002099 int ret = 0;
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07002100 char property[PROPERTY_VALUE_MAX];
2101
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002102 if(!list) {
2103 ALOGE("%s: Invalid list", __FUNCTION__);
Raj Kamal4393eaa2014-06-06 13:45:20 +05302104 mCachedFrame.reset();
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002105 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Raj Kamal4393eaa2014-06-06 13:45:20 +05302106 return -1;
2107 }
2108
2109 const int numLayers = ctx->listStats[mDpy].numAppLayers;
Saurabh Shah286cf122014-09-08 14:13:08 -07002110 if(mDpy == HWC_DISPLAY_PRIMARY) {
2111 sSimulationFlags = 0;
2112 if(property_get("debug.hwc.simulate", property, NULL) > 0) {
2113 int currentFlags = atoi(property);
2114 if(currentFlags != sSimulationFlags) {
2115 sSimulationFlags = currentFlags;
2116 ALOGI("%s: Simulation Flag read: 0x%x (%d)", __FUNCTION__,
2117 sSimulationFlags, sSimulationFlags);
2118 }
Jeykumar Sankaran0ad97c42014-03-09 23:00:53 -07002119 }
2120 }
Ramkumar Radhakrishnanc5893f12013-06-06 19:43:53 -07002121
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302122 //reset old data
2123 mCurrentFrame.reset(numLayers);
2124 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
2125 mCurrentFrame.dropCount = 0;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002126 mCurrentFrame.hwCursorIndex = -1;
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302127
Raj Kamal9ed3d6b2014-02-07 16:15:17 +05302128 //Do not cache the information for next draw cycle.
2129 if(numLayers > MAX_NUM_APP_LAYERS or (!numLayers)) {
2130 ALOGI("%s: Unsupported layer count for mdp composition",
2131 __FUNCTION__);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002132 mCachedFrame.reset();
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302133#ifdef DYNAMIC_FPS
2134 setDynRefreshRate(ctx, list);
2135#endif
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002136 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002137 return -1;
2138 }
2139
Ramkumar Radhakrishnana70981a2013-08-28 11:33:53 -07002140 // Detect the start of animation and fall back to GPU only once to cache
2141 // all the layers in FB and display FB content untill animation completes.
2142 if(ctx->listStats[mDpy].isDisplayAnimating) {
2143 mCurrentFrame.needsRedraw = false;
2144 if(ctx->mAnimationState[mDpy] == ANIMATION_STOPPED) {
2145 mCurrentFrame.needsRedraw = true;
2146 ctx->mAnimationState[mDpy] = ANIMATION_STARTED;
2147 }
2148 setMDPCompLayerFlags(ctx, list);
2149 mCachedFrame.updateCounts(mCurrentFrame);
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302150#ifdef DYNAMIC_FPS
2151 setDynRefreshRate(ctx, list);
2152#endif
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002153 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Ramkumar Radhakrishnana70981a2013-08-28 11:33:53 -07002154 ret = -1;
2155 return ret;
2156 } else {
2157 ctx->mAnimationState[mDpy] = ANIMATION_STOPPED;
2158 }
2159
Raj Kamalfdfdddf2015-03-16 21:59:25 +05302160 if(!mDpy and !isSecondaryConnected(ctx) and !mPrevModeOn and
2161 mCachedFrame.isSameFrame(ctx,mDpy,list)) {
2162
2163 ALOGD_IF(isDebug(),"%s: Avoid new composition",__FUNCTION__);
2164 mCurrentFrame.needsRedraw = false;
2165 setMDPCompLayerFlags(ctx, list);
2166 mCachedFrame.updateCounts(mCurrentFrame);
2167#ifdef DYNAMIC_FPS
2168 setDynRefreshRate(ctx, list);
2169#endif
2170 return -1;
2171
2172 }
2173
Saurabh Shahb39f8152013-08-22 10:21:44 -07002174 //Hard conditions, if not met, cannot do MDP comp
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002175 if(isFrameDoable(ctx)) {
2176 generateROI(ctx, list);
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07002177 // if AIV Video mode is enabled, drop all non AIV layers from the
2178 // external display list.
2179 if(ctx->listStats[mDpy].mAIVVideoMode) {
2180 dropNonAIVLayers(ctx, list);
2181 }
Saurabh Shahb39f8152013-08-22 10:21:44 -07002182
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002183 // Configure the cursor if present
2184 int topIndex = ctx->listStats[mDpy].numAppLayers - 1;
2185 if(ctx->listStats[mDpy].cursorLayerPresent &&
2186 validForCursor(ctx, mDpy, &(list->hwLayers[topIndex]))) {
2187 if(configHwCursor(ctx->dpyAttr[mDpy].fd, mDpy,
2188 &(list->hwLayers[topIndex]))) {
2189 // As cursor is configured, mark that layer as dropped, so that
2190 // it wont be considered for composition by other strategies.
2191 mCurrentFrame.hwCursorIndex = topIndex;
2192 mCurrentFrame.drop[topIndex] = true;
2193 mCurrentFrame.dropCount++;
2194 }
2195 } else {
2196 // Release the hw cursor
2197 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
2198 }
2199
Ramkumar Radhakrishnan4ec775f2014-07-23 17:43:18 -07002200 // if tryFullFrame fails, try to push all video and secure RGB layers
2201 // to MDP for composition.
2202 mModeOn = tryFullFrame(ctx, list) || tryMDPOnlyLayers(ctx, list) ||
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07002203 tryVideoOnly(ctx, list);
Raj Kamal4393eaa2014-06-06 13:45:20 +05302204 if(mModeOn) {
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002205 setMDPCompLayerFlags(ctx, list);
2206 } else {
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08002207 resetROI(ctx, mDpy);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002208 reset(ctx);
2209 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
2210 mCurrentFrame.dropCount = 0;
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002211 // Check if cursor is in use for primary and mark accordingly
2212 if(!mDpy && HWCursor::getInstance()->isCursorSet()) {
2213 int topIndex = ctx->listStats[mDpy].numAppLayers - 1;
2214 hwc_layer_1_t *layer = &(list->hwLayers[topIndex]);
2215 layer->compositionType = HWC_CURSOR_OVERLAY;
2216 }
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002217 ret = -1;
Saurabh Shah286cf122014-09-08 14:13:08 -07002218 ALOGE_IF(sSimulationFlags && (mDpy == HWC_DISPLAY_PRIMARY),
2219 "MDP Composition Strategies Failed");
Saurabh Shahb39f8152013-08-22 10:21:44 -07002220 }
2221 } else {
Dileep Kumar Reddi4070e932014-09-30 09:00:57 +05302222 if ((ctx->mMDP.version == qdutils::MDP_V3_0_5) && ctx->mCopyBit[mDpy] &&
2223 enablePartialUpdateForMDP3) {
2224 generateROI(ctx, list);
2225 for(int i = 0; i < ctx->listStats[mDpy].numAppLayers; i++) {
2226 ctx->copybitDrop[i] = mCurrentFrame.drop[i];
2227 }
2228 }
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002229 ALOGD_IF( isDebug(),"%s: MDP Comp not possible for this frame",
2230 __FUNCTION__);
Arun Kumar K.R00b84792015-03-27 11:28:36 -07002231 // Release the hw cursor
2232 freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002233 ret = -1;
Saurabh Shahb39f8152013-08-22 10:21:44 -07002234 }
Saurabh Shahb39f8152013-08-22 10:21:44 -07002235
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002236 if(isDebug()) {
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002237 ALOGD("GEOMETRY change: %d",
2238 (list->flags & HWC_GEOMETRY_CHANGED));
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002239 android::String8 sDump("");
Jeykumar Sankaran6850ac62014-05-27 10:07:26 -07002240 dump(sDump, ctx);
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002241 ALOGD("%s",sDump.string());
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002242 }
2243
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07002244#ifdef DYNAMIC_FPS
Praveena Pachipulusu66c8ef72014-11-25 18:47:54 +05302245 setDynRefreshRate(ctx, list);
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07002246#endif
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08002247 setPerfHint(ctx, list);
Arun Kumar K.Ra727a882014-08-20 17:14:26 -07002248
Saurabh Shahdf4741d2013-12-12 16:40:28 -08002249 mCachedFrame.cacheAll(list);
2250 mCachedFrame.updateCounts(mCurrentFrame);
Saurabh Shah8c5c8522013-08-29 17:32:49 -07002251 return ret;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002252}
2253
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002254bool MDPComp::allocSplitVGPipes(hwc_context_t *ctx, int index) {
radhakrishnac9a67412013-09-25 17:40:42 +05302255
2256 bool bRet = true;
radhakrishnac9a67412013-09-25 17:40:42 +05302257 int mdpIndex = mCurrentFrame.layerToMDP[index];
2258 PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
2259 info.pipeInfo = new MdpYUVPipeInfo;
2260 info.rot = NULL;
2261 MdpYUVPipeInfo& pipe_info = *(MdpYUVPipeInfo*)info.pipeInfo;
radhakrishnac9a67412013-09-25 17:40:42 +05302262
2263 pipe_info.lIndex = ovutils::OV_INVALID;
2264 pipe_info.rIndex = ovutils::OV_INVALID;
2265
Saurabh Shahc62f3982014-03-05 14:28:26 -08002266 Overlay::PipeSpecs pipeSpecs;
2267 pipeSpecs.formatClass = Overlay::FORMAT_YUV;
2268 pipeSpecs.needsScaling = true;
2269 pipeSpecs.dpy = mDpy;
2270 pipeSpecs.fb = false;
2271
2272 pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
radhakrishnac9a67412013-09-25 17:40:42 +05302273 if(pipe_info.lIndex == ovutils::OV_INVALID){
2274 bRet = false;
2275 ALOGD_IF(isDebug(),"%s: allocating first VG pipe failed",
2276 __FUNCTION__);
2277 }
Saurabh Shahc62f3982014-03-05 14:28:26 -08002278 pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
radhakrishnac9a67412013-09-25 17:40:42 +05302279 if(pipe_info.rIndex == ovutils::OV_INVALID){
2280 bRet = false;
2281 ALOGD_IF(isDebug(),"%s: allocating second VG pipe failed",
2282 __FUNCTION__);
2283 }
2284 return bRet;
2285}
Sushil Chauhandefd3522014-05-13 18:17:12 -07002286
2287int MDPComp::drawOverlap(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
2288 int fd = -1;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002289 if (ctx->mPtorInfo.isActive()) {
2290 fd = ctx->mCopyBit[mDpy]->drawOverlap(ctx, list);
Sushil Chauhandefd3522014-05-13 18:17:12 -07002291 if (fd < 0) {
2292 ALOGD_IF(isDebug(),"%s: failed", __FUNCTION__);
Sushil Chauhandefd3522014-05-13 18:17:12 -07002293 }
2294 }
2295 return fd;
2296}
Arun Kumar K.R2aa44c62014-01-21 23:08:28 -08002297//=============MDPCompNonSplit==================================================
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002298
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002299void MDPCompNonSplit::adjustForSourceSplit(hwc_context_t *ctx,
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302300 hwc_display_contents_1_t* list) {
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002301 //If 4k2k Yuv layer split is possible, and if
2302 //fbz is above 4k2k layer, increment fb zorder by 1
2303 //as we split 4k2k layer and increment zorder for right half
2304 //of the layer
Shalaj Jaina70b4352014-06-15 13:47:47 -07002305 if(!ctx)
2306 return;
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002307 if(mCurrentFrame.fbZ >= 0) {
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302308 for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
2309 index++) {
2310 if(!mCurrentFrame.isFBComposed[index]) {
2311 if(mdpNextZOrder == mCurrentFrame.fbZ) {
2312 mdpNextZOrder++;
2313 }
2314 mdpNextZOrder++;
2315 hwc_layer_1_t* layer = &list->hwLayers[index];
2316 private_handle_t *hnd = (private_handle_t *)layer->handle;
Raj Kamal389d6e32014-08-04 14:43:24 +05302317 if(isYUVSplitNeeded(hnd)) {
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302318 if(mdpNextZOrder <= mCurrentFrame.fbZ)
2319 mCurrentFrame.fbZ += 1;
2320 mdpNextZOrder++;
2321 //As we split 4kx2k yuv layer and program to 2 VG pipes
2322 //(if available) increase mdpcount by 1.
2323 mCurrentFrame.mdpCount++;
2324 }
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002325 }
2326 }
2327 }
radhakrishnac9a67412013-09-25 17:40:42 +05302328}
2329
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002330/*
2331 * Configures pipe(s) for MDP composition
2332 */
Saurabh Shah88e4d272013-09-03 13:31:29 -07002333int MDPCompNonSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002334 PipeLayerPair& PipeLayerPair) {
Saurabh Shah88e4d272013-09-03 13:31:29 -07002335 MdpPipeInfoNonSplit& mdp_info =
2336 *(static_cast<MdpPipeInfoNonSplit*>(PipeLayerPair.pipeInfo));
Justin Philipd6166602014-08-12 13:42:21 +05302337 eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shahacf10202013-02-26 10:15:15 -08002338 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Saurabh Shahacf10202013-02-26 10:15:15 -08002339 eDest dest = mdp_info.index;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002340
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002341 ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipe: %d",
2342 __FUNCTION__, layer, zOrder, dest);
2343
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002344 return configureNonSplit(ctx, layer, mDpy, mdpFlags, zOrder, dest,
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002345 &PipeLayerPair.rot);
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002346}
2347
Saurabh Shah88e4d272013-09-03 13:31:29 -07002348bool MDPCompNonSplit::allocLayerPipes(hwc_context_t *ctx,
Saurabh Shahe51f8ca2013-05-06 17:26:16 -07002349 hwc_display_contents_1_t* list) {
2350 for(int index = 0; index < mCurrentFrame.layerCount; index++) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002351
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002352 if(mCurrentFrame.isFBComposed[index]) continue;
Saurabh Shahe51f8ca2013-05-06 17:26:16 -07002353
Jeykumar Sankarancf537002013-01-21 21:19:15 -08002354 hwc_layer_1_t* layer = &list->hwLayers[index];
2355 private_handle_t *hnd = (private_handle_t *)layer->handle;
Raj Kamal389d6e32014-08-04 14:43:24 +05302356 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002357 if(allocSplitVGPipes(ctx, index)){
radhakrishnac9a67412013-09-25 17:40:42 +05302358 continue;
2359 }
2360 }
2361
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002362 int mdpIndex = mCurrentFrame.layerToMDP[index];
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002363 PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
Saurabh Shah88e4d272013-09-03 13:31:29 -07002364 info.pipeInfo = new MdpPipeInfoNonSplit;
Saurabh Shahacf10202013-02-26 10:15:15 -08002365 info.rot = NULL;
Saurabh Shah88e4d272013-09-03 13:31:29 -07002366 MdpPipeInfoNonSplit& pipe_info = *(MdpPipeInfoNonSplit*)info.pipeInfo;
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -08002367
Saurabh Shahc62f3982014-03-05 14:28:26 -08002368 Overlay::PipeSpecs pipeSpecs;
2369 pipeSpecs.formatClass = isYuvBuffer(hnd) ?
2370 Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
2371 pipeSpecs.needsScaling = qhwc::needsScaling(layer) or
2372 (qdutils::MDPVersion::getInstance().is8x26() and
2373 ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres > 1024);
2374 pipeSpecs.dpy = mDpy;
2375 pipeSpecs.fb = false;
Xu Yang1e686f62014-04-08 13:56:47 +08002376 pipeSpecs.numActiveDisplays = ctx->numActiveDisplays;
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -08002377
Saurabh Shahc62f3982014-03-05 14:28:26 -08002378 pipe_info.index = ctx->mOverlay->getPipe(pipeSpecs);
2379
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002380 if(pipe_info.index == ovutils::OV_INVALID) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002381 ALOGD_IF(isDebug(), "%s: Unable to get pipe", __FUNCTION__);
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002382 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002383 }
2384 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002385 return true;
2386}
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002387
radhakrishnac9a67412013-09-25 17:40:42 +05302388int MDPCompNonSplit::configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
2389 PipeLayerPair& PipeLayerPair) {
2390 MdpYUVPipeInfo& mdp_info =
2391 *(static_cast<MdpYUVPipeInfo*>(PipeLayerPair.pipeInfo));
2392 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Justin Philipd6166602014-08-12 13:42:21 +05302393 eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
radhakrishnac9a67412013-09-25 17:40:42 +05302394 eDest lDest = mdp_info.lIndex;
2395 eDest rDest = mdp_info.rIndex;
2396
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002397 return configureSourceSplit(ctx, layer, mDpy, mdpFlagsL, zOrder,
radhakrishnac9a67412013-09-25 17:40:42 +05302398 lDest, rDest, &PipeLayerPair.rot);
2399}
2400
Saurabh Shah88e4d272013-09-03 13:31:29 -07002401bool MDPCompNonSplit::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002402
Raj Kamal4393eaa2014-06-06 13:45:20 +05302403 if(!isEnabled() or !mModeOn) {
2404 ALOGD_IF(isDebug(),"%s: MDP Comp not enabled/configured", __FUNCTION__);
Prabhanjan Kandula08222fc2013-07-10 17:20:59 +05302405 return true;
2406 }
2407
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002408 overlay::Overlay& ov = *ctx->mOverlay;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002409 LayerProp *layerProp = ctx->layerProp[mDpy];
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002410
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002411 int numHwLayers = ctx->listStats[mDpy].numAppLayers;
2412 for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ )
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002413 {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002414 if(mCurrentFrame.isFBComposed[i]) continue;
2415
Naseer Ahmed5b6708a2012-08-02 13:46:08 -07002416 hwc_layer_1_t *layer = &list->hwLayers[i];
Saurabh Shahacf10202013-02-26 10:15:15 -08002417 private_handle_t *hnd = (private_handle_t *)layer->handle;
2418 if(!hnd) {
Sushil Chauhan897a9c32013-07-18 11:09:55 -07002419 if (!(layer->flags & HWC_COLOR_FILL)) {
2420 ALOGE("%s handle null", __FUNCTION__);
2421 return false;
2422 }
2423 // No PLAY for Color layer
2424 layerProp[i].mFlags &= ~HWC_MDPCOMP;
2425 continue;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002426 }
2427
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002428 int mdpIndex = mCurrentFrame.layerToMDP[i];
2429
Raj Kamal389d6e32014-08-04 14:43:24 +05302430 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit)
radhakrishnac9a67412013-09-25 17:40:42 +05302431 {
2432 MdpYUVPipeInfo& pipe_info =
2433 *(MdpYUVPipeInfo*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
2434 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
2435 ovutils::eDest indexL = pipe_info.lIndex;
2436 ovutils::eDest indexR = pipe_info.rIndex;
2437 int fd = hnd->fd;
Praveena Pachipulusud9443c72014-02-17 10:42:28 +05302438 uint32_t offset = (uint32_t)hnd->offset;
radhakrishnac9a67412013-09-25 17:40:42 +05302439 if(rot) {
2440 rot->queueBuffer(fd, offset);
2441 fd = rot->getDstMemId();
2442 offset = rot->getDstOffset();
2443 }
2444 if(indexL != ovutils::OV_INVALID) {
2445 ovutils::eDest destL = (ovutils::eDest)indexL;
2446 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2447 using pipe: %d", __FUNCTION__, layer, hnd, indexL );
2448 if (!ov.queueBuffer(fd, offset, destL)) {
2449 ALOGE("%s: queueBuffer failed for display:%d",
2450 __FUNCTION__, mDpy);
2451 return false;
2452 }
2453 }
2454
2455 if(indexR != ovutils::OV_INVALID) {
2456 ovutils::eDest destR = (ovutils::eDest)indexR;
2457 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2458 using pipe: %d", __FUNCTION__, layer, hnd, indexR );
2459 if (!ov.queueBuffer(fd, offset, destR)) {
2460 ALOGE("%s: queueBuffer failed for display:%d",
2461 __FUNCTION__, mDpy);
2462 return false;
2463 }
2464 }
2465 }
2466 else{
2467 MdpPipeInfoNonSplit& pipe_info =
Saurabh Shah88e4d272013-09-03 13:31:29 -07002468 *(MdpPipeInfoNonSplit*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
radhakrishnac9a67412013-09-25 17:40:42 +05302469 ovutils::eDest dest = pipe_info.index;
2470 if(dest == ovutils::OV_INVALID) {
2471 ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, dest);
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002472 return false;
radhakrishnac9a67412013-09-25 17:40:42 +05302473 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002474
radhakrishnac9a67412013-09-25 17:40:42 +05302475 if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
2476 continue;
2477 }
2478
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002479 int fd = hnd->fd;
2480 uint32_t offset = (uint32_t)hnd->offset;
2481 int index = ctx->mPtorInfo.getPTORArrayIndex(i);
2482 if (!mDpy && (index != -1)) {
Sushil Chauhandefd3522014-05-13 18:17:12 -07002483 hnd = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002484 fd = hnd->fd;
Sushil Chauhan875a92e2014-07-25 12:20:23 -07002485 offset = 0;
Sushil Chauhandefd3522014-05-13 18:17:12 -07002486 }
2487
radhakrishnac9a67412013-09-25 17:40:42 +05302488 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2489 using pipe: %d", __FUNCTION__, layer,
2490 hnd, dest );
2491
radhakrishnac9a67412013-09-25 17:40:42 +05302492 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
2493 if(rot) {
2494 if(!rot->queueBuffer(fd, offset))
2495 return false;
2496 fd = rot->getDstMemId();
2497 offset = rot->getDstOffset();
2498 }
2499
2500 if (!ov.queueBuffer(fd, offset, dest)) {
2501 ALOGE("%s: queueBuffer failed for display:%d ",
2502 __FUNCTION__, mDpy);
2503 return false;
2504 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002505 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002506
2507 layerProp[i].mFlags &= ~HWC_MDPCOMP;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002508 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002509 return true;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002510}
2511
Saurabh Shah88e4d272013-09-03 13:31:29 -07002512//=============MDPCompSplit===================================================
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002513
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002514void MDPCompSplit::adjustForSourceSplit(hwc_context_t *ctx,
radhakrishnac9a67412013-09-25 17:40:42 +05302515 hwc_display_contents_1_t* list){
2516 //if 4kx2k yuv layer is totally present in either in left half
2517 //or right half then try splitting the yuv layer to avoid decimation
radhakrishnac9a67412013-09-25 17:40:42 +05302518 const int lSplit = getLeftSplit(ctx, mDpy);
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302519 if(mCurrentFrame.fbZ >= 0) {
2520 for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
2521 index++) {
2522 if(!mCurrentFrame.isFBComposed[index]) {
2523 if(mdpNextZOrder == mCurrentFrame.fbZ) {
2524 mdpNextZOrder++;
2525 }
2526 mdpNextZOrder++;
2527 hwc_layer_1_t* layer = &list->hwLayers[index];
2528 private_handle_t *hnd = (private_handle_t *)layer->handle;
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002529 if(isYUVSplitNeeded(hnd) ||
2530 (needs3DComposition(ctx,mDpy) &&
2531 get3DFormat(hnd) != HAL_NO_3D)) {
Dileep Kumar Reddi190dc1c2014-05-22 22:24:53 +05302532 hwc_rect_t dst = layer->displayFrame;
2533 if((dst.left > lSplit) || (dst.right < lSplit)) {
2534 mCurrentFrame.mdpCount += 1;
2535 }
2536 if(mdpNextZOrder <= mCurrentFrame.fbZ)
2537 mCurrentFrame.fbZ += 1;
2538 mdpNextZOrder++;
2539 }
2540 }
Saurabh Shah3d4b8042013-12-10 15:19:17 -08002541 }
radhakrishnac9a67412013-09-25 17:40:42 +05302542 }
2543}
2544
Saurabh Shah88e4d272013-09-03 13:31:29 -07002545bool MDPCompSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
Saurabh Shahc62f3982014-03-05 14:28:26 -08002546 MdpPipeInfoSplit& pipe_info) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002547
Saurabh Shahc62f3982014-03-05 14:28:26 -08002548 const int lSplit = getLeftSplit(ctx, mDpy);
2549 private_handle_t *hnd = (private_handle_t *)layer->handle;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002550 hwc_rect_t dst = layer->displayFrame;
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002551 pipe_info.lIndex = ovutils::OV_INVALID;
2552 pipe_info.rIndex = ovutils::OV_INVALID;
2553
Saurabh Shahc62f3982014-03-05 14:28:26 -08002554 Overlay::PipeSpecs pipeSpecs;
2555 pipeSpecs.formatClass = isYuvBuffer(hnd) ?
2556 Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
2557 pipeSpecs.needsScaling = qhwc::needsScalingWithSplit(ctx, layer, mDpy);
2558 pipeSpecs.dpy = mDpy;
2559 pipeSpecs.mixer = Overlay::MIXER_LEFT;
2560 pipeSpecs.fb = false;
2561
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08002562 // Acquire pipe only for the updating half
2563 hwc_rect_t l_roi = ctx->listStats[mDpy].lRoi;
2564 hwc_rect_t r_roi = ctx->listStats[mDpy].rRoi;
2565
2566 if (dst.left < lSplit && isValidRect(getIntersection(dst, l_roi))) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002567 pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002568 if(pipe_info.lIndex == ovutils::OV_INVALID)
2569 return false;
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002570 }
2571
Jeykumar Sankaran6c7eeac2013-11-18 11:19:45 -08002572 if(dst.right > lSplit && isValidRect(getIntersection(dst, r_roi))) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002573 pipeSpecs.mixer = Overlay::MIXER_RIGHT;
2574 pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002575 if(pipe_info.rIndex == ovutils::OV_INVALID)
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002576 return false;
2577 }
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002578
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002579 return true;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002580}
2581
Saurabh Shah88e4d272013-09-03 13:31:29 -07002582bool MDPCompSplit::allocLayerPipes(hwc_context_t *ctx,
Saurabh Shahe51f8ca2013-05-06 17:26:16 -07002583 hwc_display_contents_1_t* list) {
2584 for(int index = 0 ; index < mCurrentFrame.layerCount; index++) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002585
Saurabh Shahe51f8ca2013-05-06 17:26:16 -07002586 if(mCurrentFrame.isFBComposed[index]) continue;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002587
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002588 hwc_layer_1_t* layer = &list->hwLayers[index];
2589 private_handle_t *hnd = (private_handle_t *)layer->handle;
radhakrishnac9a67412013-09-25 17:40:42 +05302590 hwc_rect_t dst = layer->displayFrame;
2591 const int lSplit = getLeftSplit(ctx, mDpy);
Raj Kamal389d6e32014-08-04 14:43:24 +05302592 if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
radhakrishnac9a67412013-09-25 17:40:42 +05302593 if((dst.left > lSplit)||(dst.right < lSplit)){
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002594 if(allocSplitVGPipes(ctx, index)){
radhakrishnac9a67412013-09-25 17:40:42 +05302595 continue;
2596 }
2597 }
2598 }
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002599 //XXX: Check for forced 2D composition
2600 if(needs3DComposition(ctx, mDpy) && get3DFormat(hnd) != HAL_NO_3D)
2601 if(allocSplitVGPipes(ctx,index))
2602 continue;
2603
Saurabh Shah0d65dbe2013-06-06 18:33:16 -07002604 int mdpIndex = mCurrentFrame.layerToMDP[index];
2605 PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
Saurabh Shah88e4d272013-09-03 13:31:29 -07002606 info.pipeInfo = new MdpPipeInfoSplit;
Saurabh Shah9e3adb22013-03-26 11:16:27 -07002607 info.rot = NULL;
Saurabh Shah88e4d272013-09-03 13:31:29 -07002608 MdpPipeInfoSplit& pipe_info = *(MdpPipeInfoSplit*)info.pipeInfo;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002609
Saurabh Shahc62f3982014-03-05 14:28:26 -08002610 if(!acquireMDPPipes(ctx, layer, pipe_info)) {
2611 ALOGD_IF(isDebug(), "%s: Unable to get pipe for type",
2612 __FUNCTION__);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002613 return false;
2614 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002615 }
2616 return true;
2617}
Saurabh Shahaf5f5972013-07-30 13:56:35 -07002618
radhakrishnac9a67412013-09-25 17:40:42 +05302619int MDPCompSplit::configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
2620 PipeLayerPair& PipeLayerPair) {
2621 const int lSplit = getLeftSplit(ctx, mDpy);
2622 hwc_rect_t dst = layer->displayFrame;
2623 if((dst.left > lSplit)||(dst.right < lSplit)){
2624 MdpYUVPipeInfo& mdp_info =
2625 *(static_cast<MdpYUVPipeInfo*>(PipeLayerPair.pipeInfo));
2626 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Justin Philipd6166602014-08-12 13:42:21 +05302627 eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
radhakrishnac9a67412013-09-25 17:40:42 +05302628 eDest lDest = mdp_info.lIndex;
2629 eDest rDest = mdp_info.rIndex;
2630
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002631 return configureSourceSplit(ctx, layer, mDpy, mdpFlagsL, zOrder,
radhakrishnac9a67412013-09-25 17:40:42 +05302632 lDest, rDest, &PipeLayerPair.rot);
2633 }
2634 else{
2635 return configure(ctx, layer, PipeLayerPair);
2636 }
2637}
2638
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002639/*
2640 * Configures pipe(s) for MDP composition
2641 */
Saurabh Shah88e4d272013-09-03 13:31:29 -07002642int MDPCompSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
Saurabh Shah67a38c32013-06-10 16:23:15 -07002643 PipeLayerPair& PipeLayerPair) {
Saurabh Shah88e4d272013-09-03 13:31:29 -07002644 MdpPipeInfoSplit& mdp_info =
2645 *(static_cast<MdpPipeInfoSplit*>(PipeLayerPair.pipeInfo));
Saurabh Shahacf10202013-02-26 10:15:15 -08002646 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
Justin Philipd6166602014-08-12 13:42:21 +05302647 eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shahacf10202013-02-26 10:15:15 -08002648 eDest lDest = mdp_info.lIndex;
2649 eDest rDest = mdp_info.rIndex;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002650
2651 ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
Jeykumar Sankaran39305802014-12-12 17:55:57 -08002652 "dest_pipeR: %d",__FUNCTION__, layer, zOrder, lDest, rDest);
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002653
Saurabh Shah2c8ad052014-08-15 13:27:46 -07002654 return configureSplit(ctx, layer, mDpy, mdpFlagsL, zOrder, lDest,
Jeykumar Sankaran39305802014-12-12 17:55:57 -08002655 rDest, &PipeLayerPair.rot);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002656}
2657
Saurabh Shah88e4d272013-09-03 13:31:29 -07002658bool MDPCompSplit::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002659
Raj Kamal4393eaa2014-06-06 13:45:20 +05302660 if(!isEnabled() or !mModeOn) {
2661 ALOGD_IF(isDebug(),"%s: MDP Comp not enabled/configured", __FUNCTION__);
Prabhanjan Kandula08222fc2013-07-10 17:20:59 +05302662 return true;
2663 }
2664
Naseer Ahmed54821fe2012-11-28 18:44:38 -05002665 overlay::Overlay& ov = *ctx->mOverlay;
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002666 LayerProp *layerProp = ctx->layerProp[mDpy];
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002667
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002668 int numHwLayers = ctx->listStats[mDpy].numAppLayers;
2669 for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ )
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002670 {
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002671 if(mCurrentFrame.isFBComposed[i]) continue;
2672
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002673 hwc_layer_1_t *layer = &list->hwLayers[i];
Saurabh Shahacf10202013-02-26 10:15:15 -08002674 private_handle_t *hnd = (private_handle_t *)layer->handle;
2675 if(!hnd) {
2676 ALOGE("%s handle null", __FUNCTION__);
2677 return false;
2678 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002679
2680 if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
2681 continue;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002682 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002683
Jeykumar Sankaran85977e32013-02-25 17:06:08 -08002684 int mdpIndex = mCurrentFrame.layerToMDP[i];
2685
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002686 if((isYUVSplitNeeded(hnd) && sEnableYUVsplit) ||
2687 (needs3DComposition(ctx, mDpy) && get3DFormat(hnd) != HAL_NO_3D))
radhakrishnac9a67412013-09-25 17:40:42 +05302688 {
2689 MdpYUVPipeInfo& pipe_info =
2690 *(MdpYUVPipeInfo*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
2691 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
2692 ovutils::eDest indexL = pipe_info.lIndex;
2693 ovutils::eDest indexR = pipe_info.rIndex;
2694 int fd = hnd->fd;
Praveena Pachipulusud9443c72014-02-17 10:42:28 +05302695 uint32_t offset = (uint32_t)hnd->offset;
radhakrishnac9a67412013-09-25 17:40:42 +05302696 if(rot) {
2697 rot->queueBuffer(fd, offset);
2698 fd = rot->getDstMemId();
2699 offset = rot->getDstOffset();
2700 }
2701 if(indexL != ovutils::OV_INVALID) {
2702 ovutils::eDest destL = (ovutils::eDest)indexL;
2703 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2704 using pipe: %d", __FUNCTION__, layer, hnd, indexL );
2705 if (!ov.queueBuffer(fd, offset, destL)) {
2706 ALOGE("%s: queueBuffer failed for display:%d",
2707 __FUNCTION__, mDpy);
2708 return false;
2709 }
2710 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002711
radhakrishnac9a67412013-09-25 17:40:42 +05302712 if(indexR != ovutils::OV_INVALID) {
2713 ovutils::eDest destR = (ovutils::eDest)indexR;
2714 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2715 using pipe: %d", __FUNCTION__, layer, hnd, indexR );
2716 if (!ov.queueBuffer(fd, offset, destR)) {
2717 ALOGE("%s: queueBuffer failed for display:%d",
2718 __FUNCTION__, mDpy);
2719 return false;
2720 }
Saurabh Shaha9da08f2013-07-03 13:27:53 -07002721 }
2722 }
radhakrishnac9a67412013-09-25 17:40:42 +05302723 else{
2724 MdpPipeInfoSplit& pipe_info =
2725 *(MdpPipeInfoSplit*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
2726 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
Saurabh Shaha9da08f2013-07-03 13:27:53 -07002727
radhakrishnac9a67412013-09-25 17:40:42 +05302728 ovutils::eDest indexL = pipe_info.lIndex;
2729 ovutils::eDest indexR = pipe_info.rIndex;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002730
radhakrishnac9a67412013-09-25 17:40:42 +05302731 int fd = hnd->fd;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002732 uint32_t offset = (uint32_t)hnd->offset;
2733 int index = ctx->mPtorInfo.getPTORArrayIndex(i);
2734 if (!mDpy && (index != -1)) {
2735 hnd = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
2736 fd = hnd->fd;
Sushil Chauhan875a92e2014-07-25 12:20:23 -07002737 offset = 0;
Arun Kumar K.Rb2a03b12014-06-03 11:54:10 -07002738 }
radhakrishnac9a67412013-09-25 17:40:42 +05302739
Tatenda Chipeperekwa88fe6352014-04-14 10:36:06 -07002740 if(ctx->mAD->draw(ctx, fd, offset)) {
2741 fd = ctx->mAD->getDstFd();
2742 offset = ctx->mAD->getDstOffset();
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002743 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002744
radhakrishnac9a67412013-09-25 17:40:42 +05302745 if(rot) {
2746 rot->queueBuffer(fd, offset);
2747 fd = rot->getDstMemId();
2748 offset = rot->getDstOffset();
2749 }
2750
2751 //************* play left mixer **********
2752 if(indexL != ovutils::OV_INVALID) {
2753 ovutils::eDest destL = (ovutils::eDest)indexL;
2754 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2755 using pipe: %d", __FUNCTION__, layer, hnd, indexL );
2756 if (!ov.queueBuffer(fd, offset, destL)) {
2757 ALOGE("%s: queueBuffer failed for left mixer",
2758 __FUNCTION__);
2759 return false;
2760 }
2761 }
2762
2763 //************* play right mixer **********
2764 if(indexR != ovutils::OV_INVALID) {
2765 ovutils::eDest destR = (ovutils::eDest)indexR;
2766 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
2767 using pipe: %d", __FUNCTION__, layer, hnd, indexR );
2768 if (!ov.queueBuffer(fd, offset, destR)) {
2769 ALOGE("%s: queueBuffer failed for right mixer",
2770 __FUNCTION__);
2771 return false;
2772 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002773 }
2774 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002775
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002776 layerProp[i].mFlags &= ~HWC_MDPCOMP;
2777 }
Saurabh Shahacf10202013-02-26 10:15:15 -08002778
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002779 return true;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07002780}
Saurabh Shahab47c692014-02-12 18:45:57 -08002781
2782//================MDPCompSrcSplit==============================================
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08002783
2784bool MDPCompSrcSplit::validateAndApplyROI(hwc_context_t *ctx,
2785 hwc_display_contents_1_t* list) {
2786 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
2787 hwc_rect_t visibleRect = ctx->listStats[mDpy].lRoi;
2788
2789 for(int i = numAppLayers - 1; i >= 0; i--) {
2790 if(!isValidRect(visibleRect)) {
2791 mCurrentFrame.drop[i] = true;
2792 mCurrentFrame.dropCount++;
2793 continue;
2794 }
2795
2796 const hwc_layer_1_t* layer = &list->hwLayers[i];
2797 hwc_rect_t dstRect = layer->displayFrame;
2798 hwc_rect_t res = getIntersection(visibleRect, dstRect);
2799
2800 if(!isValidRect(res)) {
2801 mCurrentFrame.drop[i] = true;
2802 mCurrentFrame.dropCount++;
2803 } else {
2804 /* Reset frame ROI when any layer which needs scaling also needs ROI
2805 * cropping */
2806 if(!isSameRect(res, dstRect) && needsScaling (layer)) {
2807 ALOGI("%s: Resetting ROI due to scaling", __FUNCTION__);
2808 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
2809 mCurrentFrame.dropCount = 0;
2810 return false;
2811 }
2812
2813 /* deduct any opaque region from visibleRect */
2814 if (layer->blending == HWC_BLENDING_NONE &&
2815 layer->planeAlpha == 0xFF)
2816 visibleRect = deductRect(visibleRect, res);
2817 }
2818 }
2819 return true;
2820}
2821
2822/*
2823 * HW Limitation: ping pong split can always split the ping pong output
2824 * equally across two DSI's. So the ROI programmed should be of equal width
2825 * for both the halves
2826 */
2827void MDPCompSrcSplit::generateROI(hwc_context_t *ctx,
2828 hwc_display_contents_1_t* list) {
2829 int numAppLayers = ctx->listStats[mDpy].numAppLayers;
2830
2831
2832 if(!canPartialUpdate(ctx, list))
2833 return;
2834
2835 struct hwc_rect roi = (struct hwc_rect){0, 0, 0, 0};
2836 hwc_rect fullFrame = (struct hwc_rect) {0, 0,(int)ctx->dpyAttr[mDpy].xres,
2837 (int)ctx->dpyAttr[mDpy].yres};
2838
2839 for(int index = 0; index < numAppLayers; index++ ) {
2840 hwc_layer_1_t* layer = &list->hwLayers[index];
2841
2842 // If we have a RGB layer which needs rotation, no partial update
2843 if(!isYuvBuffer((private_handle_t *)layer->handle) && layer->transform)
2844 return;
2845
2846 if ((mCachedFrame.hnd[index] != layer->handle) ||
2847 isYuvBuffer((private_handle_t *)layer->handle)) {
2848 hwc_rect_t dst = layer->displayFrame;
2849 hwc_rect_t updatingRect = dst;
2850
2851#ifdef QCOM_BSP
2852 if(!needsScaling(layer) && !layer->transform)
2853 {
2854 hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
2855 int x_off = dst.left - src.left;
2856 int y_off = dst.top - src.top;
2857 updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
2858 }
2859#endif
2860
2861 roi = getUnion(roi, updatingRect);
2862 }
2863 }
2864
2865 /* No layer is updating. Still SF wants a refresh.*/
2866 if(!isValidRect(roi))
2867 return;
2868
2869 roi = expandROIFromMidPoint(roi, fullFrame);
2870
2871 hwc_rect lFrame = fullFrame;
2872 lFrame.right /= 2;
2873 hwc_rect lRoi = getIntersection(roi, lFrame);
2874
2875 // Align ROI coordinates to panel restrictions
2876 lRoi = getSanitizeROI(lRoi, lFrame);
2877
2878 hwc_rect rFrame = fullFrame;
2879 rFrame.left = lFrame.right;
2880 hwc_rect rRoi = getIntersection(roi, rFrame);
2881
2882 // Align ROI coordinates to panel restrictions
2883 rRoi = getSanitizeROI(rRoi, rFrame);
2884
2885 roi = getUnion(lRoi, rRoi);
2886
2887 ctx->listStats[mDpy].lRoi = roi;
2888 if(!validateAndApplyROI(ctx, list))
2889 resetROI(ctx, mDpy);
2890
2891 ALOGD_IF(isDebug(),"%s: generated ROI: [%d, %d, %d, %d] [%d, %d, %d, %d]",
2892 __FUNCTION__,
2893 ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
2894 ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom,
2895 ctx->listStats[mDpy].rRoi.left, ctx->listStats[mDpy].rRoi.top,
2896 ctx->listStats[mDpy].rRoi.right, ctx->listStats[mDpy].rRoi.bottom);
2897}
2898
Saurabh Shahab47c692014-02-12 18:45:57 -08002899bool MDPCompSrcSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
Saurabh Shahc62f3982014-03-05 14:28:26 -08002900 MdpPipeInfoSplit& pipe_info) {
Saurabh Shahab47c692014-02-12 18:45:57 -08002901 private_handle_t *hnd = (private_handle_t *)layer->handle;
2902 hwc_rect_t dst = layer->displayFrame;
2903 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
2904 pipe_info.lIndex = ovutils::OV_INVALID;
2905 pipe_info.rIndex = ovutils::OV_INVALID;
2906
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08002907 if(qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() && !mDpy)
2908 trimAgainstROI(ctx,crop, dst);
2909
Saurabh Shahab47c692014-02-12 18:45:57 -08002910 //If 2 pipes are staged on a single stage of a mixer, then the left pipe
2911 //should have a higher priority than the right one. Pipe priorities are
2912 //starting with VG0, VG1 ... , RGB0 ..., DMA1
Saurabh Shahab47c692014-02-12 18:45:57 -08002913
Saurabh Shahc62f3982014-03-05 14:28:26 -08002914 Overlay::PipeSpecs pipeSpecs;
2915 pipeSpecs.formatClass = isYuvBuffer(hnd) ?
2916 Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
2917 pipeSpecs.needsScaling = qhwc::needsScaling(layer);
2918 pipeSpecs.dpy = mDpy;
2919 pipeSpecs.fb = false;
2920
Saurabh Shahab47c692014-02-12 18:45:57 -08002921 //1 pipe by default for a layer
Saurabh Shahc62f3982014-03-05 14:28:26 -08002922 pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahab47c692014-02-12 18:45:57 -08002923 if(pipe_info.lIndex == ovutils::OV_INVALID) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002924 return false;
Saurabh Shahab47c692014-02-12 18:45:57 -08002925 }
2926
Saurabh Shahea7a01d2014-05-22 17:45:36 -07002927 /* Use 2 pipes IF
2928 a) Layer's crop width is > 2048 or
2929 b) Layer's dest width > 2048 or
2930 c) On primary, driver has indicated with caps to split always. This is
2931 based on an empirically derived value of panel height. Applied only
2932 if the layer's width is > mixer's width
2933 */
2934
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +05302935 MDPVersion& mdpHw = MDPVersion::getInstance();
Saurabh Shahea7a01d2014-05-22 17:45:36 -07002936 bool primarySplitAlways = (mDpy == HWC_DISPLAY_PRIMARY) and
Prabhanjan Kandula5bae9f52014-05-15 16:48:18 +05302937 mdpHw.isSrcSplitAlways();
Saurabh Shah514759d2014-11-11 18:02:24 -08002938 const uint32_t lSplit = getLeftSplit(ctx, mDpy);
2939 const uint32_t dstWidth = dst.right - dst.left;
2940 const uint32_t dstHeight = dst.bottom - dst.top;
Saurabh Shah05f4e222015-02-05 14:36:22 -08002941 uint32_t cropWidth = has90Transform(layer) ? crop.bottom - crop.top :
Saurabh Shah189f23d2014-09-26 17:21:00 -07002942 crop.right - crop.left;
Saurabh Shah05f4e222015-02-05 14:36:22 -08002943 uint32_t cropHeight = has90Transform(layer) ? crop.right - crop.left :
Saurabh Shah514759d2014-11-11 18:02:24 -08002944 crop.bottom - crop.top;
2945 //Approximation to actual clock, ignoring the common factors in pipe and
2946 //mixer cases like line_time
2947 const uint32_t layerClock = getLayerClock(dstWidth, dstHeight, cropHeight);
2948 const uint32_t mixerClock = lSplit;
Saurabh Shahea7a01d2014-05-22 17:45:36 -07002949
Saurabh Shah05f4e222015-02-05 14:36:22 -08002950 const uint32_t downscale = getRotDownscale(ctx, layer);
2951 if(downscale) {
2952 cropWidth /= downscale;
2953 cropHeight /= downscale;
2954 }
2955
Jeykumar Sankaran39305802014-12-12 17:55:57 -08002956 if(dstWidth > mdpHw.getMaxPipeWidth() or
2957 cropWidth > mdpHw.getMaxPipeWidth() or
Saurabh Shah514759d2014-11-11 18:02:24 -08002958 (primarySplitAlways and
2959 (cropWidth > lSplit or layerClock > mixerClock))) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002960 pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
Saurabh Shahab47c692014-02-12 18:45:57 -08002961 if(pipe_info.rIndex == ovutils::OV_INVALID) {
Saurabh Shahc62f3982014-03-05 14:28:26 -08002962 return false;
Saurabh Shahdd8237a2014-02-28 14:29:09 -08002963 }
2964
Jeykumar Sankaran89e23ab2015-01-28 15:57:46 -08002965 if(ctx->mOverlay->needsPrioritySwap(pipe_info.lIndex,
2966 pipe_info.rIndex)) {
Saurabh Shahdd8237a2014-02-28 14:29:09 -08002967 qhwc::swap(pipe_info.lIndex, pipe_info.rIndex);
Saurabh Shahab47c692014-02-12 18:45:57 -08002968 }
2969 }
2970
2971 return true;
2972}
2973
Saurabh Shahab47c692014-02-12 18:45:57 -08002974int MDPCompSrcSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
2975 PipeLayerPair& PipeLayerPair) {
2976 private_handle_t *hnd = (private_handle_t *)layer->handle;
2977 if(!hnd) {
2978 ALOGE("%s: layer handle is NULL", __FUNCTION__);
2979 return -1;
2980 }
2981 MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
2982 MdpPipeInfoSplit& mdp_info =
2983 *(static_cast<MdpPipeInfoSplit*>(PipeLayerPair.pipeInfo));
2984 Rotator **rot = &PipeLayerPair.rot;
2985 eZorder z = static_cast<eZorder>(mdp_info.zOrder);
Saurabh Shahab47c692014-02-12 18:45:57 -08002986 eDest lDest = mdp_info.lIndex;
2987 eDest rDest = mdp_info.rIndex;
2988 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
2989 hwc_rect_t dst = layer->displayFrame;
2990 int transform = layer->transform;
2991 eTransform orient = static_cast<eTransform>(transform);
Saurabh Shahab47c692014-02-12 18:45:57 -08002992 int rotFlags = ROT_FLAGS_NONE;
Sushil Chauhan65e26302015-01-14 10:48:57 -08002993 uint32_t format = ovutils::getMdpFormat(hnd->format, hnd->flags);
Saurabh Shahab47c692014-02-12 18:45:57 -08002994 Whf whf(getWidth(hnd), getHeight(hnd), format, hnd->size);
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05002995 eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shahab47c692014-02-12 18:45:57 -08002996
2997 ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
2998 "dest_pipeR: %d",__FUNCTION__, layer, z, lDest, rDest);
2999
Jeykumar Sankaranaedd1432015-01-15 11:25:03 -08003000 if(qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() && !mDpy) {
3001 /* MDP driver crops layer coordinates against ROI in Non-Split
3002 * and Split MDP comp. But HWC needs to crop them for source split.
3003 * Reason: 1) Source split is efficient only when the final effective
3004 * load is distributed evenly across mixers.
3005 * 2) We have to know the effective width of the layer that
3006 * the ROI needs to find the no. of pipes the layer needs.
3007 */
3008 trimAgainstROI(ctx, crop, dst);
3009 }
3010
Naseer Ahmed6bbd0a12015-01-23 11:57:10 -05003011 if(needs3DComposition(ctx, mDpy) &&
3012 get3DFormat(hnd) != HAL_NO_3D){
3013 return configure3DVideo(ctx, layer, mDpy, mdpFlags, z, lDest,
3014 rDest, &PipeLayerPair.rot);
3015 }
3016
Saurabh Shahab47c692014-02-12 18:45:57 -08003017 // Handle R/B swap
3018 if (layer->flags & HWC_FORMAT_RB_SWAP) {
3019 if (hnd->format == HAL_PIXEL_FORMAT_RGBA_8888)
3020 whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRA_8888);
3021 else if (hnd->format == HAL_PIXEL_FORMAT_RGBX_8888)
3022 whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
3023 }
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07003024 // update source crop and destination position of AIV video layer.
Ramkumar Radhakrishnanb33f4902014-10-03 16:46:35 -07003025 if(ctx->listStats[mDpy].mAIVVideoMode && isYuvBuffer(hnd)) {
3026 updateCoordinates(ctx, crop, dst, mDpy);
Ramkumar Radhakrishnan9d7bc312014-08-13 19:38:13 -07003027 }
Ramkumar Radhakrishnana5c72872014-08-28 19:04:18 -07003028 /* Calculate the external display position based on MDP downscale,
3029 ActionSafe, and extorientation features. */
3030 calcExtDisplayPosition(ctx, hnd, mDpy, crop, dst, transform, orient);
Saurabh Shahab47c692014-02-12 18:45:57 -08003031
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003032 int downscale = getRotDownscale(ctx, layer);
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003033 setMdpFlags(ctx, layer, mdpFlags, downscale, transform);
Saurabh Shahab47c692014-02-12 18:45:57 -08003034
3035 if(lDest != OV_INVALID && rDest != OV_INVALID) {
3036 //Enable overfetch
Saurabh Shah97e2d802014-04-14 18:03:54 -07003037 setMdpFlags(mdpFlags, OV_MDSS_MDP_DUAL_PIPE);
Saurabh Shahab47c692014-02-12 18:45:57 -08003038 }
3039
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003040 if((has90Transform(layer) or downscale) and isRotationDoable(ctx, hnd)) {
Saurabh Shahab47c692014-02-12 18:45:57 -08003041 (*rot) = ctx->mRotMgr->getNext();
3042 if((*rot) == NULL) return -1;
Saurabh Shah39240c92014-03-31 10:31:42 -07003043 ctx->mLayerRotMap[mDpy]->add(layer, *rot);
Saurabh Shah1bd5b6f2014-05-19 12:23:13 -07003044 //If the video is using a single pipe, enable BWC
3045 if(rDest == OV_INVALID) {
Saurabh Shahcd018352014-11-11 13:54:19 -08003046 BwcPM::setBwc(ctx, mDpy, hnd, crop, dst, transform, downscale,
3047 mdpFlags);
Saurabh Shah1bd5b6f2014-05-19 12:23:13 -07003048 }
Saurabh Shahab47c692014-02-12 18:45:57 -08003049 //Configure rotator for pre-rotation
Saurabh Shah97e2d802014-04-14 18:03:54 -07003050 if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale) < 0) {
Saurabh Shahab47c692014-02-12 18:45:57 -08003051 ALOGE("%s: configRotator failed!", __FUNCTION__);
3052 return -1;
3053 }
Saurabh Shah8ec9b5e2014-06-30 14:37:17 -07003054 updateSource(orient, whf, crop, *rot);
Saurabh Shahc46cf9d2014-07-02 15:22:34 -07003055 rotFlags |= ovutils::ROT_PREROTATED;
Saurabh Shahab47c692014-02-12 18:45:57 -08003056 }
3057
3058 //If 2 pipes being used, divide layer into half, crop and dst
3059 hwc_rect_t cropL = crop;
3060 hwc_rect_t cropR = crop;
3061 hwc_rect_t dstL = dst;
3062 hwc_rect_t dstR = dst;
3063 if(lDest != OV_INVALID && rDest != OV_INVALID) {
3064 cropL.right = (crop.right + crop.left) / 2;
3065 cropR.left = cropL.right;
3066 sanitizeSourceCrop(cropL, cropR, hnd);
3067
Saurabh Shahb729b192014-08-15 18:04:24 -07003068 bool cropSwap = false;
Saurabh Shahab47c692014-02-12 18:45:57 -08003069 //Swap crops on H flip since 2 pipes are being used
3070 if((orient & OVERLAY_TRANSFORM_FLIP_H) && (*rot) == NULL) {
3071 hwc_rect_t tmp = cropL;
3072 cropL = cropR;
3073 cropR = tmp;
Saurabh Shahb729b192014-08-15 18:04:24 -07003074 cropSwap = true;
Saurabh Shahab47c692014-02-12 18:45:57 -08003075 }
3076
Saurabh Shahb729b192014-08-15 18:04:24 -07003077 //cropSwap trick: If the src and dst widths are both odd, let us say
3078 //2507, then splitting both into half would cause left width to be 1253
3079 //and right 1254. If crop is swapped because of H flip, this will cause
3080 //left crop width to be 1254, whereas left dst width remains 1253, thus
3081 //inducing a scaling that is unaccounted for. To overcome that we add 1
3082 //to the dst width if there is a cropSwap. So if the original width was
3083 //2507, the left dst width will be 1254. Even if the original width was
3084 //even for ex: 2508, the left dst width will still remain 1254.
3085 dstL.right = (dst.right + dst.left + cropSwap) / 2;
Saurabh Shahab47c692014-02-12 18:45:57 -08003086 dstR.left = dstL.right;
3087 }
3088
3089 //For the mdp, since either we are pre-rotating or MDP does flips
3090 orient = OVERLAY_TRANSFORM_0;
3091 transform = 0;
3092
3093 //configure left pipe
3094 if(lDest != OV_INVALID) {
Saurabh Shah2c8ad052014-08-15 13:27:46 -07003095 PipeArgs pargL(mdpFlags, whf, z,
Saurabh Shahab47c692014-02-12 18:45:57 -08003096 static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
3097 (ovutils::eBlending) getBlending(layer->blending));
3098
3099 if(configMdp(ctx->mOverlay, pargL, orient,
3100 cropL, dstL, metadata, lDest) < 0) {
3101 ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
3102 return -1;
3103 }
3104 }
3105
3106 //configure right pipe
3107 if(rDest != OV_INVALID) {
Saurabh Shah2c8ad052014-08-15 13:27:46 -07003108 PipeArgs pargR(mdpFlags, whf, z,
Saurabh Shahab47c692014-02-12 18:45:57 -08003109 static_cast<eRotFlags>(rotFlags),
3110 layer->planeAlpha,
3111 (ovutils::eBlending) getBlending(layer->blending));
3112 if(configMdp(ctx->mOverlay, pargR, orient,
3113 cropR, dstR, metadata, rDest) < 0) {
3114 ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
3115 return -1;
3116 }
3117 }
3118
3119 return 0;
3120}
3121
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -08003122bool MDPComp::getPartialUpdatePref(hwc_context_t *ctx) {
3123 Locker::Autolock _l(ctx->mDrawLock);
3124 const int fbNum = Overlay::getFbForDpy(Overlay::DPY_PRIMARY);
3125 char path[MAX_SYSFS_FILE_PATH];
3126 snprintf (path, sizeof(path), "sys/class/graphics/fb%d/dyn_pu", fbNum);
3127 int fd = open(path, O_RDONLY);
3128 if(fd < 0) {
3129 ALOGE("%s: Failed to open sysfd node: %s", __FUNCTION__, path);
3130 return -1;
3131 }
3132 char value[4];
3133 ssize_t size_read = read(fd, value, sizeof(value)-1);
3134 if(size_read <= 0) {
3135 ALOGE("%s: Failed to read sysfd node: %s", __FUNCTION__, path);
3136 close(fd);
3137 return -1;
3138 }
3139 close(fd);
3140 value[size_read] = '\0';
3141 return atoi(value);
3142}
3143
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003144int MDPComp::setPartialUpdatePref(hwc_context_t *ctx, bool enable) {
3145 Locker::Autolock _l(ctx->mDrawLock);
3146 const int fbNum = Overlay::getFbForDpy(Overlay::DPY_PRIMARY);
3147 char path[MAX_SYSFS_FILE_PATH];
3148 snprintf (path, sizeof(path), "sys/class/graphics/fb%d/dyn_pu", fbNum);
3149 int fd = open(path, O_WRONLY);
3150 if(fd < 0) {
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -08003151 ALOGE("%s: Failed to open sysfd node: %s", __FUNCTION__, path);
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003152 return -1;
3153 }
3154 char value[4];
3155 snprintf(value, sizeof(value), "%d", (int)enable);
3156 ssize_t ret = write(fd, value, strlen(value));
3157 if(ret <= 0) {
Jeykumar Sankaranf4eb9fb2014-12-04 13:06:43 -08003158 ALOGE("%s: Failed to write to sysfd nodes: %s", __FUNCTION__, path);
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003159 close(fd);
3160 return -1;
3161 }
3162 close(fd);
Jeykumar Sankaran53b05f22014-08-05 11:27:03 -07003163 return 0;
3164}
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08003165
3166bool MDPComp::loadPerfLib() {
3167 char perfLibPath[PROPERTY_VALUE_MAX] = {0};
3168 bool success = false;
3169 if((property_get("ro.vendor.extension_library", perfLibPath, NULL) <= 0)) {
3170 ALOGE("vendor library not set in ro.vendor.extension_library");
3171 return false;
3172 }
3173
3174 sLibPerfHint = dlopen(perfLibPath, RTLD_NOW);
3175 if(sLibPerfHint) {
3176 *(void **)&sPerfLockAcquire = dlsym(sLibPerfHint, "perf_lock_acq");
3177 *(void **)&sPerfLockRelease = dlsym(sLibPerfHint, "perf_lock_rel");
3178 if (!sPerfLockAcquire || !sPerfLockRelease) {
3179 ALOGE("Failed to load symbols for perfLock");
3180 dlclose(sLibPerfHint);
3181 sLibPerfHint = NULL;
3182 return false;
3183 }
3184 success = true;
3185 ALOGI("Successfully Loaded perf hint API's");
3186 } else {
3187 ALOGE("Failed to open %s : %s", perfLibPath, dlerror());
3188 }
3189 return success;
3190}
3191
3192void MDPComp::setPerfHint(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
3193 if ((sPerfHintWindow < 0) || mDpy || !sLibPerfHint) {
3194 return;
3195 }
3196 static int count = sPerfHintWindow;
3197 static int perflockFlag = 0;
3198
3199 /* Send hint to mpctl when single layer is updated
3200 * for a successful number of windows. Hint release
3201 * happens immediately upon multiple layer update.
3202 */
3203 if (onlyVideosUpdating(ctx, list)) {
3204 if(count) {
3205 count--;
3206 }
3207 } else {
3208 if (perflockFlag) {
3209 perflockFlag = 0;
3210 sPerfLockRelease(sPerfLockHandle);
3211 }
3212 count = sPerfHintWindow;
3213 }
3214 if (count == 0 && !perflockFlag) {
3215 int perfHint = 0x4501; // 45-display layer hint, 01-Enable
3216 sPerfLockHandle = sPerfLockAcquire(0 /*handle*/, 0/*duration*/,
3217 &perfHint, sizeof(perfHint)/sizeof(int));
Arun Kumar K.R8b927022015-02-24 12:34:21 -08003218 if(sPerfLockHandle > 0) {
Arun Kumar K.R299bcda2014-12-18 19:36:40 -08003219 perflockFlag = 1;
3220 }
3221 }
3222}
3223
Naseer Ahmed7c958d42012-07-31 18:57:03 -07003224}; //namespace
3225