blob: 7eaea7f8636a1a9c67285f06106c239e610ba04e [file] [log] [blame]
Naseer Ahmed7c958d42012-07-31 18:57:03 -07001/*
2 * Copyright (C) 2012, Code Aurora Forum. All rights reserved.
3 * 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"
20#include "hwc_qbuf.h"
21#include "hwc_external.h"
22
23#define SUPPORT_4LAYER 0
24
25namespace qhwc {
26
27/****** Class PipeMgr ***********/
28
29void inline PipeMgr::reset() {
30 mVGPipes = MAX_VG;
31 mVGUsed = 0;
32 mVGIndex = 0;
33 mRGBPipes = MAX_RGB;
34 mRGBUsed = 0;
35 mRGBIndex = MAX_VG;
36 mTotalAvail = mVGPipes + mRGBPipes;
37 memset(&mStatus, 0x0 , sizeof(int)*mTotalAvail);
38}
39
40int PipeMgr::req_for_pipe(int pipe_req) {
41
42 switch(pipe_req) {
43 case PIPE_REQ_VG: //VG
44 if(mVGPipes){
45 mVGPipes--;
46 mVGUsed++;
47 mTotalAvail--;
48 return PIPE_REQ_VG;
49 }
50 case PIPE_REQ_RGB: // RGB
51 if(mRGBPipes) {
52 mRGBPipes--;
53 mRGBUsed++;
54 mTotalAvail--;
55 return PIPE_REQ_RGB;
56 }
57 return PIPE_NONE;
58 case PIPE_REQ_FB: //FB
59 if(mRGBPipes) {
60 mRGBPipes--;
61 mRGBUsed++;
62 mTotalAvail--;
63 mStatus[VAR_INDEX] = PIPE_IN_FB_MODE;
64 return PIPE_REQ_FB;
65 }
66 default:
67 break;
68 };
69 return PIPE_NONE;
70}
71
72int PipeMgr::assign_pipe(int pipe_pref) {
73 switch(pipe_pref) {
74 case PIPE_REQ_VG: //VG
75 if(mVGUsed) {
76 mVGUsed--;
77 mStatus[mVGIndex] = PIPE_IN_COMP_MODE;
78 return mVGIndex++;
79 }
80 case PIPE_REQ_RGB: //RGB
81 if(mRGBUsed) {
82 mRGBUsed--;
83 mStatus[mRGBIndex] = PIPE_IN_COMP_MODE;
84 return mRGBIndex++;
85 }
86 default:
87 ALOGE("%s: PipeMgr:invalid case in pipe_mgr_assign",
88 __FUNCTION__);
89 return -1;
90 };
91}
92
93/****** Class MDPComp ***********/
94
95MDPComp::State MDPComp::sMDPCompState = MDPCOMP_OFF;
96struct MDPComp::frame_info MDPComp::sCurrentFrame;
97PipeMgr MDPComp::sPipeMgr;
98IdleInvalidator *MDPComp::idleInvalidator = NULL;
99bool MDPComp::sIdleFallBack = false;
100bool MDPComp::sDebugLogs = false;
101int MDPComp::sSkipCount = 0;
102int MDPComp::sMaxLayers = 0;
103
104bool MDPComp::deinit() {
105 //XXX: Tear down MDP comp state
106 return true;
107}
108
109void MDPComp::timeout_handler(void *udata) {
110 struct hwc_context_t* ctx = (struct hwc_context_t*)(udata);
111
112 if(!ctx) {
113 ALOGE("%s: received empty data in timer callback", __FUNCTION__);
114 return;
115 }
116
Jesse Hall3be78d92012-08-21 15:12:23 -0700117 if(!ctx->proc) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700118 ALOGE("%s: HWC proc not registered", __FUNCTION__);
119 return;
120 }
121 sIdleFallBack = true;
122 /* Trigger SF to redraw the current frame */
Jesse Hall3be78d92012-08-21 15:12:23 -0700123 ctx->proc->invalidate(ctx->proc);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700124}
125
Naseer Ahmedfb4cbdd2012-08-16 15:54:53 -0700126void MDPComp::reset(hwc_context_t *ctx, hwc_display_contents_1_t* list ) {
127 //Reset flags and states
128 unsetMDPCompLayerFlags(ctx, list);
129 if(sMDPCompState == MDPCOMP_ON) {
130 sMDPCompState = MDPCOMP_OFF_PENDING;
131 }
132
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700133 sCurrentFrame.count = 0;
134 free(sCurrentFrame.pipe_layer);
135 sCurrentFrame.pipe_layer = NULL;
136
137 //Reset MDP pipes
138 sPipeMgr.reset();
139 sPipeMgr.setStatus(VAR_INDEX, PIPE_IN_FB_MODE);
140
141#if SUPPORT_4LAYER
142 configure_var_pipe(ctx);
143#endif
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700144}
145
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700146void MDPComp::setLayerIndex(hwc_layer_1_t* layer, const int pipe_index)
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700147{
148 layer->flags &= ~HWC_MDPCOMP_INDEX_MASK;
149 layer->flags |= pipe_index << MDPCOMP_INDEX_OFFSET;
150}
151
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700152int MDPComp::getLayerIndex(hwc_layer_1_t* layer)
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700153{
154 int byp_index = -1;
155
156 if(layer->flags & HWC_MDPCOMP) {
157 byp_index = ((layer->flags & HWC_MDPCOMP_INDEX_MASK) >>
158 MDPCOMP_INDEX_OFFSET);
159 byp_index = (byp_index < sMaxLayers ? byp_index : -1 );
160 }
161 return byp_index;
162}
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700163void MDPComp::print_info(hwc_layer_1_t* layer)
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700164{
165 hwc_rect_t sourceCrop = layer->sourceCrop;
166 hwc_rect_t displayFrame = layer->displayFrame;
167
168 int s_l = sourceCrop.left;
169 int s_t = sourceCrop.top;
170 int s_r = sourceCrop.right;
171 int s_b = sourceCrop.bottom;
172
173 int d_l = displayFrame.left;
174 int d_t = displayFrame.top;
175 int d_r = displayFrame.right;
176 int d_b = displayFrame.bottom;
177
178 ALOGD_IF(isDebug(), "src:[%d,%d,%d,%d] (%d x %d) \
179 dst:[%d,%d,%d,%d] (%d x %d)",
180 s_l, s_t, s_r, s_b, (s_r - s_l), (s_b - s_t),
181 d_l, d_t, d_r, d_b, (d_r - d_l), (d_b - d_t));
182}
183/*
184 * Configures pipe(s) for MDP composition
185 */
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700186int MDPComp::prepare(hwc_context_t *ctx, hwc_layer_1_t *layer,
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700187 mdp_pipe_info& mdp_info) {
188
189 int nPipeIndex = mdp_info.index;
190
191 if (ctx) {
192
193 private_handle_t *hnd = (private_handle_t *)layer->handle;
194
195 overlay::Overlay& ov = *(ctx->mOverlay);
196
197 if(!hnd) {
198 ALOGE("%s: layer handle is NULL", __FUNCTION__);
199 return -1;
200 }
201
202
203 int hw_w = ctx->mFbDev->width;
204 int hw_h = ctx->mFbDev->height;
205
206
207 hwc_rect_t sourceCrop = layer->sourceCrop;
208 hwc_rect_t displayFrame = layer->displayFrame;
209
210 const int src_w = sourceCrop.right - sourceCrop.left;
211 const int src_h = sourceCrop.bottom - sourceCrop.top;
212
213 hwc_rect_t crop = sourceCrop;
214 int crop_w = crop.right - crop.left;
215 int crop_h = crop.bottom - crop.top;
216
217 hwc_rect_t dst = displayFrame;
218 int dst_w = dst.right - dst.left;
219 int dst_h = dst.bottom - dst.top;
220
221 //REDUNDANT ??
222 if(hnd != NULL &&
223 (hnd->flags & private_handle_t::PRIV_FLAGS_NONCONTIGUOUS_MEM )) {
224 ALOGE("%s: failed due to non-pmem memory",__FUNCTION__);
225 return -1;
226 }
227
228 if(dst.left < 0 || dst.top < 0 ||
229 dst.right > hw_w || dst.bottom > hw_h) {
230 ALOGD_IF(isDebug(),"%s: Destination has negative coordinates",
231 __FUNCTION__);
232
233 qhwc::calculate_crop_rects(crop, dst, hw_w, hw_h);
234
235 //Update calulated width and height
236 crop_w = crop.right - crop.left;
237 crop_h = crop.bottom - crop.top;
238
239 dst_w = dst.right - dst.left;
240 dst_h = dst.bottom - dst.top;
241 }
242
243 if( (dst_w > hw_w)|| (dst_h > hw_h)) {
244 ALOGD_IF(isDebug(),"%s: Dest rect exceeds FB", __FUNCTION__);
245 print_info(layer);
246 dst_w = hw_w;
247 dst_h = hw_h;
248 }
249
250 // Determine pipe to set based on pipe index
251 ovutils::eDest dest = ovutils::OV_PIPE_ALL;
252 if (nPipeIndex == 0) {
253 dest = ovutils::OV_PIPE0;
254 } else if (nPipeIndex == 1) {
255 dest = ovutils::OV_PIPE1;
256 } else if (nPipeIndex == 2) {
257 dest = ovutils::OV_PIPE2;
258 }
259
260 ovutils::eZorder zOrder = ovutils::ZORDER_0;
261
262 if(mdp_info.z_order == 0 ) {
263 zOrder = ovutils::ZORDER_0;
264 } else if(mdp_info.z_order == 1 ) {
265 zOrder = ovutils::ZORDER_1;
266 } else if(mdp_info.z_order == 2 ) {
267 zOrder = ovutils::ZORDER_2;
268 }
269
270 // Order order order
271 // setSource - just setting source
272 // setParameter - changes src w/h/f accordingly
273 // setCrop - ROI - src_rect
274 // setPosition - dst_rect
275 // commit - commit changes to mdp driver
276 // queueBuffer - not here, happens when draw is called
277
278 ovutils::eTransform orient =
279 static_cast<ovutils::eTransform>(layer->transform);
280
281 ov.setTransform(orient, dest);
282 ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
283 ovutils::eMdpFlags mdpFlags = mdp_info.isVG ? ovutils::OV_MDP_PIPE_SHARE
284 : ovutils::OV_MDP_FLAGS_NONE;
285 ovutils::eIsFg isFG = mdp_info.isFG ? ovutils::IS_FG_SET
286 : ovutils::IS_FG_OFF;
287 ovutils::PipeArgs parg(mdpFlags,
288 info,
289 zOrder,
290 isFG,
291 ovutils::ROT_FLAG_DISABLED);
292
293 ovutils::PipeArgs pargs[MAX_PIPES] = { parg, parg, parg };
294 if (!ov.setSource(pargs, dest)) {
295 ALOGE("%s: setSource failed", __FUNCTION__);
296 return -1;
297 }
298
299 ovutils::Dim dcrop(crop.left, crop.top, crop_w, crop_h);
300 if (!ov.setCrop(dcrop, dest)) {
301 ALOGE("%s: setCrop failed", __FUNCTION__);
302 return -1;
303 }
304
305 ovutils::Dim dim(dst.left, dst.top, dst_w, dst_h);
306 if (!ov.setPosition(dim, dest)) {
307 ALOGE("%s: setPosition failed", __FUNCTION__);
308 return -1;
309 }
310
311 ALOGD_IF(isDebug(),"%s: MDP set: crop[%d,%d,%d,%d] dst[%d,%d,%d,%d] \
312 nPipe: %d isFG: %d zorder: %d",__FUNCTION__, dcrop.x,
313 dcrop.y,dcrop.w, dcrop.h, dim.x, dim.y, dim.w, dim.h,
314 nPipeIndex,mdp_info.isFG, mdp_info.z_order);
315
316 if (!ov.commit(dest)) {
317 ALOGE("%s: commit failed", __FUNCTION__);
318 return -1;
319 }
320 }
321 return 0;
322}
323
324/*
325 * MDPComp not possible when
326 * 1. We have more than sMaxLayers
327 * 2. External display connected
328 * 3. Composition is triggered by
329 * Idle timer expiry
330 * 4. Rotation is needed
331 * 5. Overlay in use
332 */
333
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700334bool MDPComp::is_doable(hwc_composer_device_1_t *dev,
Naseer Ahmedfb4cbdd2012-08-16 15:54:53 -0700335 hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700336 hwc_context_t* ctx = (hwc_context_t*)(dev);
337
338 if(!ctx) {
339 ALOGE("%s: hwc context is NULL", __FUNCTION__);
340 return false;
341 }
342
343 //Number of layers
Naseer Ahmedb90d0912012-07-31 13:09:51 -0700344 if(list->numHwLayers < 1 || list->numHwLayers > (uint32_t)sMaxLayers) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700345 ALOGD_IF(isDebug(), "%s: Unsupported number of layers",__FUNCTION__);
346 return false;
347 }
348
349 //Disable MDPComp when ext display connected
350 if(ctx->mExtDisplay->getExternalDisplay()) {
351 ALOGD_IF(isDebug(), "%s: External display connected.", __FUNCTION__);
Saurabh Shahb45b8812012-08-19 18:36:59 +0530352 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700353 }
354
355 //FB composition on idle timeout
356 if(sIdleFallBack) {
357 ALOGD_IF(isDebug(), "%s: idle fallback",__FUNCTION__);
358 return false;
359 }
360
361 //MDP composition is not efficient if rotation is needed.
362 for(unsigned int i = 0; i < list->numHwLayers; ++i) {
363 if(list->hwLayers[i].transform) {
364 ALOGD_IF(isDebug(), "%s: orientation involved",__FUNCTION__);
365 return false;
366 }
367 }
368
369 return true;
370}
371
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700372void MDPComp::setMDPCompLayerFlags(hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700373
374 for(int index = 0 ; index < sCurrentFrame.count; index++ )
375 {
376 int layer_index = sCurrentFrame.pipe_layer[index].layer_index;
377 if(layer_index >= 0) {
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700378 hwc_layer_1_t* layer = &(list->hwLayers[layer_index]);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700379
380 layer->flags |= HWC_MDPCOMP;
381 layer->compositionType = HWC_OVERLAY;
382 layer->hints |= HWC_HINT_CLEAR_FB;
383 }
384 }
385}
386
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700387void MDPComp::get_layer_info(hwc_layer_1_t* layer, int& flags) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700388
389 private_handle_t* hnd = (private_handle_t*)layer->handle;
390
391 if(layer->flags & HWC_SKIP_LAYER) {
392 flags |= MDPCOMP_LAYER_SKIP;
393 } else if(hnd != NULL &&
394 (hnd->flags & private_handle_t::PRIV_FLAGS_NONCONTIGUOUS_MEM )) {
395 flags |= MDPCOMP_LAYER_UNSUPPORTED_MEM;
396 }
397
398 if(layer->blending != HWC_BLENDING_NONE)
399 flags |= MDPCOMP_LAYER_BLEND;
400
401 int dst_w, dst_h;
402 getLayerResolution(layer, dst_w, dst_h);
403
404 hwc_rect_t sourceCrop = layer->sourceCrop;
405 const int src_w = sourceCrop.right - sourceCrop.left;
406 const int src_h = sourceCrop.bottom - sourceCrop.top;
407 if(((src_w > dst_w) || (src_h > dst_h))) {
408 flags |= MDPCOMP_LAYER_DOWNSCALE;
409 }
410}
411
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700412int MDPComp::mark_layers(hwc_display_contents_1_t* list, layer_mdp_info* layer_info,
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700413 frame_info& current_frame) {
414
415 int layer_count = list->numHwLayers;
416
417 if(layer_count > sMaxLayers) {
418 if(!sPipeMgr.req_for_pipe(PIPE_REQ_FB)) {
419 ALOGE("%s: binding var pipe to FB failed!!", __FUNCTION__);
420 return 0;
421 }
422 }
423
424 //Parse layers from higher z-order
425 for(int index = layer_count - 1 ; index >= 0; index-- ) {
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700426 hwc_layer_1_t* layer = &list->hwLayers[index];
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700427
428 int layer_prop = 0;
429 get_layer_info(layer, layer_prop);
430
431 ALOGD_IF(isDebug(),"%s: prop for layer [%d]: %x", __FUNCTION__,
432 index, layer_prop);
433
434 //Both in cases of NON-CONTIGUOUS memory or SKIP layer,
435 //current version of mdp composition falls back completely to FB
436 //composition.
437 //TO DO: Support dual mode composition
438
439 if(layer_prop & MDPCOMP_LAYER_UNSUPPORTED_MEM) {
440 ALOGD_IF(isDebug(), "%s: Non contigous memory",__FUNCTION__);
441 return MDPCOMP_ABORT;
442 }
443
444 if(layer_prop & MDPCOMP_LAYER_SKIP) {
445 ALOGD_IF(isDebug(), "%s:skip layer",__FUNCTION__);
446 return MDPCOMP_ABORT;
447 }
448
449 //Request for MDP pipes
450 int pipe_pref = PIPE_REQ_VG;
451
452 if((layer_prop & MDPCOMP_LAYER_DOWNSCALE) &&
453 (layer_prop & MDPCOMP_LAYER_BLEND)) {
454 pipe_pref = PIPE_REQ_RGB;
455 }
456
457 int allocated_pipe = sPipeMgr.req_for_pipe( pipe_pref);
458 if(allocated_pipe) {
459 layer_info[index].can_use_mdp = true;
460 layer_info[index].pipe_pref = allocated_pipe;
461 current_frame.count++;
462 }else {
463 ALOGE("%s: pipe marking in mark layer fails for : %d",
464 __FUNCTION__, allocated_pipe);
465 return MDPCOMP_FAILURE;
466 }
467 }
468 return MDPCOMP_SUCCESS;
469}
470
471void MDPComp::reset_layer_mdp_info(layer_mdp_info* layer_info, int count) {
472 for(int i = 0 ; i < count; i++ ) {
473 layer_info[i].can_use_mdp = false;
474 layer_info[i].pipe_pref = PIPE_NONE;
475 }
476}
477
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700478bool MDPComp::alloc_layer_pipes(hwc_display_contents_1_t* list,
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700479 layer_mdp_info* layer_info, frame_info& current_frame) {
480
481 int layer_count = list->numHwLayers;
482 int mdp_count = current_frame.count;
483 int fallback_count = layer_count - mdp_count;
484 int frame_pipe_count = 0;
485
486 ALOGD_IF(isDebug(), "%s: dual mode: %d total count: %d \
487 mdp count: %d fallback count: %d",
488 __FUNCTION__, (layer_count != mdp_count),
489 layer_count, mdp_count, fallback_count);
490
491 for(int index = 0 ; index < layer_count ; index++ ) {
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700492 hwc_layer_1_t* layer = &list->hwLayers[index];
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700493
494 if(layer_info[index].can_use_mdp) {
495 pipe_layer_pair& info = current_frame.pipe_layer[frame_pipe_count];
496 mdp_pipe_info& pipe_info = info.pipe_index;
497
498 pipe_info.index = sPipeMgr.assign_pipe(layer_info[index].pipe_pref);
499 pipe_info.isVG = (layer_info[index].pipe_pref == PIPE_REQ_VG);
500 pipe_info.isFG = (frame_pipe_count == 0);
501 /* if VAR pipe is attached to FB, FB will be updated with
502 VSYNC WAIT flag, so no need to set VSYNC WAIT for any
503 bypass pipes. if not, set VSYNC WAIT to the last updating pipe*/
504 pipe_info.vsync_wait =
505 (sPipeMgr.getStatus(VAR_INDEX) == PIPE_IN_FB_MODE) ? false:
506 (frame_pipe_count == (mdp_count - 1));
507 /* All the layers composed on FB will have MDP zorder 0, so start
508 assigning from 1*/
509 pipe_info.z_order = index -
510 (fallback_count ? fallback_count - 1 : fallback_count);
511
512 info.layer_index = index;
513 frame_pipe_count++;
514 }
515 }
516 return 1;
517}
518
519//returns array of layers and their allocated pipes
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700520bool MDPComp::parse_and_allocate(hwc_context_t* ctx, hwc_display_contents_1_t* list,
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700521 frame_info& current_frame ) {
522
523 int layer_count = list->numHwLayers;
524
525 /* clear pipe status */
526 sPipeMgr.reset();
527
528 layer_mdp_info* bp_layer_info = (layer_mdp_info*)
529 malloc(sizeof(layer_mdp_info)* layer_count);
530
531 reset_layer_mdp_info(bp_layer_info, layer_count);
532
533 /* iterate through layer list to mark candidate */
534 if(mark_layers(list, bp_layer_info, current_frame) == MDPCOMP_ABORT) {
535 free(bp_layer_info);
536 current_frame.count = 0;
537 ALOGE_IF(isDebug(), "%s:mark_layers failed!!", __FUNCTION__);
538 return false;
539 }
540 current_frame.pipe_layer = (pipe_layer_pair*)
541 malloc(sizeof(pipe_layer_pair) * current_frame.count);
542
543 /* allocate MDP pipes for marked layers */
544 alloc_layer_pipes( list, bp_layer_info, current_frame);
545
546 free(bp_layer_info);
547 return true;
548}
549#if SUPPORT_4LAYER
550int MDPComp::configure_var_pipe(hwc_context_t* ctx) {
551
552 if(!ctx) {
553 ALOGE("%s: invalid context", __FUNCTION__);
554 return -1;
555 }
556
557 framebuffer_device_t *fbDev = ctx->fbDev;
558 if (!fbDev) {
559 ALOGE("%s: fbDev is NULL", __FUNCTION__);
560 return -1;
561 }
562
563 int new_mode = -1, cur_mode;
564 fbDev->perform(fbDev,EVENT_GET_VAR_PIPE_MODE, (void*)&cur_mode);
565
566 if(sPipeMgr.getStatus(VAR_INDEX) == PIPE_IN_FB_MODE) {
567 new_mode = VAR_PIPE_FB_ATTACH;
568 } else if(sPipeMgr.getStatus(VAR_INDEX) == PIPE_IN_BYP_MODE) {
569 new_mode = VAR_PIPE_FB_DETACH;
570 fbDev->perform(fbDev,EVENT_WAIT_POSTBUFFER,NULL);
571 }
572
573 ALOGD_IF(isDebug(),"%s: old_mode: %d new_mode: %d", __FUNCTION__,
574 cur_mode, new_mode);
575
576 if((new_mode != cur_mode) && (new_mode >= 0)) {
577 if(fbDev->perform(fbDev,EVENT_SET_VAR_PIPE_MODE,(void*)&new_mode) < 0) {
578 ALOGE("%s: Setting var pipe mode failed", __FUNCTION__);
579 }
580 }
581
582 return 0;
583}
584#endif
585
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700586bool MDPComp::setup(hwc_context_t* ctx, hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700587 int nPipeIndex, vsync_wait, isFG;
588 int numHwLayers = list->numHwLayers;
589
590 frame_info &current_frame = sCurrentFrame;
591 current_frame.count = 0;
592
593 if(!ctx) {
594 ALOGE("%s: invalid context", __FUNCTION__);
595 return -1;
596 }
597
598 framebuffer_device_t *fbDev = ctx->mFbDev;
599 if (!fbDev) {
600 ALOGE("%s: fbDev is NULL", __FUNCTION__);
601 return -1;
602 }
603
604 if(!parse_and_allocate(ctx, list, current_frame)) {
605#if SUPPORT_4LAYER
606 int mode = VAR_PIPE_FB_ATTACH;
607 if(fbDev->perform(fbDev,EVENT_SET_VAR_PIPE_MODE,(void*)&mode) < 0 ) {
608 ALOGE("%s: setting var pipe mode failed", __FUNCTION__);
609 }
610#endif
611 ALOGD_IF(isDebug(), "%s: Falling back to FB", __FUNCTION__);
612 return false;
613 }
614#if SUPPORT_4LAYER
615 configure_var_pipe(ctx);
616#endif
617
618 overlay::Overlay& ov = *(ctx->mOverlay);
619 ovutils::eOverlayState state = ov.getState();
620
621 if (current_frame.count == 1) {
622 state = ovutils::OV_BYPASS_1_LAYER;
623 } else if (current_frame.count == 2) {
624 state = ovutils::OV_BYPASS_2_LAYER;
625 } else if (current_frame.count == 3) {
626 state = ovutils::OV_BYPASS_3_LAYER;
627 }
628
629 ov.setState(state);
630
631
632 for (int index = 0 ; index < current_frame.count; index++) {
633 int layer_index = current_frame.pipe_layer[index].layer_index;
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700634 hwc_layer_1_t* layer = &list->hwLayers[layer_index];
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700635 mdp_pipe_info& cur_pipe = current_frame.pipe_layer[index].pipe_index;
636
637 if( prepare(ctx, layer, cur_pipe) != 0 ) {
638 ALOGD_IF(isDebug(), "%s: MDPComp failed to configure overlay for \
639 layer %d with pipe index:%d",__FUNCTION__,
640 index, cur_pipe.index);
641 return false;
642 } else {
643 setLayerIndex(layer, index);
644 }
645 }
646 return true;
647}
648
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700649void MDPComp::unsetMDPCompLayerFlags(hwc_context_t* ctx, hwc_display_contents_1_t* list)
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700650{
651 if (!list)
652 return;
653
654 for (int index = 0 ; index < sCurrentFrame.count; index++) {
655 int l_index = sCurrentFrame.pipe_layer[index].layer_index;
656 if(list->hwLayers[l_index].flags & HWC_MDPCOMP) {
657 list->hwLayers[l_index].flags &= ~HWC_MDPCOMP;
658 }
Naseer Ahmedfb4cbdd2012-08-16 15:54:53 -0700659
660 if(list->hwLayers[l_index].compositionType == HWC_OVERLAY) {
661 list->hwLayers[l_index].compositionType = HWC_FRAMEBUFFER;
662 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700663 }
664}
665
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700666int MDPComp::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700667
668 if(!isEnabled()) {
669 ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled",__FUNCTION__);
670 return 0;
671 }
672
673 if(!ctx || !list) {
674 ALOGE("%s: invalid contxt or list",__FUNCTION__);
675 return -1;
676 }
677
678 overlay::Overlay& ov = *(ctx->mOverlay);
679
680 for(unsigned int i = 0; i < list->numHwLayers; i++ )
681 {
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700682 hwc_layer_1_t *layer = &list->hwLayers[i];
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700683
684 if(!(layer->flags & HWC_MDPCOMP)) {
685 ALOGD_IF(isDebug(), "%s: Layer Not flagged for MDP comp",
686 __FUNCTION__);
687 continue;
688 }
689
690 int data_index = getLayerIndex(layer);
691 mdp_pipe_info& pipe_info =
692 sCurrentFrame.pipe_layer[data_index].pipe_index;
693 int index = pipe_info.index;
694
695 if(index < 0) {
696 ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, index);
697 return -1;
698 }
699
700 /* reset Invalidator */
701 if(idleInvalidator)
702 idleInvalidator->markForSleep();
703
704 ovutils::eDest dest;
705
706 if (index == 0) {
707 dest = ovutils::OV_PIPE0;
708 } else if (index == 1) {
709 dest = ovutils::OV_PIPE1;
710 } else if (index == 2) {
711 dest = ovutils::OV_PIPE2;
712 }
713
714 if (ctx ) {
715 private_handle_t *hnd = (private_handle_t *)layer->handle;
716 if(!hnd) {
717 ALOGE("%s handle null", __FUNCTION__);
718 return -1;
719 }
720
721 //lock buffer before queue
722 //XXX: Handle lock failure
723 ctx->qbuf->lockAndAdd(hnd);
724
725 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
726 using pipe: %d", __FUNCTION__, layer,
727 hnd, index );
728
729 if (!ov.queueBuffer(hnd->fd, hnd->offset, dest)) {
730 ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
731 return -1;
732 }
733 }
734 layer->flags &= ~HWC_MDPCOMP;
735 layer->flags |= HWC_MDPCOMP_INDEX_MASK;
736 }
737 return 0;
738}
739
740bool MDPComp::init(hwc_context_t *dev) {
741
742 if(!dev) {
743 ALOGE("%s: Invalid hwc context!!",__FUNCTION__);
744 return false;
745 }
746
747#if SUPPORT_4LAYER
748 if(MAX_MDPCOMP_LAYERS > MAX_STATIC_PIPES) {
749 framebuffer_device_t *fbDev = dev->fbDevice;
750 if(fbDev == NULL) {
751 ALOGE("%s: FATAL: framebuffer device is NULL", __FUNCTION__);
752 return false;
753 }
754
755 //Receive VAR pipe object from framebuffer
756 if(fbDev->perform(fbDev,EVENT_GET_VAR_PIPE,(void*)&ov) < 0) {
757 ALOGE("%s: FATAL: getVariablePipe failed!!", __FUNCTION__);
758 return false;
759 }
760
761 sPipeMgr.setStatus(VAR_INDEX, PIPE_IN_FB_MODE);
762 }
763#endif
764 char property[PROPERTY_VALUE_MAX];
765
766 sMaxLayers = 0;
767 if(property_get("debug.mdpcomp.maxlayer", property, NULL) > 0) {
768 if(atoi(property) != 0)
769 sMaxLayers = atoi(property);
770 }
771
772 sDebugLogs = false;
773 if(property_get("debug.mdpcomp.logs", property, NULL) > 0) {
774 if(atoi(property) != 0)
775 sDebugLogs = true;
776 }
777
778 unsigned long idle_timeout = DEFAULT_IDLE_TIME;
779 if(property_get("debug.mdpcomp.idletime", property, NULL) > 0) {
780 if(atoi(property) != 0)
781 idle_timeout = atoi(property);
782 }
783
784 //create Idle Invalidator
785 idleInvalidator = IdleInvalidator::getInstance();
786
787 if(idleInvalidator == NULL) {
788 ALOGE("%s: failed to instantiate idleInvalidator object", __FUNCTION__);
789 } else {
790 idleInvalidator->init(timeout_handler, dev, idle_timeout);
791 }
792 return true;
793}
794
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700795bool MDPComp::configure(hwc_composer_device_1_t *dev, hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700796
797 if(!isEnabled()) {
798 ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
799 return false;
800 }
801
802 hwc_context_t* ctx = (hwc_context_t*)(dev);
803
804 bool isMDPCompUsed = true;
805 bool doable = is_doable(dev, list);
806
807 if(doable) {
808 if(setup(ctx, list)) {
809 setMDPCompLayerFlags(list);
810 sMDPCompState = MDPCOMP_ON;
811 } else {
812 ALOGD_IF(isDebug(),"%s: MDP Comp Failed",__FUNCTION__);
813 isMDPCompUsed = false;
814 }
815 } else {
816 ALOGD_IF( isDebug(),"%s: MDP Comp not possible[%d]",__FUNCTION__,
817 doable);
818 isMDPCompUsed = false;
819 }
820
821 //Reset states
822 if(!isMDPCompUsed) {
823 //Reset current frame
824 reset(ctx, list);
825 }
826
827 sIdleFallBack = false;
828
829 return isMDPCompUsed;
830}
831}; //namespace
832