blob: 0fbe3097cae0ead93650441eba4a45d91baf67fd [file] [log] [blame]
Naseer Ahmed7c958d42012-07-31 18:57:03 -07001/*
Saurabh Shah56f610d2012-08-07 15:27:06 -07002 * Copyright (C) 2012, 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"
Saurabh Shah56f610d2012-08-07 15:27:06 -070020#include "external.h"
Naseer Ahmed7c958d42012-07-31 18:57:03 -070021
22#define SUPPORT_4LAYER 0
23
24namespace qhwc {
25
26/****** Class PipeMgr ***********/
27
28void inline PipeMgr::reset() {
29 mVGPipes = MAX_VG;
30 mVGUsed = 0;
31 mVGIndex = 0;
32 mRGBPipes = MAX_RGB;
33 mRGBUsed = 0;
34 mRGBIndex = MAX_VG;
35 mTotalAvail = mVGPipes + mRGBPipes;
36 memset(&mStatus, 0x0 , sizeof(int)*mTotalAvail);
37}
38
39int PipeMgr::req_for_pipe(int pipe_req) {
40
41 switch(pipe_req) {
42 case PIPE_REQ_VG: //VG
43 if(mVGPipes){
44 mVGPipes--;
45 mVGUsed++;
46 mTotalAvail--;
47 return PIPE_REQ_VG;
48 }
49 case PIPE_REQ_RGB: // RGB
50 if(mRGBPipes) {
51 mRGBPipes--;
52 mRGBUsed++;
53 mTotalAvail--;
54 return PIPE_REQ_RGB;
55 }
56 return PIPE_NONE;
57 case PIPE_REQ_FB: //FB
58 if(mRGBPipes) {
59 mRGBPipes--;
60 mRGBUsed++;
61 mTotalAvail--;
62 mStatus[VAR_INDEX] = PIPE_IN_FB_MODE;
63 return PIPE_REQ_FB;
64 }
65 default:
66 break;
67 };
68 return PIPE_NONE;
69}
70
71int PipeMgr::assign_pipe(int pipe_pref) {
72 switch(pipe_pref) {
73 case PIPE_REQ_VG: //VG
74 if(mVGUsed) {
75 mVGUsed--;
76 mStatus[mVGIndex] = PIPE_IN_COMP_MODE;
77 return mVGIndex++;
78 }
79 case PIPE_REQ_RGB: //RGB
80 if(mRGBUsed) {
81 mRGBUsed--;
82 mStatus[mRGBIndex] = PIPE_IN_COMP_MODE;
83 return mRGBIndex++;
84 }
85 default:
86 ALOGE("%s: PipeMgr:invalid case in pipe_mgr_assign",
87 __FUNCTION__);
88 return -1;
89 };
90}
91
92/****** Class MDPComp ***********/
93
94MDPComp::State MDPComp::sMDPCompState = MDPCOMP_OFF;
95struct MDPComp::frame_info MDPComp::sCurrentFrame;
96PipeMgr MDPComp::sPipeMgr;
97IdleInvalidator *MDPComp::idleInvalidator = NULL;
98bool MDPComp::sIdleFallBack = false;
99bool MDPComp::sDebugLogs = false;
100int MDPComp::sSkipCount = 0;
101int MDPComp::sMaxLayers = 0;
102
103bool MDPComp::deinit() {
104 //XXX: Tear down MDP comp state
105 return true;
106}
107
108void MDPComp::timeout_handler(void *udata) {
109 struct hwc_context_t* ctx = (struct hwc_context_t*)(udata);
110
111 if(!ctx) {
112 ALOGE("%s: received empty data in timer callback", __FUNCTION__);
113 return;
114 }
115
Jesse Hall3be78d92012-08-21 15:12:23 -0700116 if(!ctx->proc) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700117 ALOGE("%s: HWC proc not registered", __FUNCTION__);
118 return;
119 }
120 sIdleFallBack = true;
121 /* Trigger SF to redraw the current frame */
Jesse Hall3be78d92012-08-21 15:12:23 -0700122 ctx->proc->invalidate(ctx->proc);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700123}
124
Naseer Ahmedfb4cbdd2012-08-16 15:54:53 -0700125void MDPComp::reset(hwc_context_t *ctx, hwc_display_contents_1_t* list ) {
126 //Reset flags and states
127 unsetMDPCompLayerFlags(ctx, list);
128 if(sMDPCompState == MDPCOMP_ON) {
129 sMDPCompState = MDPCOMP_OFF_PENDING;
130 }
131
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700132 sCurrentFrame.count = 0;
Naseer Ahmed52ca6d22012-10-08 14:03:01 -0400133 if(sCurrentFrame.pipe_layer) {
134 free(sCurrentFrame.pipe_layer);
135 sCurrentFrame.pipe_layer = NULL;
136 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700137
138 //Reset MDP pipes
139 sPipeMgr.reset();
140 sPipeMgr.setStatus(VAR_INDEX, PIPE_IN_FB_MODE);
141
142#if SUPPORT_4LAYER
143 configure_var_pipe(ctx);
144#endif
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700145}
146
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700147void MDPComp::setLayerIndex(hwc_layer_1_t* layer, const int pipe_index)
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700148{
149 layer->flags &= ~HWC_MDPCOMP_INDEX_MASK;
150 layer->flags |= pipe_index << MDPCOMP_INDEX_OFFSET;
151}
152
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700153int MDPComp::getLayerIndex(hwc_layer_1_t* layer)
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700154{
155 int byp_index = -1;
156
157 if(layer->flags & HWC_MDPCOMP) {
158 byp_index = ((layer->flags & HWC_MDPCOMP_INDEX_MASK) >>
159 MDPCOMP_INDEX_OFFSET);
160 byp_index = (byp_index < sMaxLayers ? byp_index : -1 );
161 }
162 return byp_index;
163}
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700164void MDPComp::print_info(hwc_layer_1_t* layer)
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700165{
166 hwc_rect_t sourceCrop = layer->sourceCrop;
167 hwc_rect_t displayFrame = layer->displayFrame;
168
169 int s_l = sourceCrop.left;
170 int s_t = sourceCrop.top;
171 int s_r = sourceCrop.right;
172 int s_b = sourceCrop.bottom;
173
174 int d_l = displayFrame.left;
175 int d_t = displayFrame.top;
176 int d_r = displayFrame.right;
177 int d_b = displayFrame.bottom;
178
179 ALOGD_IF(isDebug(), "src:[%d,%d,%d,%d] (%d x %d) \
180 dst:[%d,%d,%d,%d] (%d x %d)",
181 s_l, s_t, s_r, s_b, (s_r - s_l), (s_b - s_t),
182 d_l, d_t, d_r, d_b, (d_r - d_l), (d_b - d_t));
183}
184/*
185 * Configures pipe(s) for MDP composition
186 */
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700187int MDPComp::prepare(hwc_context_t *ctx, hwc_layer_1_t *layer,
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700188 mdp_pipe_info& mdp_info) {
189
190 int nPipeIndex = mdp_info.index;
191
192 if (ctx) {
193
194 private_handle_t *hnd = (private_handle_t *)layer->handle;
195
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700196 overlay::Overlay& ov = *(ctx->mOverlay[HWC_DISPLAY_PRIMARY]);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700197
198 if(!hnd) {
199 ALOGE("%s: layer handle is NULL", __FUNCTION__);
200 return -1;
201 }
202
203
204 int hw_w = ctx->mFbDev->width;
205 int hw_h = ctx->mFbDev->height;
206
207
208 hwc_rect_t sourceCrop = layer->sourceCrop;
209 hwc_rect_t displayFrame = layer->displayFrame;
210
211 const int src_w = sourceCrop.right - sourceCrop.left;
212 const int src_h = sourceCrop.bottom - sourceCrop.top;
213
214 hwc_rect_t crop = sourceCrop;
215 int crop_w = crop.right - crop.left;
216 int crop_h = crop.bottom - crop.top;
217
218 hwc_rect_t dst = displayFrame;
219 int dst_w = dst.right - dst.left;
220 int dst_h = dst.bottom - dst.top;
221
222 //REDUNDANT ??
223 if(hnd != NULL &&
224 (hnd->flags & private_handle_t::PRIV_FLAGS_NONCONTIGUOUS_MEM )) {
225 ALOGE("%s: failed due to non-pmem memory",__FUNCTION__);
226 return -1;
227 }
228
229 if(dst.left < 0 || dst.top < 0 ||
230 dst.right > hw_w || dst.bottom > hw_h) {
231 ALOGD_IF(isDebug(),"%s: Destination has negative coordinates",
232 __FUNCTION__);
233
Saurabh Shah27c1d652012-08-14 19:30:28 -0700234 qhwc::calculate_crop_rects(crop, dst, hw_w, hw_h, 0);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700235
236 //Update calulated width and height
237 crop_w = crop.right - crop.left;
238 crop_h = crop.bottom - crop.top;
239
240 dst_w = dst.right - dst.left;
241 dst_h = dst.bottom - dst.top;
242 }
243
244 if( (dst_w > hw_w)|| (dst_h > hw_h)) {
245 ALOGD_IF(isDebug(),"%s: Dest rect exceeds FB", __FUNCTION__);
246 print_info(layer);
247 dst_w = hw_w;
248 dst_h = hw_h;
249 }
250
251 // Determine pipe to set based on pipe index
252 ovutils::eDest dest = ovutils::OV_PIPE_ALL;
253 if (nPipeIndex == 0) {
254 dest = ovutils::OV_PIPE0;
255 } else if (nPipeIndex == 1) {
256 dest = ovutils::OV_PIPE1;
257 } else if (nPipeIndex == 2) {
258 dest = ovutils::OV_PIPE2;
259 }
260
261 ovutils::eZorder zOrder = ovutils::ZORDER_0;
262
263 if(mdp_info.z_order == 0 ) {
264 zOrder = ovutils::ZORDER_0;
265 } else if(mdp_info.z_order == 1 ) {
266 zOrder = ovutils::ZORDER_1;
267 } else if(mdp_info.z_order == 2 ) {
268 zOrder = ovutils::ZORDER_2;
269 }
270
271 // Order order order
272 // setSource - just setting source
273 // setParameter - changes src w/h/f accordingly
274 // setCrop - ROI - src_rect
275 // setPosition - dst_rect
276 // commit - commit changes to mdp driver
277 // queueBuffer - not here, happens when draw is called
278
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700279 ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
280 ovutils::eMdpFlags mdpFlags = mdp_info.isVG ? ovutils::OV_MDP_PIPE_SHARE
281 : ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shah799a3972012-09-01 12:16:12 -0700282 ovutils::setMdpFlags(mdpFlags,ovutils::OV_MDP_BACKEND_COMPOSITION);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700283 ovutils::eIsFg isFG = mdp_info.isFG ? ovutils::IS_FG_SET
Saurabh Shah91a6a992012-08-20 15:25:28 -0700284 : ovutils::IS_FG_OFF;
285
286 if(layer->blending == HWC_BLENDING_PREMULT) {
287 ovutils::setMdpFlags(mdpFlags,
288 ovutils::OV_MDP_BLEND_FG_PREMULT);
289 }
290
Saurabh Shah09549f62012-10-04 13:25:44 -0700291 if(layer->transform & HAL_TRANSFORM_FLIP_H) {
292 ovutils::setMdpFlags(mdpFlags,
293 ovutils::OV_MDP_FLIP_H);
294 }
295
296 if(layer->transform & HAL_TRANSFORM_FLIP_V) {
297 ovutils::setMdpFlags(mdpFlags,
298 ovutils::OV_MDP_FLIP_V);
299 }
300
301 ov.setTransform(0, dest);
302
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700303 ovutils::PipeArgs parg(mdpFlags,
304 info,
305 zOrder,
306 isFG,
307 ovutils::ROT_FLAG_DISABLED);
308
309 ovutils::PipeArgs pargs[MAX_PIPES] = { parg, parg, parg };
310 if (!ov.setSource(pargs, dest)) {
311 ALOGE("%s: setSource failed", __FUNCTION__);
312 return -1;
313 }
314
315 ovutils::Dim dcrop(crop.left, crop.top, crop_w, crop_h);
316 if (!ov.setCrop(dcrop, dest)) {
317 ALOGE("%s: setCrop failed", __FUNCTION__);
318 return -1;
319 }
320
321 ovutils::Dim dim(dst.left, dst.top, dst_w, dst_h);
322 if (!ov.setPosition(dim, dest)) {
323 ALOGE("%s: setPosition failed", __FUNCTION__);
324 return -1;
325 }
326
327 ALOGD_IF(isDebug(),"%s: MDP set: crop[%d,%d,%d,%d] dst[%d,%d,%d,%d] \
328 nPipe: %d isFG: %d zorder: %d",__FUNCTION__, dcrop.x,
329 dcrop.y,dcrop.w, dcrop.h, dim.x, dim.y, dim.w, dim.h,
330 nPipeIndex,mdp_info.isFG, mdp_info.z_order);
331
332 if (!ov.commit(dest)) {
333 ALOGE("%s: commit failed", __FUNCTION__);
334 return -1;
335 }
336 }
337 return 0;
338}
339
340/*
341 * MDPComp not possible when
342 * 1. We have more than sMaxLayers
343 * 2. External display connected
344 * 3. Composition is triggered by
345 * Idle timer expiry
346 * 4. Rotation is needed
347 * 5. Overlay in use
348 */
349
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700350bool MDPComp::is_doable(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700351 //Number of layers
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700352 int numAppLayers = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
353 if(numAppLayers < 1 || numAppLayers > (uint32_t)sMaxLayers) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700354 ALOGD_IF(isDebug(), "%s: Unsupported number of layers",__FUNCTION__);
355 return false;
356 }
357
358 //Disable MDPComp when ext display connected
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700359 if(isExternalActive(ctx)) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700360 ALOGD_IF(isDebug(), "%s: External display connected.", __FUNCTION__);
Saurabh Shahb45b8812012-08-19 18:36:59 +0530361 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700362 }
363
364 //FB composition on idle timeout
365 if(sIdleFallBack) {
366 ALOGD_IF(isDebug(), "%s: idle fallback",__FUNCTION__);
367 return false;
368 }
369
Saurabh Shah09549f62012-10-04 13:25:44 -0700370 //MDP composition is not efficient if layer needs rotator.
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700371 for(int i = 0; i < numAppLayers; ++i) {
Saurabh Shah09549f62012-10-04 13:25:44 -0700372 // As MDP h/w supports flip operation, use MDP comp only for
373 // 180 transforms. Fail for any transform involving 90 (90, 270).
374 if(list->hwLayers[i].transform & HWC_TRANSFORM_ROT_90) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700375 ALOGD_IF(isDebug(), "%s: orientation involved",__FUNCTION__);
376 return false;
377 }
378 }
379
380 return true;
381}
382
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700383void MDPComp::setMDPCompLayerFlags(hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700384
385 for(int index = 0 ; index < sCurrentFrame.count; index++ )
386 {
387 int layer_index = sCurrentFrame.pipe_layer[index].layer_index;
388 if(layer_index >= 0) {
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700389 hwc_layer_1_t* layer = &(list->hwLayers[layer_index]);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700390
391 layer->flags |= HWC_MDPCOMP;
392 layer->compositionType = HWC_OVERLAY;
393 layer->hints |= HWC_HINT_CLEAR_FB;
394 }
395 }
396}
397
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700398void MDPComp::get_layer_info(hwc_layer_1_t* layer, int& flags) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700399
400 private_handle_t* hnd = (private_handle_t*)layer->handle;
401
402 if(layer->flags & HWC_SKIP_LAYER) {
403 flags |= MDPCOMP_LAYER_SKIP;
404 } else if(hnd != NULL &&
405 (hnd->flags & private_handle_t::PRIV_FLAGS_NONCONTIGUOUS_MEM )) {
406 flags |= MDPCOMP_LAYER_UNSUPPORTED_MEM;
407 }
408
409 if(layer->blending != HWC_BLENDING_NONE)
410 flags |= MDPCOMP_LAYER_BLEND;
411
412 int dst_w, dst_h;
413 getLayerResolution(layer, dst_w, dst_h);
414
415 hwc_rect_t sourceCrop = layer->sourceCrop;
416 const int src_w = sourceCrop.right - sourceCrop.left;
417 const int src_h = sourceCrop.bottom - sourceCrop.top;
418 if(((src_w > dst_w) || (src_h > dst_h))) {
419 flags |= MDPCOMP_LAYER_DOWNSCALE;
420 }
421}
422
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700423int MDPComp::mark_layers(hwc_context_t *ctx,
424 hwc_display_contents_1_t* list, layer_mdp_info* layer_info,
425 frame_info& current_frame) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700426
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700427 int layer_count = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700428
429 if(layer_count > sMaxLayers) {
430 if(!sPipeMgr.req_for_pipe(PIPE_REQ_FB)) {
431 ALOGE("%s: binding var pipe to FB failed!!", __FUNCTION__);
432 return 0;
433 }
434 }
435
436 //Parse layers from higher z-order
437 for(int index = layer_count - 1 ; index >= 0; index-- ) {
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700438 hwc_layer_1_t* layer = &list->hwLayers[index];
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700439
440 int layer_prop = 0;
441 get_layer_info(layer, layer_prop);
442
443 ALOGD_IF(isDebug(),"%s: prop for layer [%d]: %x", __FUNCTION__,
444 index, layer_prop);
445
446 //Both in cases of NON-CONTIGUOUS memory or SKIP layer,
447 //current version of mdp composition falls back completely to FB
448 //composition.
449 //TO DO: Support dual mode composition
450
451 if(layer_prop & MDPCOMP_LAYER_UNSUPPORTED_MEM) {
452 ALOGD_IF(isDebug(), "%s: Non contigous memory",__FUNCTION__);
453 return MDPCOMP_ABORT;
454 }
455
456 if(layer_prop & MDPCOMP_LAYER_SKIP) {
457 ALOGD_IF(isDebug(), "%s:skip layer",__FUNCTION__);
458 return MDPCOMP_ABORT;
459 }
460
461 //Request for MDP pipes
462 int pipe_pref = PIPE_REQ_VG;
463
464 if((layer_prop & MDPCOMP_LAYER_DOWNSCALE) &&
465 (layer_prop & MDPCOMP_LAYER_BLEND)) {
466 pipe_pref = PIPE_REQ_RGB;
467 }
468
469 int allocated_pipe = sPipeMgr.req_for_pipe( pipe_pref);
470 if(allocated_pipe) {
471 layer_info[index].can_use_mdp = true;
472 layer_info[index].pipe_pref = allocated_pipe;
473 current_frame.count++;
474 }else {
475 ALOGE("%s: pipe marking in mark layer fails for : %d",
476 __FUNCTION__, allocated_pipe);
477 return MDPCOMP_FAILURE;
478 }
479 }
480 return MDPCOMP_SUCCESS;
481}
482
483void MDPComp::reset_layer_mdp_info(layer_mdp_info* layer_info, int count) {
484 for(int i = 0 ; i < count; i++ ) {
485 layer_info[i].can_use_mdp = false;
486 layer_info[i].pipe_pref = PIPE_NONE;
487 }
488}
489
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700490bool MDPComp::alloc_layer_pipes(hwc_context_t *ctx,
491 hwc_display_contents_1_t* list,
492 layer_mdp_info* layer_info, frame_info& current_frame) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700493
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700494 int layer_count = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700495 int mdp_count = current_frame.count;
496 int fallback_count = layer_count - mdp_count;
497 int frame_pipe_count = 0;
498
499 ALOGD_IF(isDebug(), "%s: dual mode: %d total count: %d \
500 mdp count: %d fallback count: %d",
501 __FUNCTION__, (layer_count != mdp_count),
502 layer_count, mdp_count, fallback_count);
503
504 for(int index = 0 ; index < layer_count ; index++ ) {
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700505 hwc_layer_1_t* layer = &list->hwLayers[index];
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700506
507 if(layer_info[index].can_use_mdp) {
508 pipe_layer_pair& info = current_frame.pipe_layer[frame_pipe_count];
509 mdp_pipe_info& pipe_info = info.pipe_index;
510
511 pipe_info.index = sPipeMgr.assign_pipe(layer_info[index].pipe_pref);
512 pipe_info.isVG = (layer_info[index].pipe_pref == PIPE_REQ_VG);
513 pipe_info.isFG = (frame_pipe_count == 0);
514 /* if VAR pipe is attached to FB, FB will be updated with
515 VSYNC WAIT flag, so no need to set VSYNC WAIT for any
516 bypass pipes. if not, set VSYNC WAIT to the last updating pipe*/
517 pipe_info.vsync_wait =
518 (sPipeMgr.getStatus(VAR_INDEX) == PIPE_IN_FB_MODE) ? false:
519 (frame_pipe_count == (mdp_count - 1));
520 /* All the layers composed on FB will have MDP zorder 0, so start
521 assigning from 1*/
522 pipe_info.z_order = index -
523 (fallback_count ? fallback_count - 1 : fallback_count);
524
525 info.layer_index = index;
526 frame_pipe_count++;
527 }
528 }
529 return 1;
530}
531
532//returns array of layers and their allocated pipes
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700533bool MDPComp::parse_and_allocate(hwc_context_t* ctx,
534 hwc_display_contents_1_t* list, frame_info& current_frame ) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700535
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700536 int layer_count = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700537
538 /* clear pipe status */
539 sPipeMgr.reset();
540
541 layer_mdp_info* bp_layer_info = (layer_mdp_info*)
542 malloc(sizeof(layer_mdp_info)* layer_count);
543
544 reset_layer_mdp_info(bp_layer_info, layer_count);
545
546 /* iterate through layer list to mark candidate */
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700547 if(mark_layers(ctx, list, bp_layer_info, current_frame) == MDPCOMP_ABORT) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700548 free(bp_layer_info);
549 current_frame.count = 0;
550 ALOGE_IF(isDebug(), "%s:mark_layers failed!!", __FUNCTION__);
551 return false;
552 }
553 current_frame.pipe_layer = (pipe_layer_pair*)
554 malloc(sizeof(pipe_layer_pair) * current_frame.count);
555
556 /* allocate MDP pipes for marked layers */
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700557 alloc_layer_pipes(ctx, list, bp_layer_info, current_frame);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700558
559 free(bp_layer_info);
560 return true;
561}
562#if SUPPORT_4LAYER
563int MDPComp::configure_var_pipe(hwc_context_t* ctx) {
564
565 if(!ctx) {
566 ALOGE("%s: invalid context", __FUNCTION__);
567 return -1;
568 }
569
570 framebuffer_device_t *fbDev = ctx->fbDev;
571 if (!fbDev) {
572 ALOGE("%s: fbDev is NULL", __FUNCTION__);
573 return -1;
574 }
575
576 int new_mode = -1, cur_mode;
577 fbDev->perform(fbDev,EVENT_GET_VAR_PIPE_MODE, (void*)&cur_mode);
578
579 if(sPipeMgr.getStatus(VAR_INDEX) == PIPE_IN_FB_MODE) {
580 new_mode = VAR_PIPE_FB_ATTACH;
581 } else if(sPipeMgr.getStatus(VAR_INDEX) == PIPE_IN_BYP_MODE) {
582 new_mode = VAR_PIPE_FB_DETACH;
583 fbDev->perform(fbDev,EVENT_WAIT_POSTBUFFER,NULL);
584 }
585
586 ALOGD_IF(isDebug(),"%s: old_mode: %d new_mode: %d", __FUNCTION__,
587 cur_mode, new_mode);
588
589 if((new_mode != cur_mode) && (new_mode >= 0)) {
590 if(fbDev->perform(fbDev,EVENT_SET_VAR_PIPE_MODE,(void*)&new_mode) < 0) {
591 ALOGE("%s: Setting var pipe mode failed", __FUNCTION__);
592 }
593 }
594
595 return 0;
596}
597#endif
598
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700599bool MDPComp::setup(hwc_context_t* ctx, hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700600 int nPipeIndex, vsync_wait, isFG;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700601 int numHwLayers = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700602
603 frame_info &current_frame = sCurrentFrame;
604 current_frame.count = 0;
605
Naseer Ahmed52ca6d22012-10-08 14:03:01 -0400606 if(current_frame.pipe_layer) {
607 free(current_frame.pipe_layer);
608 current_frame.pipe_layer = NULL;
609 }
610
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700611 if(!ctx) {
612 ALOGE("%s: invalid context", __FUNCTION__);
613 return -1;
614 }
615
616 framebuffer_device_t *fbDev = ctx->mFbDev;
617 if (!fbDev) {
618 ALOGE("%s: fbDev is NULL", __FUNCTION__);
619 return -1;
620 }
621
622 if(!parse_and_allocate(ctx, list, current_frame)) {
623#if SUPPORT_4LAYER
624 int mode = VAR_PIPE_FB_ATTACH;
625 if(fbDev->perform(fbDev,EVENT_SET_VAR_PIPE_MODE,(void*)&mode) < 0 ) {
626 ALOGE("%s: setting var pipe mode failed", __FUNCTION__);
627 }
628#endif
629 ALOGD_IF(isDebug(), "%s: Falling back to FB", __FUNCTION__);
630 return false;
631 }
632#if SUPPORT_4LAYER
633 configure_var_pipe(ctx);
634#endif
635
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700636 overlay::Overlay& ov = *(ctx->mOverlay[HWC_DISPLAY_PRIMARY]);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700637 ovutils::eOverlayState state = ov.getState();
638
639 if (current_frame.count == 1) {
640 state = ovutils::OV_BYPASS_1_LAYER;
641 } else if (current_frame.count == 2) {
642 state = ovutils::OV_BYPASS_2_LAYER;
643 } else if (current_frame.count == 3) {
644 state = ovutils::OV_BYPASS_3_LAYER;
645 }
646
647 ov.setState(state);
648
649
650 for (int index = 0 ; index < current_frame.count; index++) {
651 int layer_index = current_frame.pipe_layer[index].layer_index;
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700652 hwc_layer_1_t* layer = &list->hwLayers[layer_index];
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700653 mdp_pipe_info& cur_pipe = current_frame.pipe_layer[index].pipe_index;
654
655 if( prepare(ctx, layer, cur_pipe) != 0 ) {
656 ALOGD_IF(isDebug(), "%s: MDPComp failed to configure overlay for \
657 layer %d with pipe index:%d",__FUNCTION__,
658 index, cur_pipe.index);
659 return false;
660 } else {
661 setLayerIndex(layer, index);
662 }
663 }
664 return true;
665}
666
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700667void MDPComp::unsetMDPCompLayerFlags(hwc_context_t* ctx, hwc_display_contents_1_t* list)
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700668{
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700669 for (int index = 0 ; index < sCurrentFrame.count; index++) {
670 int l_index = sCurrentFrame.pipe_layer[index].layer_index;
671 if(list->hwLayers[l_index].flags & HWC_MDPCOMP) {
672 list->hwLayers[l_index].flags &= ~HWC_MDPCOMP;
673 }
Naseer Ahmedfb4cbdd2012-08-16 15:54:53 -0700674
675 if(list->hwLayers[l_index].compositionType == HWC_OVERLAY) {
676 list->hwLayers[l_index].compositionType = HWC_FRAMEBUFFER;
677 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700678 }
679}
680
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700681int MDPComp::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700682
683 if(!isEnabled()) {
684 ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled",__FUNCTION__);
685 return 0;
686 }
687
688 if(!ctx || !list) {
689 ALOGE("%s: invalid contxt or list",__FUNCTION__);
690 return -1;
691 }
692
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700693 overlay::Overlay& ov = *(ctx->mOverlay[HWC_DISPLAY_PRIMARY]);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700694
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700695 int numHwLayers = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
696 for(int i = 0; i < numHwLayers; i++ )
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700697 {
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700698 hwc_layer_1_t *layer = &list->hwLayers[i];
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700699
700 if(!(layer->flags & HWC_MDPCOMP)) {
701 ALOGD_IF(isDebug(), "%s: Layer Not flagged for MDP comp",
702 __FUNCTION__);
703 continue;
704 }
705
706 int data_index = getLayerIndex(layer);
707 mdp_pipe_info& pipe_info =
708 sCurrentFrame.pipe_layer[data_index].pipe_index;
709 int index = pipe_info.index;
710
711 if(index < 0) {
712 ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, index);
713 return -1;
714 }
715
716 /* reset Invalidator */
717 if(idleInvalidator)
Saurabh Shah09549f62012-10-04 13:25:44 -0700718 idleInvalidator->markForSleep();
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700719
720 ovutils::eDest dest;
721
722 if (index == 0) {
723 dest = ovutils::OV_PIPE0;
724 } else if (index == 1) {
725 dest = ovutils::OV_PIPE1;
726 } else if (index == 2) {
727 dest = ovutils::OV_PIPE2;
728 }
729
730 if (ctx ) {
731 private_handle_t *hnd = (private_handle_t *)layer->handle;
732 if(!hnd) {
733 ALOGE("%s handle null", __FUNCTION__);
734 return -1;
735 }
736
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700737 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
738 using pipe: %d", __FUNCTION__, layer,
739 hnd, index );
740
741 if (!ov.queueBuffer(hnd->fd, hnd->offset, dest)) {
742 ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
743 return -1;
744 }
745 }
746 layer->flags &= ~HWC_MDPCOMP;
747 layer->flags |= HWC_MDPCOMP_INDEX_MASK;
748 }
749 return 0;
750}
751
752bool MDPComp::init(hwc_context_t *dev) {
753
754 if(!dev) {
755 ALOGE("%s: Invalid hwc context!!",__FUNCTION__);
756 return false;
757 }
758
759#if SUPPORT_4LAYER
760 if(MAX_MDPCOMP_LAYERS > MAX_STATIC_PIPES) {
761 framebuffer_device_t *fbDev = dev->fbDevice;
762 if(fbDev == NULL) {
763 ALOGE("%s: FATAL: framebuffer device is NULL", __FUNCTION__);
764 return false;
765 }
766
767 //Receive VAR pipe object from framebuffer
768 if(fbDev->perform(fbDev,EVENT_GET_VAR_PIPE,(void*)&ov) < 0) {
769 ALOGE("%s: FATAL: getVariablePipe failed!!", __FUNCTION__);
770 return false;
771 }
772
773 sPipeMgr.setStatus(VAR_INDEX, PIPE_IN_FB_MODE);
774 }
775#endif
776 char property[PROPERTY_VALUE_MAX];
777
778 sMaxLayers = 0;
779 if(property_get("debug.mdpcomp.maxlayer", property, NULL) > 0) {
780 if(atoi(property) != 0)
781 sMaxLayers = atoi(property);
782 }
783
784 sDebugLogs = false;
785 if(property_get("debug.mdpcomp.logs", property, NULL) > 0) {
786 if(atoi(property) != 0)
787 sDebugLogs = true;
788 }
789
790 unsigned long idle_timeout = DEFAULT_IDLE_TIME;
791 if(property_get("debug.mdpcomp.idletime", property, NULL) > 0) {
792 if(atoi(property) != 0)
793 idle_timeout = atoi(property);
794 }
795
796 //create Idle Invalidator
797 idleInvalidator = IdleInvalidator::getInstance();
798
799 if(idleInvalidator == NULL) {
800 ALOGE("%s: failed to instantiate idleInvalidator object", __FUNCTION__);
801 } else {
802 idleInvalidator->init(timeout_handler, dev, idle_timeout);
803 }
804 return true;
805}
806
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700807bool MDPComp::configure(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700808
809 if(!isEnabled()) {
810 ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
811 return false;
812 }
813
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700814 bool isMDPCompUsed = true;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700815 bool doable = is_doable(ctx, list);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700816
817 if(doable) {
818 if(setup(ctx, list)) {
819 setMDPCompLayerFlags(list);
820 sMDPCompState = MDPCOMP_ON;
821 } else {
822 ALOGD_IF(isDebug(),"%s: MDP Comp Failed",__FUNCTION__);
823 isMDPCompUsed = false;
824 }
825 } else {
826 ALOGD_IF( isDebug(),"%s: MDP Comp not possible[%d]",__FUNCTION__,
827 doable);
828 isMDPCompUsed = false;
829 }
830
831 //Reset states
832 if(!isMDPCompUsed) {
833 //Reset current frame
834 reset(ctx, list);
835 }
836
837 sIdleFallBack = false;
838
839 return isMDPCompUsed;
840}
841}; //namespace
842