blob: f141af804e8826624fe1833adc503dc4cdb3e11f [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) {
253 return mdp_pipe;
254 }
255 case MDPCOMP_OV_ANY:
256 case MDPCOMP_OV_RGB:
257 mdp_pipe = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, dpy);
258 if(mdp_pipe != ovutils::OV_INVALID) {
259 return mdp_pipe;
260 }
261
262 if(type == MDPCOMP_OV_RGB) {
263 //Requested only for RGB pipe
264 break;
265 }
266 case MDPCOMP_OV_VG:
267 return ov.nextPipe(ovutils::OV_MDP_PIPE_VG, dpy);
268 default:
269 ALOGE("%s: Invalid pipe type",__FUNCTION__);
270 return ovutils::OV_INVALID;
271 };
272 return ovutils::OV_INVALID;
273}
274
275bool MDPComp::isDoable(hwc_context_t *ctx,
276 hwc_display_contents_1_t* list) {
277 //Number of layers
278 const int dpy = HWC_DISPLAY_PRIMARY;
279 int numAppLayers = ctx->listStats[dpy].numAppLayers;
280
281 overlay::Overlay& ov = *ctx->mOverlay;
282 int availablePipes = ov.availablePipes(dpy);
283
284 if(numAppLayers < 1 || numAppLayers > MAX_PIPES_PER_MIXER ||
285 pipesNeeded(ctx, list) > availablePipes) {
286 ALOGD_IF(isDebug(), "%s: Unsupported number of layers",__FUNCTION__);
287 return false;
288 }
289
290 if(ctx->mExtDispConfiguring) {
291 ALOGD_IF( isDebug(),"%s: External Display connection is pending",
292 __FUNCTION__);
293 return false;
294 }
295
296 if(isSecuring(ctx)) {
297 ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
298 return false;
299 }
300
301 if(ctx->mSecureMode)
302 return false;
303
304 //Check for skip layers
305 if(isSkipPresent(ctx, dpy)) {
306 ALOGD_IF(isDebug(), "%s: Skip layers are present",__FUNCTION__);
307 return false;
308 }
309
310 if(ctx->listStats[dpy].needsAlphaScale
311 && ctx->mMDP.version < qdutils::MDSS_V5) {
312 ALOGD_IF(isDebug(), "%s: frame needs alpha downscaling",__FUNCTION__);
313 return false;
314 }
315
316 //FB composition on idle timeout
317 if(sIdleFallBack) {
318 sIdleFallBack = false;
319 ALOGD_IF(isDebug(), "%s: idle fallback",__FUNCTION__);
320 return false;
321 }
322
323 //MDP composition is not efficient if layer needs rotator.
324 for(int i = 0; i < numAppLayers; ++i) {
325 // As MDP h/w supports flip operation, use MDP comp only for
326 // 180 transforms. Fail for any transform involving 90 (90, 270).
327 hwc_layer_1_t* layer = &list->hwLayers[i];
328 private_handle_t *hnd = (private_handle_t *)layer->handle;
329 if((layer->transform & HWC_TRANSFORM_ROT_90) && (!isYuvBuffer(hnd)
330 || !canRotate())) {
331 ALOGD_IF(isDebug(), "%s: orientation involved",__FUNCTION__);
332 return false;
333 }
334
335 if(!isYuvBuffer(hnd) && !isWidthValid(ctx,layer)) {
336 ALOGD_IF(isDebug(), "%s: Buffer is of invalid width",__FUNCTION__);
337 return false;
338 }
339 }
340 return true;
341}
342
343bool MDPComp::setup(hwc_context_t* ctx, hwc_display_contents_1_t* list) {
344 const int dpy = HWC_DISPLAY_PRIMARY;
345 if(!ctx) {
346 ALOGE("%s: invalid context", __FUNCTION__);
347 return -1;
348 }
349
350 if(!allocLayerPipes(ctx, list, mCurrentFrame)) {
351 ALOGD_IF(isDebug(), "%s: Falling back to FB", __FUNCTION__);
352 return false;
353 }
354
355 for (int index = 0 ; index < mCurrentFrame.count; index++) {
356 hwc_layer_1_t* layer = &list->hwLayers[index];
Saurabh Shahacf10202013-02-26 10:15:15 -0800357 if(configure(ctx, layer, mCurrentFrame.pipeLayer[index]) != 0 ) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800358 ALOGD_IF(isDebug(), "%s: MDPComp failed to configure overlay for \
359 layer %d",__FUNCTION__, index);
360 return false;
361 }
362 }
363 return true;
364}
365
366bool MDPComp::prepare(hwc_context_t *ctx,
367 hwc_display_contents_1_t* list) {
368 if(!isEnabled()) {
369 ALOGE_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
370 return false;
371 }
372
373 overlay::Overlay& ov = *ctx->mOverlay;
374 bool isMDPCompUsed = true;
375
376 //reset old data
377 reset(ctx, list);
378
379 bool doable = isDoable(ctx, list);
380 if(doable) {
381 if(setup(ctx, list)) {
382 setMDPCompLayerFlags(ctx, list);
383 } else {
384 ALOGD_IF(isDebug(),"%s: MDP Comp Failed",__FUNCTION__);
385 isMDPCompUsed = false;
386 }
387 } else {
388 ALOGD_IF( isDebug(),"%s: MDP Comp not possible[%d]",__FUNCTION__,
389 doable);
390 isMDPCompUsed = false;
391 }
392
393 //Reset states
394 if(!isMDPCompUsed) {
395 //Reset current frame
396 reset(ctx, list);
397 }
398
399 mState = isMDPCompUsed ? MDPCOMP_ON : MDPCOMP_OFF;
400 return isMDPCompUsed;
401}
402
403//=============MDPCompLowRes===================================================
404
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700405/*
406 * Configures pipe(s) for MDP composition
407 */
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800408int MDPCompLowRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
Saurabh Shahacf10202013-02-26 10:15:15 -0800409 PipeLayerPair& pipeLayerPair) {
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800410 const int dpy = HWC_DISPLAY_PRIMARY;
Saurabh Shahacf10202013-02-26 10:15:15 -0800411 MdpPipeInfoLowRes& mdp_info =
412 *(static_cast<MdpPipeInfoLowRes*>(pipeLayerPair.pipeInfo));
413 eMdpFlags mdpFlags = OV_MDP_BACKEND_COMPOSITION;
414 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
415 eIsFg isFg = IS_FG_OFF;
416 eDest dest = mdp_info.index;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700417
Saurabh Shahacf10202013-02-26 10:15:15 -0800418 return configureLowRes(ctx, layer, dpy, mdpFlags, zOrder, isFg, dest,
419 &pipeLayerPair.rot);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700420}
421
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800422int MDPCompLowRes::pipesNeeded(hwc_context_t *ctx,
423 hwc_display_contents_1_t* list) {
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800424 const int dpy = HWC_DISPLAY_PRIMARY;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800425 return ctx->listStats[dpy].numAppLayers;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700426}
427
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800428bool MDPCompLowRes::allocLayerPipes(hwc_context_t *ctx,
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700429 hwc_display_contents_1_t* list,
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500430 FrameInfo& currentFrame) {
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800431 const int dpy = HWC_DISPLAY_PRIMARY;
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500432 overlay::Overlay& ov = *ctx->mOverlay;
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800433 int layer_count = ctx->listStats[dpy].numAppLayers;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700434
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500435 currentFrame.count = layer_count;
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500436 currentFrame.pipeLayer = (PipeLayerPair*)
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800437 malloc(sizeof(PipeLayerPair) * currentFrame.count);
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500438
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800439 if(isYuvPresent(ctx, dpy)) {
Jeykumar Sankarancf537002013-01-21 21:19:15 -0800440 int nYuvCount = ctx->listStats[dpy].yuvCount;
441
442 for(int index = 0; index < nYuvCount; index ++) {
443 int nYuvIndex = ctx->listStats[dpy].yuvIndices[index];
444 hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
445 PipeLayerPair& info = currentFrame.pipeLayer[nYuvIndex];
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800446 info.pipeInfo = new MdpPipeInfoLowRes;
Saurabh Shahacf10202013-02-26 10:15:15 -0800447 info.rot = NULL;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800448 MdpPipeInfoLowRes& pipe_info = *(MdpPipeInfoLowRes*)info.pipeInfo;
Jeykumar Sankarancf537002013-01-21 21:19:15 -0800449 pipe_info.index = getMdpPipe(ctx, MDPCOMP_OV_VG);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800450 if(pipe_info.index == ovutils::OV_INVALID) {
Jeykumar Sankarancf537002013-01-21 21:19:15 -0800451 ALOGD_IF(isDebug(), "%s: Unable to get pipe for Videos",
452 __FUNCTION__);
453 return false;
454 }
455 pipe_info.zOrder = nYuvIndex;
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500456 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500457 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700458
459 for(int index = 0 ; index < layer_count ; index++ ) {
Jeykumar Sankarancf537002013-01-21 21:19:15 -0800460 hwc_layer_1_t* layer = &list->hwLayers[index];
461 private_handle_t *hnd = (private_handle_t *)layer->handle;
462
463 if(isYuvBuffer(hnd))
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500464 continue;
465
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500466 PipeLayerPair& info = currentFrame.pipeLayer[index];
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800467 info.pipeInfo = new MdpPipeInfoLowRes;
Saurabh Shahacf10202013-02-26 10:15:15 -0800468 info.rot = NULL;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800469 MdpPipeInfoLowRes& pipe_info = *(MdpPipeInfoLowRes*)info.pipeInfo;
470
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500471 pipe_info.index = getMdpPipe(ctx, MDPCOMP_OV_ANY);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800472 if(pipe_info.index == ovutils::OV_INVALID) {
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500473 ALOGD_IF(isDebug(), "%s: Unable to get pipe for UI", __FUNCTION__);
474 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700475 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500476 pipe_info.zOrder = index;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700477 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700478 return true;
479}
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700480
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800481bool MDPCompLowRes::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700482
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500483 if(!isEnabled() || !isUsed()) {
484 ALOGD_IF(isDebug(),"%s: MDP Comp not configured", __FUNCTION__);
485 return true;
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800486 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700487
488 if(!ctx || !list) {
489 ALOGE("%s: invalid contxt or list",__FUNCTION__);
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500490 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700491 }
492
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500493 /* reset Invalidator */
494 if(idleInvalidator)
495 idleInvalidator->markForSleep();
496
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800497 const int dpy = HWC_DISPLAY_PRIMARY;
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500498 overlay::Overlay& ov = *ctx->mOverlay;
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800499 LayerProp *layerProp = ctx->layerProp[dpy];
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700500
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800501 int numHwLayers = ctx->listStats[dpy].numAppLayers;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700502 for(int i = 0; i < numHwLayers; i++ )
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700503 {
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700504 hwc_layer_1_t *layer = &list->hwLayers[i];
Saurabh Shahacf10202013-02-26 10:15:15 -0800505 private_handle_t *hnd = (private_handle_t *)layer->handle;
506 if(!hnd) {
507 ALOGE("%s handle null", __FUNCTION__);
508 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700509 }
510
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800511 MdpPipeInfoLowRes& pipe_info =
512 *(MdpPipeInfoLowRes*)mCurrentFrame.pipeLayer[i].pipeInfo;
513 ovutils::eDest dest = pipe_info.index;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800514 if(dest == ovutils::OV_INVALID) {
515 ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, dest);
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500516 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700517 }
518
Saurabh Shahacf10202013-02-26 10:15:15 -0800519 if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
520 continue;
521 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700522
Saurabh Shahacf10202013-02-26 10:15:15 -0800523 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
524 using pipe: %d", __FUNCTION__, layer,
525 hnd, dest );
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700526
Saurabh Shahacf10202013-02-26 10:15:15 -0800527 int fd = hnd->fd;
528 uint32_t offset = hnd->offset;
529 Rotator *rot = mCurrentFrame.pipeLayer[i].rot;
530 if(rot) {
531 if(!rot->queueBuffer(fd, offset))
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500532 return false;
Saurabh Shahacf10202013-02-26 10:15:15 -0800533 fd = rot->getDstMemId();
534 offset = rot->getDstOffset();
535 }
536
537 if (!ov.queueBuffer(fd, offset, dest)) {
538 ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
539 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700540 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500541
542 layerProp[i].mFlags &= ~HWC_MDPCOMP;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700543 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500544 return true;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700545}
546
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800547//=============MDPCompHighRes===================================================
548
549int MDPCompHighRes::pipesNeeded(hwc_context_t *ctx,
550 hwc_display_contents_1_t* list) {
551 const int dpy = HWC_DISPLAY_PRIMARY;
552 int numAppLayers = ctx->listStats[dpy].numAppLayers;
553 int pipesNeeded = 0;
554
555 int hw_w = ctx->dpyAttr[dpy].xres;
556
557 for(int i = 0; i < numAppLayers; ++i) {
558 hwc_layer_1_t* layer = &list->hwLayers[i];
559 hwc_rect_t dst = layer->displayFrame;
560 if(dst.left > hw_w/2) {
561 pipesNeeded++;
562 } else if(dst.right <= hw_w/2) {
563 pipesNeeded++;
564 } else {
565 pipesNeeded += 2;
566 }
567 }
568 return pipesNeeded;
569}
570
571bool MDPCompHighRes::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
572 MdpPipeInfoHighRes& pipe_info, ePipeType type) {
573 const int dpy = HWC_DISPLAY_PRIMARY;
574 int hw_w = ctx->dpyAttr[dpy].xres;
575
576 hwc_rect_t dst = layer->displayFrame;
577 if(dst.left > hw_w/2) {
578 pipe_info.lIndex = ovutils::OV_INVALID;
579 pipe_info.rIndex = getMdpPipe(ctx, type);
580 if(pipe_info.rIndex == ovutils::OV_INVALID)
581 return false;
582 } else if (dst.right <= hw_w/2) {
583 pipe_info.rIndex = ovutils::OV_INVALID;
584 pipe_info.lIndex = getMdpPipe(ctx, type);
585 if(pipe_info.lIndex == ovutils::OV_INVALID)
586 return false;
587 } else {
588 pipe_info.rIndex = getMdpPipe(ctx, type);
589 pipe_info.lIndex = getMdpPipe(ctx, type);
590 if(pipe_info.rIndex == ovutils::OV_INVALID ||
591 pipe_info.lIndex == ovutils::OV_INVALID)
592 return false;
593 }
594 return true;
595}
596
597bool MDPCompHighRes::allocLayerPipes(hwc_context_t *ctx,
598 hwc_display_contents_1_t* list,
599 FrameInfo& currentFrame) {
600 const int dpy = HWC_DISPLAY_PRIMARY;
601 overlay::Overlay& ov = *ctx->mOverlay;
602 int layer_count = ctx->listStats[dpy].numAppLayers;
603
604 currentFrame.count = layer_count;
605 currentFrame.pipeLayer = (PipeLayerPair*)
606 malloc(sizeof(PipeLayerPair) * currentFrame.count);
607
608 if(isYuvPresent(ctx, dpy)) {
609 int nYuvCount = ctx->listStats[dpy].yuvCount;
610
611 for(int index = 0; index < nYuvCount; index ++) {
612 int nYuvIndex = ctx->listStats[dpy].yuvIndices[index];
613 hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
614 PipeLayerPair& info = currentFrame.pipeLayer[nYuvIndex];
615 info.pipeInfo = new MdpPipeInfoHighRes;
616 MdpPipeInfoHighRes& pipe_info = *(MdpPipeInfoHighRes*)info.pipeInfo;
617 if(!acquireMDPPipes(ctx, layer, pipe_info,MDPCOMP_OV_VG)) {
618 ALOGD_IF(isDebug(),"%s: Unable to get pipe for videos",
619 __FUNCTION__);
620 //TODO: windback pipebook data on fail
621 return false;
622 }
623 pipe_info.zOrder = nYuvIndex;
624 }
625 }
626
627 for(int index = 0 ; index < layer_count ; index++ ) {
628 hwc_layer_1_t* layer = &list->hwLayers[index];
629 private_handle_t *hnd = (private_handle_t *)layer->handle;
630
631 if(isYuvBuffer(hnd))
632 continue;
633
634 PipeLayerPair& info = currentFrame.pipeLayer[index];
635 info.pipeInfo = new MdpPipeInfoHighRes;
636 MdpPipeInfoHighRes& pipe_info = *(MdpPipeInfoHighRes*)info.pipeInfo;
637
638 ePipeType type = MDPCOMP_OV_ANY;
639
640 if(!qhwc::needsScaling(layer) && !ctx->mDMAInUse
641 && ctx->mMDP.version >= qdutils::MDSS_V5)
642 type = MDPCOMP_OV_DMA;
643
644 if(!acquireMDPPipes(ctx, layer, pipe_info, type)) {
645 ALOGD_IF(isDebug(), "%s: Unable to get pipe for UI", __FUNCTION__);
646 //TODO: windback pipebook data on fail
647 return false;
648 }
649 pipe_info.zOrder = index;
650 }
651 return true;
652}
653/*
654 * Configures pipe(s) for MDP composition
655 */
656int MDPCompHighRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
Saurabh Shahacf10202013-02-26 10:15:15 -0800657 PipeLayerPair& pipeLayerPair) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800658 const int dpy = HWC_DISPLAY_PRIMARY;
Saurabh Shahacf10202013-02-26 10:15:15 -0800659 MdpPipeInfoHighRes& mdp_info =
660 *(static_cast<MdpPipeInfoHighRes*>(pipeLayerPair.pipeInfo));
661 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
662 eIsFg isFg = IS_FG_OFF;
663 eMdpFlags mdpFlagsL = OV_MDP_BACKEND_COMPOSITION;
664 eDest lDest = mdp_info.lIndex;
665 eDest rDest = mdp_info.rIndex;
666 return configureHighRes(ctx, layer, dpy, mdpFlagsL, zOrder, isFg, lDest,
667 rDest, &pipeLayerPair.rot);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800668}
669
670bool MDPCompHighRes::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
671
672 if(!isEnabled() || !isUsed()) {
673 ALOGD_IF(isDebug(),"%s: MDP Comp not configured", __FUNCTION__);
674 return true;
675 }
676
677 if(!ctx || !list) {
678 ALOGE("%s: invalid contxt or list",__FUNCTION__);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700679 return false;
680 }
681
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800682 /* reset Invalidator */
683 if(idleInvalidator)
684 idleInvalidator->markForSleep();
685
686 const int dpy = HWC_DISPLAY_PRIMARY;
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500687 overlay::Overlay& ov = *ctx->mOverlay;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800688 LayerProp *layerProp = ctx->layerProp[dpy];
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700689
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800690 int numHwLayers = ctx->listStats[dpy].numAppLayers;
691 for(int i = 0; i < numHwLayers; i++ )
692 {
693 hwc_layer_1_t *layer = &list->hwLayers[i];
Saurabh Shahacf10202013-02-26 10:15:15 -0800694 private_handle_t *hnd = (private_handle_t *)layer->handle;
695 if(!hnd) {
696 ALOGE("%s handle null", __FUNCTION__);
697 return false;
698 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800699
700 if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
701 continue;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700702 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700703
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800704 MdpPipeInfoHighRes& pipe_info =
705 *(MdpPipeInfoHighRes*)mCurrentFrame.pipeLayer[i].pipeInfo;
Saurabh Shahacf10202013-02-26 10:15:15 -0800706 Rotator *rot = mCurrentFrame.pipeLayer[i].rot;
707
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800708 ovutils::eDest indexL = pipe_info.lIndex;
709 ovutils::eDest indexR = pipe_info.rIndex;
Saurabh Shahacf10202013-02-26 10:15:15 -0800710 int fd = hnd->fd;
711 int offset = hnd->offset;
712
713 if(rot) {
714 rot->queueBuffer(fd, offset);
715 fd = rot->getDstMemId();
716 offset = rot->getDstOffset();
717 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700718
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800719 //************* play left mixer **********
720 if(indexL != ovutils::OV_INVALID) {
721 ovutils::eDest destL = (ovutils::eDest)indexL;
Saurabh Shahacf10202013-02-26 10:15:15 -0800722 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
723 using pipe: %d", __FUNCTION__, layer, hnd, indexL );
724 if (!ov.queueBuffer(fd, offset, destL)) {
725 ALOGE("%s: queueBuffer failed for left mixer", __FUNCTION__);
726 return false;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800727 }
728 }
729
730 //************* play right mixer **********
731 if(indexR != ovutils::OV_INVALID) {
732 ovutils::eDest destR = (ovutils::eDest)indexR;
Saurabh Shahacf10202013-02-26 10:15:15 -0800733 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
734 using pipe: %d", __FUNCTION__, layer, hnd, indexR );
735 if (!ov.queueBuffer(fd, offset, destR)) {
736 ALOGE("%s: queueBuffer failed for right mixer", __FUNCTION__);
737 return false;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800738 }
739 }
Saurabh Shahacf10202013-02-26 10:15:15 -0800740
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800741 layerProp[i].mFlags &= ~HWC_MDPCOMP;
742 }
Saurabh Shahacf10202013-02-26 10:15:15 -0800743
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800744 return true;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700745}
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700746}; //namespace
747