blob: 56432db9bc2f402ab039a6b993f4ca1e4549200e [file] [log] [blame]
Naseer Ahmed7c958d42012-07-31 18:57:03 -07001/*
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002 * Copyright (C) 2012-2013, 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
19#include "hwc_mdpcomp.h"
Naseer Ahmed54821fe2012-11-28 18:44:38 -050020#include <sys/ioctl.h>
Saurabh Shah56f610d2012-08-07 15:27:06 -070021#include "external.h"
Ramkumar Radhakrishnan47573e22012-11-07 11:36:41 -080022#include "qdMetaData.h"
Ramkumar Radhakrishnan288f8c72013-01-15 11:37:54 -080023#include "mdp_version.h"
Saurabh Shahacf10202013-02-26 10:15:15 -080024#include <overlayRotator.h>
25
26using overlay::Rotator;
27using namespace overlay::utils;
28namespace ovutils = overlay::utils;
Naseer Ahmed7c958d42012-07-31 18:57:03 -070029
Naseer Ahmed7c958d42012-07-31 18:57:03 -070030namespace qhwc {
31
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -080032//==============MDPComp========================================================
33
Naseer Ahmed7c958d42012-07-31 18:57:03 -070034IdleInvalidator *MDPComp::idleInvalidator = NULL;
35bool MDPComp::sIdleFallBack = false;
36bool MDPComp::sDebugLogs = false;
Naseer Ahmed54821fe2012-11-28 18:44:38 -050037bool MDPComp::sEnabled = false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -070038
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -080039MDPComp* MDPComp::getObject(const int& width) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -080040 if(width <= MAX_DISPLAY_DIM) {
41 return new MDPCompLowRes();
42 } else {
43 return new MDPCompHighRes();
44 }
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -080045}
46
47void MDPComp::dump(android::String8& buf)
48{
49 dumpsys_log(buf, " MDP Composition: ");
50 dumpsys_log(buf, "MDPCompState=%d\n", mState);
51 //XXX: Log more info
52}
53
54bool MDPComp::init(hwc_context_t *ctx) {
55
56 if(!ctx) {
57 ALOGE("%s: Invalid hwc context!!",__FUNCTION__);
58 return false;
59 }
60
61 if(!setupBasePipe(ctx)) {
62 ALOGE("%s: Failed to setup primary base pipe", __FUNCTION__);
63 return false;
64 }
65
66 char property[PROPERTY_VALUE_MAX];
67
68 sEnabled = false;
69 if((property_get("persist.hwc.mdpcomp.enable", property, NULL) > 0) &&
70 (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
71 (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
72 sEnabled = true;
73 }
74
75 sDebugLogs = false;
76 if(property_get("debug.mdpcomp.logs", property, NULL) > 0) {
77 if(atoi(property) != 0)
78 sDebugLogs = true;
79 }
80
81 unsigned long idle_timeout = DEFAULT_IDLE_TIME;
82 if(property_get("debug.mdpcomp.idletime", property, NULL) > 0) {
83 if(atoi(property) != 0)
84 idle_timeout = atoi(property);
85 }
86
87 //create Idle Invalidator
88 idleInvalidator = IdleInvalidator::getInstance();
89
90 if(idleInvalidator == NULL) {
91 ALOGE("%s: failed to instantiate idleInvalidator object", __FUNCTION__);
92 } else {
93 idleInvalidator->init(timeout_handler, ctx, idle_timeout);
94 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -070095 return true;
96}
97
98void MDPComp::timeout_handler(void *udata) {
99 struct hwc_context_t* ctx = (struct hwc_context_t*)(udata);
100
101 if(!ctx) {
102 ALOGE("%s: received empty data in timer callback", __FUNCTION__);
103 return;
104 }
105
Jesse Hall3be78d92012-08-21 15:12:23 -0700106 if(!ctx->proc) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700107 ALOGE("%s: HWC proc not registered", __FUNCTION__);
108 return;
109 }
110 sIdleFallBack = true;
111 /* Trigger SF to redraw the current frame */
Jesse Hall3be78d92012-08-21 15:12:23 -0700112 ctx->proc->invalidate(ctx->proc);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700113}
114
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800115void MDPComp::setMDPCompLayerFlags(hwc_context_t *ctx,
116 hwc_display_contents_1_t* list) {
117 const int dpy = HWC_DISPLAY_PRIMARY;
118 LayerProp *layerProp = ctx->layerProp[dpy];
119
120 for(int index = 0; index < ctx->listStats[dpy].numAppLayers; index++ ) {
121 hwc_layer_1_t* layer = &(list->hwLayers[index]);
122 layerProp[index].mFlags |= HWC_MDPCOMP;
123 layer->compositionType = HWC_OVERLAY;
124 layer->hints |= HWC_HINT_CLEAR_FB;
Naseer Ahmed52ca6d22012-10-08 14:03:01 -0400125 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700126}
127
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800128void MDPComp::unsetMDPCompLayerFlags(hwc_context_t* ctx,
129 hwc_display_contents_1_t* list) {
130 const int dpy = HWC_DISPLAY_PRIMARY;
131 LayerProp *layerProp = ctx->layerProp[dpy];
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700132
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800133 for (int index = 0 ;
134 index < ctx->listStats[dpy].numAppLayers; index++) {
135 if(layerProp[index].mFlags & HWC_MDPCOMP) {
136 layerProp[index].mFlags &= ~HWC_MDPCOMP;
137 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700138
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800139 if(list->hwLayers[index].compositionType == HWC_OVERLAY) {
140 list->hwLayers[index].compositionType = HWC_FRAMEBUFFER;
141 }
142 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700143}
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500144
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800145/*
146 * Sets up BORDERFILL as default base pipe and detaches RGB0.
147 * Framebuffer is always updated using PLAY ioctl.
148 */
149bool MDPComp::setupBasePipe(hwc_context_t *ctx) {
150 const int dpy = HWC_DISPLAY_PRIMARY;
151 int fb_stride = ctx->dpyAttr[dpy].stride;
152 int fb_width = ctx->dpyAttr[dpy].xres;
153 int fb_height = ctx->dpyAttr[dpy].yres;
154 int fb_fd = ctx->dpyAttr[dpy].fd;
155
156 mdp_overlay ovInfo;
157 msmfb_overlay_data ovData;
158 memset(&ovInfo, 0, sizeof(mdp_overlay));
159 memset(&ovData, 0, sizeof(msmfb_overlay_data));
160
161 ovInfo.src.format = MDP_RGB_BORDERFILL;
162 ovInfo.src.width = fb_width;
163 ovInfo.src.height = fb_height;
164 ovInfo.src_rect.w = fb_width;
165 ovInfo.src_rect.h = fb_height;
166 ovInfo.dst_rect.w = fb_width;
167 ovInfo.dst_rect.h = fb_height;
168 ovInfo.id = MSMFB_NEW_REQUEST;
169
170 if (ioctl(fb_fd, MSMFB_OVERLAY_SET, &ovInfo) < 0) {
171 ALOGE("Failed to call ioctl MSMFB_OVERLAY_SET err=%s",
172 strerror(errno));
173 return false;
174 }
175
176 ovData.id = ovInfo.id;
177 if (ioctl(fb_fd, MSMFB_OVERLAY_PLAY, &ovData) < 0) {
178 ALOGE("Failed to call ioctl MSMFB_OVERLAY_PLAY err=%s",
179 strerror(errno));
180 return false;
181 }
182 return true;
183}
184
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800185void MDPComp::reset(hwc_context_t *ctx,
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800186 hwc_display_contents_1_t* list ) {
187 //Reset flags and states
188 unsetMDPCompLayerFlags(ctx, list);
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800189 if(mCurrentFrame.pipeLayer) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800190 for(int i = 0 ; i < mCurrentFrame.count; i++ ) {
191 if(mCurrentFrame.pipeLayer[i].pipeInfo) {
192 delete mCurrentFrame.pipeLayer[i].pipeInfo;
193 mCurrentFrame.pipeLayer[i].pipeInfo = NULL;
Saurabh Shahacf10202013-02-26 10:15:15 -0800194 //We dont own the rotator
195 mCurrentFrame.pipeLayer[i].rot = NULL;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800196 }
197 }
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800198 free(mCurrentFrame.pipeLayer);
199 mCurrentFrame.pipeLayer = NULL;
200 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800201 mCurrentFrame.count = 0;
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800202}
203
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800204bool MDPComp::isWidthValid(hwc_context_t *ctx, hwc_layer_1_t *layer) {
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800205
206 const int dpy = HWC_DISPLAY_PRIMARY;
207 private_handle_t *hnd = (private_handle_t *)layer->handle;
208
209 if(!hnd) {
210 ALOGE("%s: layer handle is NULL", __FUNCTION__);
211 return false;
212 }
213
214 int hw_w = ctx->dpyAttr[dpy].xres;
215 int hw_h = ctx->dpyAttr[dpy].yres;
216
217 hwc_rect_t sourceCrop = layer->sourceCrop;
218 hwc_rect_t displayFrame = layer->displayFrame;
219
220 hwc_rect_t crop = sourceCrop;
221 int crop_w = crop.right - crop.left;
222 int crop_h = crop.bottom - crop.top;
223
224 hwc_rect_t dst = displayFrame;
225 int dst_w = dst.right - dst.left;
226 int dst_h = dst.bottom - dst.top;
227
228 if(dst.left < 0 || dst.top < 0 || dst.right > hw_w || dst.bottom > hw_h) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800229 hwc_rect_t scissor = {0, 0, hw_w, hw_h };
230 qhwc::calculate_crop_rects(crop, dst, scissor, layer->transform);
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800231 crop_w = crop.right - crop.left;
232 crop_h = crop.bottom - crop.top;
233 }
234
235 //Workaround for MDP HW limitation in DSI command mode panels where
236 //FPS will not go beyond 30 if buffers on RGB pipes are of width < 5
237
238 if(crop_w < 5)
239 return false;
240
241 return true;
242}
243
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800244ovutils::eDest MDPComp::getMdpPipe(hwc_context_t *ctx, ePipeType type) {
245 const int dpy = HWC_DISPLAY_PRIMARY;
246 overlay::Overlay& ov = *ctx->mOverlay;
247 ovutils::eDest mdp_pipe = ovutils::OV_INVALID;
248
249 switch(type) {
250 case MDPCOMP_OV_DMA:
251 mdp_pipe = ov.nextPipe(ovutils::OV_MDP_PIPE_DMA, dpy);
252 if(mdp_pipe != ovutils::OV_INVALID) {
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -0800253 ctx->mDMAInUse = true;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800254 return mdp_pipe;
255 }
256 case MDPCOMP_OV_ANY:
257 case MDPCOMP_OV_RGB:
258 mdp_pipe = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, dpy);
259 if(mdp_pipe != ovutils::OV_INVALID) {
260 return mdp_pipe;
261 }
262
263 if(type == MDPCOMP_OV_RGB) {
264 //Requested only for RGB pipe
265 break;
266 }
267 case MDPCOMP_OV_VG:
268 return ov.nextPipe(ovutils::OV_MDP_PIPE_VG, dpy);
269 default:
270 ALOGE("%s: Invalid pipe type",__FUNCTION__);
271 return ovutils::OV_INVALID;
272 };
273 return ovutils::OV_INVALID;
274}
275
276bool MDPComp::isDoable(hwc_context_t *ctx,
277 hwc_display_contents_1_t* list) {
278 //Number of layers
279 const int dpy = HWC_DISPLAY_PRIMARY;
280 int numAppLayers = ctx->listStats[dpy].numAppLayers;
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -0800281 int numDMAPipes = qdutils::MDPVersion::getInstance().getDMAPipes();
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800282
283 overlay::Overlay& ov = *ctx->mOverlay;
284 int availablePipes = ov.availablePipes(dpy);
285
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -0800286 if(ctx->mNeedsRotator)
287 availablePipes -= numDMAPipes;
288
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800289 if(numAppLayers < 1 || numAppLayers > MAX_PIPES_PER_MIXER ||
290 pipesNeeded(ctx, list) > availablePipes) {
291 ALOGD_IF(isDebug(), "%s: Unsupported number of layers",__FUNCTION__);
292 return false;
293 }
294
295 if(ctx->mExtDispConfiguring) {
296 ALOGD_IF( isDebug(),"%s: External Display connection is pending",
297 __FUNCTION__);
298 return false;
299 }
300
301 if(isSecuring(ctx)) {
302 ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
303 return false;
304 }
305
306 if(ctx->mSecureMode)
307 return false;
308
309 //Check for skip layers
310 if(isSkipPresent(ctx, dpy)) {
311 ALOGD_IF(isDebug(), "%s: Skip layers are present",__FUNCTION__);
312 return false;
313 }
314
315 if(ctx->listStats[dpy].needsAlphaScale
316 && ctx->mMDP.version < qdutils::MDSS_V5) {
317 ALOGD_IF(isDebug(), "%s: frame needs alpha downscaling",__FUNCTION__);
318 return false;
319 }
320
321 //FB composition on idle timeout
322 if(sIdleFallBack) {
323 sIdleFallBack = false;
324 ALOGD_IF(isDebug(), "%s: idle fallback",__FUNCTION__);
325 return false;
326 }
327
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -0800328 if(ctx->mNeedsRotator && ctx->mDMAInUse) {
329 ALOGD_IF(isDebug(), "%s: DMA not available for Rotator",__FUNCTION__);
330 return false;
331 }
332
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800333 //MDP composition is not efficient if layer needs rotator.
334 for(int i = 0; i < numAppLayers; ++i) {
335 // As MDP h/w supports flip operation, use MDP comp only for
336 // 180 transforms. Fail for any transform involving 90 (90, 270).
337 hwc_layer_1_t* layer = &list->hwLayers[i];
338 private_handle_t *hnd = (private_handle_t *)layer->handle;
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -0800339
340 if(layer->transform & HWC_TRANSFORM_ROT_90 && !isYuvBuffer(hnd)) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800341 ALOGD_IF(isDebug(), "%s: orientation involved",__FUNCTION__);
342 return false;
343 }
344
345 if(!isYuvBuffer(hnd) && !isWidthValid(ctx,layer)) {
346 ALOGD_IF(isDebug(), "%s: Buffer is of invalid width",__FUNCTION__);
347 return false;
348 }
349 }
350 return true;
351}
352
353bool MDPComp::setup(hwc_context_t* ctx, hwc_display_contents_1_t* list) {
354 const int dpy = HWC_DISPLAY_PRIMARY;
355 if(!ctx) {
356 ALOGE("%s: invalid context", __FUNCTION__);
357 return -1;
358 }
359
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -0800360 ctx->mDMAInUse = false;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800361 if(!allocLayerPipes(ctx, list, mCurrentFrame)) {
362 ALOGD_IF(isDebug(), "%s: Falling back to FB", __FUNCTION__);
363 return false;
364 }
365
366 for (int index = 0 ; index < mCurrentFrame.count; index++) {
367 hwc_layer_1_t* layer = &list->hwLayers[index];
Saurabh Shahacf10202013-02-26 10:15:15 -0800368 if(configure(ctx, layer, mCurrentFrame.pipeLayer[index]) != 0 ) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800369 ALOGD_IF(isDebug(), "%s: MDPComp failed to configure overlay for \
370 layer %d",__FUNCTION__, index);
371 return false;
372 }
373 }
374 return true;
375}
376
377bool MDPComp::prepare(hwc_context_t *ctx,
378 hwc_display_contents_1_t* list) {
379 if(!isEnabled()) {
380 ALOGE_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
381 return false;
382 }
383
384 overlay::Overlay& ov = *ctx->mOverlay;
385 bool isMDPCompUsed = true;
386
387 //reset old data
388 reset(ctx, list);
389
390 bool doable = isDoable(ctx, list);
391 if(doable) {
392 if(setup(ctx, list)) {
393 setMDPCompLayerFlags(ctx, list);
394 } else {
395 ALOGD_IF(isDebug(),"%s: MDP Comp Failed",__FUNCTION__);
396 isMDPCompUsed = false;
397 }
398 } else {
399 ALOGD_IF( isDebug(),"%s: MDP Comp not possible[%d]",__FUNCTION__,
400 doable);
401 isMDPCompUsed = false;
402 }
403
404 //Reset states
405 if(!isMDPCompUsed) {
406 //Reset current frame
407 reset(ctx, list);
408 }
409
410 mState = isMDPCompUsed ? MDPCOMP_ON : MDPCOMP_OFF;
411 return isMDPCompUsed;
412}
413
414//=============MDPCompLowRes===================================================
415
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700416/*
417 * Configures pipe(s) for MDP composition
418 */
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800419int MDPCompLowRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
Saurabh Shahacf10202013-02-26 10:15:15 -0800420 PipeLayerPair& pipeLayerPair) {
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800421 const int dpy = HWC_DISPLAY_PRIMARY;
Saurabh Shahacf10202013-02-26 10:15:15 -0800422 MdpPipeInfoLowRes& mdp_info =
423 *(static_cast<MdpPipeInfoLowRes*>(pipeLayerPair.pipeInfo));
424 eMdpFlags mdpFlags = OV_MDP_BACKEND_COMPOSITION;
425 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
426 eIsFg isFg = IS_FG_OFF;
427 eDest dest = mdp_info.index;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700428
Saurabh Shahacf10202013-02-26 10:15:15 -0800429 return configureLowRes(ctx, layer, dpy, mdpFlags, zOrder, isFg, dest,
430 &pipeLayerPair.rot);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700431}
432
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800433int MDPCompLowRes::pipesNeeded(hwc_context_t *ctx,
434 hwc_display_contents_1_t* list) {
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800435 const int dpy = HWC_DISPLAY_PRIMARY;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800436 return ctx->listStats[dpy].numAppLayers;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700437}
438
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800439bool MDPCompLowRes::allocLayerPipes(hwc_context_t *ctx,
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700440 hwc_display_contents_1_t* list,
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500441 FrameInfo& currentFrame) {
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800442 const int dpy = HWC_DISPLAY_PRIMARY;
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500443 overlay::Overlay& ov = *ctx->mOverlay;
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800444 int layer_count = ctx->listStats[dpy].numAppLayers;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700445
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500446 currentFrame.count = layer_count;
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500447 currentFrame.pipeLayer = (PipeLayerPair*)
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800448 malloc(sizeof(PipeLayerPair) * currentFrame.count);
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500449
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800450 if(isYuvPresent(ctx, dpy)) {
Jeykumar Sankarancf537002013-01-21 21:19:15 -0800451 int nYuvCount = ctx->listStats[dpy].yuvCount;
452
453 for(int index = 0; index < nYuvCount; index ++) {
454 int nYuvIndex = ctx->listStats[dpy].yuvIndices[index];
455 hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
456 PipeLayerPair& info = currentFrame.pipeLayer[nYuvIndex];
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800457 info.pipeInfo = new MdpPipeInfoLowRes;
Saurabh Shahacf10202013-02-26 10:15:15 -0800458 info.rot = NULL;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800459 MdpPipeInfoLowRes& pipe_info = *(MdpPipeInfoLowRes*)info.pipeInfo;
Jeykumar Sankarancf537002013-01-21 21:19:15 -0800460 pipe_info.index = getMdpPipe(ctx, MDPCOMP_OV_VG);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800461 if(pipe_info.index == ovutils::OV_INVALID) {
Jeykumar Sankarancf537002013-01-21 21:19:15 -0800462 ALOGD_IF(isDebug(), "%s: Unable to get pipe for Videos",
463 __FUNCTION__);
464 return false;
465 }
466 pipe_info.zOrder = nYuvIndex;
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500467 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500468 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700469
470 for(int index = 0 ; index < layer_count ; index++ ) {
Jeykumar Sankarancf537002013-01-21 21:19:15 -0800471 hwc_layer_1_t* layer = &list->hwLayers[index];
472 private_handle_t *hnd = (private_handle_t *)layer->handle;
473
474 if(isYuvBuffer(hnd))
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500475 continue;
476
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500477 PipeLayerPair& info = currentFrame.pipeLayer[index];
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800478 info.pipeInfo = new MdpPipeInfoLowRes;
Saurabh Shahacf10202013-02-26 10:15:15 -0800479 info.rot = NULL;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800480 MdpPipeInfoLowRes& pipe_info = *(MdpPipeInfoLowRes*)info.pipeInfo;
481
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -0800482 ePipeType type = MDPCOMP_OV_ANY;
483
484 if(!qhwc::needsScaling(layer) && !ctx->mNeedsRotator
485 && ctx->mMDP.version >= qdutils::MDSS_V5) {
486 type = MDPCOMP_OV_DMA;
487 }
488
489 pipe_info.index = getMdpPipe(ctx, type);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800490 if(pipe_info.index == ovutils::OV_INVALID) {
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500491 ALOGD_IF(isDebug(), "%s: Unable to get pipe for UI", __FUNCTION__);
492 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700493 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500494 pipe_info.zOrder = index;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700495 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700496 return true;
497}
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700498
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800499bool MDPCompLowRes::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700500
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500501 if(!isEnabled() || !isUsed()) {
502 ALOGD_IF(isDebug(),"%s: MDP Comp not configured", __FUNCTION__);
503 return true;
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800504 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700505
506 if(!ctx || !list) {
507 ALOGE("%s: invalid contxt or list",__FUNCTION__);
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500508 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700509 }
510
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500511 /* reset Invalidator */
512 if(idleInvalidator)
513 idleInvalidator->markForSleep();
514
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800515 const int dpy = HWC_DISPLAY_PRIMARY;
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500516 overlay::Overlay& ov = *ctx->mOverlay;
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800517 LayerProp *layerProp = ctx->layerProp[dpy];
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700518
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800519 int numHwLayers = ctx->listStats[dpy].numAppLayers;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700520 for(int i = 0; i < numHwLayers; i++ )
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700521 {
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700522 hwc_layer_1_t *layer = &list->hwLayers[i];
Saurabh Shahacf10202013-02-26 10:15:15 -0800523 private_handle_t *hnd = (private_handle_t *)layer->handle;
524 if(!hnd) {
525 ALOGE("%s handle null", __FUNCTION__);
526 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700527 }
528
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800529 MdpPipeInfoLowRes& pipe_info =
530 *(MdpPipeInfoLowRes*)mCurrentFrame.pipeLayer[i].pipeInfo;
531 ovutils::eDest dest = pipe_info.index;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800532 if(dest == ovutils::OV_INVALID) {
533 ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, dest);
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500534 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700535 }
536
Saurabh Shahacf10202013-02-26 10:15:15 -0800537 if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
538 continue;
539 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700540
Saurabh Shahacf10202013-02-26 10:15:15 -0800541 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
542 using pipe: %d", __FUNCTION__, layer,
543 hnd, dest );
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700544
Saurabh Shahacf10202013-02-26 10:15:15 -0800545 int fd = hnd->fd;
546 uint32_t offset = hnd->offset;
547 Rotator *rot = mCurrentFrame.pipeLayer[i].rot;
548 if(rot) {
549 if(!rot->queueBuffer(fd, offset))
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500550 return false;
Saurabh Shahacf10202013-02-26 10:15:15 -0800551 fd = rot->getDstMemId();
552 offset = rot->getDstOffset();
553 }
554
555 if (!ov.queueBuffer(fd, offset, dest)) {
556 ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
557 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700558 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500559
560 layerProp[i].mFlags &= ~HWC_MDPCOMP;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700561 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500562 return true;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700563}
564
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800565//=============MDPCompHighRes===================================================
566
567int MDPCompHighRes::pipesNeeded(hwc_context_t *ctx,
568 hwc_display_contents_1_t* list) {
569 const int dpy = HWC_DISPLAY_PRIMARY;
570 int numAppLayers = ctx->listStats[dpy].numAppLayers;
571 int pipesNeeded = 0;
572
573 int hw_w = ctx->dpyAttr[dpy].xres;
574
575 for(int i = 0; i < numAppLayers; ++i) {
576 hwc_layer_1_t* layer = &list->hwLayers[i];
577 hwc_rect_t dst = layer->displayFrame;
578 if(dst.left > hw_w/2) {
579 pipesNeeded++;
580 } else if(dst.right <= hw_w/2) {
581 pipesNeeded++;
582 } else {
583 pipesNeeded += 2;
584 }
585 }
586 return pipesNeeded;
587}
588
589bool MDPCompHighRes::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
590 MdpPipeInfoHighRes& pipe_info, ePipeType type) {
591 const int dpy = HWC_DISPLAY_PRIMARY;
592 int hw_w = ctx->dpyAttr[dpy].xres;
593
594 hwc_rect_t dst = layer->displayFrame;
595 if(dst.left > hw_w/2) {
596 pipe_info.lIndex = ovutils::OV_INVALID;
597 pipe_info.rIndex = getMdpPipe(ctx, type);
598 if(pipe_info.rIndex == ovutils::OV_INVALID)
599 return false;
600 } else if (dst.right <= hw_w/2) {
601 pipe_info.rIndex = ovutils::OV_INVALID;
602 pipe_info.lIndex = getMdpPipe(ctx, type);
603 if(pipe_info.lIndex == ovutils::OV_INVALID)
604 return false;
605 } else {
606 pipe_info.rIndex = getMdpPipe(ctx, type);
607 pipe_info.lIndex = getMdpPipe(ctx, type);
608 if(pipe_info.rIndex == ovutils::OV_INVALID ||
609 pipe_info.lIndex == ovutils::OV_INVALID)
610 return false;
611 }
612 return true;
613}
614
615bool MDPCompHighRes::allocLayerPipes(hwc_context_t *ctx,
616 hwc_display_contents_1_t* list,
617 FrameInfo& currentFrame) {
618 const int dpy = HWC_DISPLAY_PRIMARY;
619 overlay::Overlay& ov = *ctx->mOverlay;
620 int layer_count = ctx->listStats[dpy].numAppLayers;
621
622 currentFrame.count = layer_count;
623 currentFrame.pipeLayer = (PipeLayerPair*)
624 malloc(sizeof(PipeLayerPair) * currentFrame.count);
625
626 if(isYuvPresent(ctx, dpy)) {
627 int nYuvCount = ctx->listStats[dpy].yuvCount;
628
629 for(int index = 0; index < nYuvCount; index ++) {
630 int nYuvIndex = ctx->listStats[dpy].yuvIndices[index];
631 hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
632 PipeLayerPair& info = currentFrame.pipeLayer[nYuvIndex];
633 info.pipeInfo = new MdpPipeInfoHighRes;
634 MdpPipeInfoHighRes& pipe_info = *(MdpPipeInfoHighRes*)info.pipeInfo;
635 if(!acquireMDPPipes(ctx, layer, pipe_info,MDPCOMP_OV_VG)) {
636 ALOGD_IF(isDebug(),"%s: Unable to get pipe for videos",
637 __FUNCTION__);
638 //TODO: windback pipebook data on fail
639 return false;
640 }
641 pipe_info.zOrder = nYuvIndex;
642 }
643 }
644
645 for(int index = 0 ; index < layer_count ; index++ ) {
646 hwc_layer_1_t* layer = &list->hwLayers[index];
647 private_handle_t *hnd = (private_handle_t *)layer->handle;
648
649 if(isYuvBuffer(hnd))
650 continue;
651
652 PipeLayerPair& info = currentFrame.pipeLayer[index];
653 info.pipeInfo = new MdpPipeInfoHighRes;
654 MdpPipeInfoHighRes& pipe_info = *(MdpPipeInfoHighRes*)info.pipeInfo;
655
656 ePipeType type = MDPCOMP_OV_ANY;
657
Jeykumar Sankarana37fdbf2013-03-06 18:59:28 -0800658 if(!qhwc::needsScaling(layer) && !ctx->mNeedsRotator
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800659 && ctx->mMDP.version >= qdutils::MDSS_V5)
660 type = MDPCOMP_OV_DMA;
661
662 if(!acquireMDPPipes(ctx, layer, pipe_info, type)) {
663 ALOGD_IF(isDebug(), "%s: Unable to get pipe for UI", __FUNCTION__);
664 //TODO: windback pipebook data on fail
665 return false;
666 }
667 pipe_info.zOrder = index;
668 }
669 return true;
670}
671/*
672 * Configures pipe(s) for MDP composition
673 */
674int MDPCompHighRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
Saurabh Shahacf10202013-02-26 10:15:15 -0800675 PipeLayerPair& pipeLayerPair) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800676 const int dpy = HWC_DISPLAY_PRIMARY;
Saurabh Shahacf10202013-02-26 10:15:15 -0800677 MdpPipeInfoHighRes& mdp_info =
678 *(static_cast<MdpPipeInfoHighRes*>(pipeLayerPair.pipeInfo));
679 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
680 eIsFg isFg = IS_FG_OFF;
681 eMdpFlags mdpFlagsL = OV_MDP_BACKEND_COMPOSITION;
682 eDest lDest = mdp_info.lIndex;
683 eDest rDest = mdp_info.rIndex;
684 return configureHighRes(ctx, layer, dpy, mdpFlagsL, zOrder, isFg, lDest,
685 rDest, &pipeLayerPair.rot);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800686}
687
688bool MDPCompHighRes::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
689
690 if(!isEnabled() || !isUsed()) {
691 ALOGD_IF(isDebug(),"%s: MDP Comp not configured", __FUNCTION__);
692 return true;
693 }
694
695 if(!ctx || !list) {
696 ALOGE("%s: invalid contxt or list",__FUNCTION__);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700697 return false;
698 }
699
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800700 /* reset Invalidator */
701 if(idleInvalidator)
702 idleInvalidator->markForSleep();
703
704 const int dpy = HWC_DISPLAY_PRIMARY;
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500705 overlay::Overlay& ov = *ctx->mOverlay;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800706 LayerProp *layerProp = ctx->layerProp[dpy];
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700707
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800708 int numHwLayers = ctx->listStats[dpy].numAppLayers;
709 for(int i = 0; i < numHwLayers; i++ )
710 {
711 hwc_layer_1_t *layer = &list->hwLayers[i];
Saurabh Shahacf10202013-02-26 10:15:15 -0800712 private_handle_t *hnd = (private_handle_t *)layer->handle;
713 if(!hnd) {
714 ALOGE("%s handle null", __FUNCTION__);
715 return false;
716 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800717
718 if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
719 continue;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700720 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700721
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800722 MdpPipeInfoHighRes& pipe_info =
723 *(MdpPipeInfoHighRes*)mCurrentFrame.pipeLayer[i].pipeInfo;
Saurabh Shahacf10202013-02-26 10:15:15 -0800724 Rotator *rot = mCurrentFrame.pipeLayer[i].rot;
725
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800726 ovutils::eDest indexL = pipe_info.lIndex;
727 ovutils::eDest indexR = pipe_info.rIndex;
Saurabh Shahacf10202013-02-26 10:15:15 -0800728 int fd = hnd->fd;
729 int offset = hnd->offset;
730
731 if(rot) {
732 rot->queueBuffer(fd, offset);
733 fd = rot->getDstMemId();
734 offset = rot->getDstOffset();
735 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700736
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800737 //************* play left mixer **********
738 if(indexL != ovutils::OV_INVALID) {
739 ovutils::eDest destL = (ovutils::eDest)indexL;
Saurabh Shahacf10202013-02-26 10:15:15 -0800740 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
741 using pipe: %d", __FUNCTION__, layer, hnd, indexL );
742 if (!ov.queueBuffer(fd, offset, destL)) {
743 ALOGE("%s: queueBuffer failed for left mixer", __FUNCTION__);
744 return false;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800745 }
746 }
747
748 //************* play right mixer **********
749 if(indexR != ovutils::OV_INVALID) {
750 ovutils::eDest destR = (ovutils::eDest)indexR;
Saurabh Shahacf10202013-02-26 10:15:15 -0800751 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
752 using pipe: %d", __FUNCTION__, layer, hnd, indexR );
753 if (!ov.queueBuffer(fd, offset, destR)) {
754 ALOGE("%s: queueBuffer failed for right mixer", __FUNCTION__);
755 return false;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800756 }
757 }
Saurabh Shahacf10202013-02-26 10:15:15 -0800758
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800759 layerProp[i].mFlags &= ~HWC_MDPCOMP;
760 }
Saurabh Shahacf10202013-02-26 10:15:15 -0800761
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800762 return true;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700763}
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700764}; //namespace
765