blob: 81074006e3e14c40d345be4d6ee55b19628771de [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
117 hwc_procs* proc = (hwc_procs*)ctx->device.reserved_proc[0];
118
119 if(!proc) {
120 ALOGE("%s: HWC proc not registered", __FUNCTION__);
121 return;
122 }
123 sIdleFallBack = true;
124 /* Trigger SF to redraw the current frame */
125 proc->invalidate(proc);
126}
127
128void MDPComp::reset( hwc_context_t *ctx, hwc_layer_list_t* list ) {
129 sCurrentFrame.count = 0;
130 free(sCurrentFrame.pipe_layer);
131 sCurrentFrame.pipe_layer = NULL;
132
133 //Reset MDP pipes
134 sPipeMgr.reset();
135 sPipeMgr.setStatus(VAR_INDEX, PIPE_IN_FB_MODE);
136
137#if SUPPORT_4LAYER
138 configure_var_pipe(ctx);
139#endif
140
141 //Reset flags and states
142 unsetMDPCompLayerFlags(ctx, list);
143 if(sMDPCompState == MDPCOMP_ON) {
144 sMDPCompState = MDPCOMP_OFF_PENDING;
145 }
146}
147
148void MDPComp::setLayerIndex(hwc_layer_t* layer, const int pipe_index)
149{
150 layer->flags &= ~HWC_MDPCOMP_INDEX_MASK;
151 layer->flags |= pipe_index << MDPCOMP_INDEX_OFFSET;
152}
153
154int MDPComp::getLayerIndex(hwc_layer_t* layer)
155{
156 int byp_index = -1;
157
158 if(layer->flags & HWC_MDPCOMP) {
159 byp_index = ((layer->flags & HWC_MDPCOMP_INDEX_MASK) >>
160 MDPCOMP_INDEX_OFFSET);
161 byp_index = (byp_index < sMaxLayers ? byp_index : -1 );
162 }
163 return byp_index;
164}
165void MDPComp::print_info(hwc_layer_t* layer)
166{
167 hwc_rect_t sourceCrop = layer->sourceCrop;
168 hwc_rect_t displayFrame = layer->displayFrame;
169
170 int s_l = sourceCrop.left;
171 int s_t = sourceCrop.top;
172 int s_r = sourceCrop.right;
173 int s_b = sourceCrop.bottom;
174
175 int d_l = displayFrame.left;
176 int d_t = displayFrame.top;
177 int d_r = displayFrame.right;
178 int d_b = displayFrame.bottom;
179
180 ALOGD_IF(isDebug(), "src:[%d,%d,%d,%d] (%d x %d) \
181 dst:[%d,%d,%d,%d] (%d x %d)",
182 s_l, s_t, s_r, s_b, (s_r - s_l), (s_b - s_t),
183 d_l, d_t, d_r, d_b, (d_r - d_l), (d_b - d_t));
184}
185/*
186 * Configures pipe(s) for MDP composition
187 */
188int MDPComp::prepare(hwc_context_t *ctx, hwc_layer_t *layer,
189 mdp_pipe_info& mdp_info) {
190
191 int nPipeIndex = mdp_info.index;
192
193 if (ctx) {
194
195 private_handle_t *hnd = (private_handle_t *)layer->handle;
196
197 overlay::Overlay& ov = *(ctx->mOverlay);
198
199 if(!hnd) {
200 ALOGE("%s: layer handle is NULL", __FUNCTION__);
201 return -1;
202 }
203
204
205 int hw_w = ctx->mFbDev->width;
206 int hw_h = ctx->mFbDev->height;
207
208
209 hwc_rect_t sourceCrop = layer->sourceCrop;
210 hwc_rect_t displayFrame = layer->displayFrame;
211
212 const int src_w = sourceCrop.right - sourceCrop.left;
213 const int src_h = sourceCrop.bottom - sourceCrop.top;
214
215 hwc_rect_t crop = sourceCrop;
216 int crop_w = crop.right - crop.left;
217 int crop_h = crop.bottom - crop.top;
218
219 hwc_rect_t dst = displayFrame;
220 int dst_w = dst.right - dst.left;
221 int dst_h = dst.bottom - dst.top;
222
223 //REDUNDANT ??
224 if(hnd != NULL &&
225 (hnd->flags & private_handle_t::PRIV_FLAGS_NONCONTIGUOUS_MEM )) {
226 ALOGE("%s: failed due to non-pmem memory",__FUNCTION__);
227 return -1;
228 }
229
230 if(dst.left < 0 || dst.top < 0 ||
231 dst.right > hw_w || dst.bottom > hw_h) {
232 ALOGD_IF(isDebug(),"%s: Destination has negative coordinates",
233 __FUNCTION__);
234
235 qhwc::calculate_crop_rects(crop, dst, hw_w, hw_h);
236
237 //Update calulated width and height
238 crop_w = crop.right - crop.left;
239 crop_h = crop.bottom - crop.top;
240
241 dst_w = dst.right - dst.left;
242 dst_h = dst.bottom - dst.top;
243 }
244
245 if( (dst_w > hw_w)|| (dst_h > hw_h)) {
246 ALOGD_IF(isDebug(),"%s: Dest rect exceeds FB", __FUNCTION__);
247 print_info(layer);
248 dst_w = hw_w;
249 dst_h = hw_h;
250 }
251
252 // Determine pipe to set based on pipe index
253 ovutils::eDest dest = ovutils::OV_PIPE_ALL;
254 if (nPipeIndex == 0) {
255 dest = ovutils::OV_PIPE0;
256 } else if (nPipeIndex == 1) {
257 dest = ovutils::OV_PIPE1;
258 } else if (nPipeIndex == 2) {
259 dest = ovutils::OV_PIPE2;
260 }
261
262 ovutils::eZorder zOrder = ovutils::ZORDER_0;
263
264 if(mdp_info.z_order == 0 ) {
265 zOrder = ovutils::ZORDER_0;
266 } else if(mdp_info.z_order == 1 ) {
267 zOrder = ovutils::ZORDER_1;
268 } else if(mdp_info.z_order == 2 ) {
269 zOrder = ovutils::ZORDER_2;
270 }
271
272 // Order order order
273 // setSource - just setting source
274 // setParameter - changes src w/h/f accordingly
275 // setCrop - ROI - src_rect
276 // setPosition - dst_rect
277 // commit - commit changes to mdp driver
278 // queueBuffer - not here, happens when draw is called
279
280 ovutils::eTransform orient =
281 static_cast<ovutils::eTransform>(layer->transform);
282
283 ov.setTransform(orient, dest);
284 ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
285 ovutils::eMdpFlags mdpFlags = mdp_info.isVG ? ovutils::OV_MDP_PIPE_SHARE
286 : ovutils::OV_MDP_FLAGS_NONE;
287 ovutils::eIsFg isFG = mdp_info.isFG ? ovutils::IS_FG_SET
288 : ovutils::IS_FG_OFF;
289 ovutils::PipeArgs parg(mdpFlags,
290 info,
291 zOrder,
292 isFG,
293 ovutils::ROT_FLAG_DISABLED);
294
295 ovutils::PipeArgs pargs[MAX_PIPES] = { parg, parg, parg };
296 if (!ov.setSource(pargs, dest)) {
297 ALOGE("%s: setSource failed", __FUNCTION__);
298 return -1;
299 }
300
301 ovutils::Dim dcrop(crop.left, crop.top, crop_w, crop_h);
302 if (!ov.setCrop(dcrop, dest)) {
303 ALOGE("%s: setCrop failed", __FUNCTION__);
304 return -1;
305 }
306
307 ovutils::Dim dim(dst.left, dst.top, dst_w, dst_h);
308 if (!ov.setPosition(dim, dest)) {
309 ALOGE("%s: setPosition failed", __FUNCTION__);
310 return -1;
311 }
312
313 ALOGD_IF(isDebug(),"%s: MDP set: crop[%d,%d,%d,%d] dst[%d,%d,%d,%d] \
314 nPipe: %d isFG: %d zorder: %d",__FUNCTION__, dcrop.x,
315 dcrop.y,dcrop.w, dcrop.h, dim.x, dim.y, dim.w, dim.h,
316 nPipeIndex,mdp_info.isFG, mdp_info.z_order);
317
318 if (!ov.commit(dest)) {
319 ALOGE("%s: commit failed", __FUNCTION__);
320 return -1;
321 }
322 }
323 return 0;
324}
325
326/*
327 * MDPComp not possible when
328 * 1. We have more than sMaxLayers
329 * 2. External display connected
330 * 3. Composition is triggered by
331 * Idle timer expiry
332 * 4. Rotation is needed
333 * 5. Overlay in use
334 */
335
336bool MDPComp::is_doable(hwc_composer_device_t *dev,
337 const hwc_layer_list_t* list) {
338 hwc_context_t* ctx = (hwc_context_t*)(dev);
339
340 if(!ctx) {
341 ALOGE("%s: hwc context is NULL", __FUNCTION__);
342 return false;
343 }
344
345 //Number of layers
346 if(list->numHwLayers < 1 || list->numHwLayers > sMaxLayers) {
347 ALOGD_IF(isDebug(), "%s: Unsupported number of layers",__FUNCTION__);
348 return false;
349 }
350
351 //Disable MDPComp when ext display connected
352 if(ctx->mExtDisplay->getExternalDisplay()) {
353 ALOGD_IF(isDebug(), "%s: External display connected.", __FUNCTION__);
354 }
355
356 //FB composition on idle timeout
357 if(sIdleFallBack) {
358 ALOGD_IF(isDebug(), "%s: idle fallback",__FUNCTION__);
359 return false;
360 }
361
362 //MDP composition is not efficient if rotation is needed.
363 for(unsigned int i = 0; i < list->numHwLayers; ++i) {
364 if(list->hwLayers[i].transform) {
365 ALOGD_IF(isDebug(), "%s: orientation involved",__FUNCTION__);
366 return false;
367 }
368 }
369
370 return true;
371}
372
373void MDPComp::setMDPCompLayerFlags(hwc_layer_list_t* list) {
374
375 for(int index = 0 ; index < sCurrentFrame.count; index++ )
376 {
377 int layer_index = sCurrentFrame.pipe_layer[index].layer_index;
378 if(layer_index >= 0) {
379 hwc_layer_t* layer = &(list->hwLayers[layer_index]);
380
381 layer->flags |= HWC_MDPCOMP;
382 layer->compositionType = HWC_OVERLAY;
383 layer->hints |= HWC_HINT_CLEAR_FB;
384 }
385 }
386}
387
388void MDPComp::get_layer_info(hwc_layer_t* layer, int& flags) {
389
390 private_handle_t* hnd = (private_handle_t*)layer->handle;
391
392 if(layer->flags & HWC_SKIP_LAYER) {
393 flags |= MDPCOMP_LAYER_SKIP;
394 } else if(hnd != NULL &&
395 (hnd->flags & private_handle_t::PRIV_FLAGS_NONCONTIGUOUS_MEM )) {
396 flags |= MDPCOMP_LAYER_UNSUPPORTED_MEM;
397 }
398
399 if(layer->blending != HWC_BLENDING_NONE)
400 flags |= MDPCOMP_LAYER_BLEND;
401
402 int dst_w, dst_h;
403 getLayerResolution(layer, dst_w, dst_h);
404
405 hwc_rect_t sourceCrop = layer->sourceCrop;
406 const int src_w = sourceCrop.right - sourceCrop.left;
407 const int src_h = sourceCrop.bottom - sourceCrop.top;
408 if(((src_w > dst_w) || (src_h > dst_h))) {
409 flags |= MDPCOMP_LAYER_DOWNSCALE;
410 }
411}
412
413int MDPComp::mark_layers(hwc_layer_list_t* list, layer_mdp_info* layer_info,
414 frame_info& current_frame) {
415
416 int layer_count = list->numHwLayers;
417
418 if(layer_count > sMaxLayers) {
419 if(!sPipeMgr.req_for_pipe(PIPE_REQ_FB)) {
420 ALOGE("%s: binding var pipe to FB failed!!", __FUNCTION__);
421 return 0;
422 }
423 }
424
425 //Parse layers from higher z-order
426 for(int index = layer_count - 1 ; index >= 0; index-- ) {
427 hwc_layer_t* layer = &list->hwLayers[index];
428
429 int layer_prop = 0;
430 get_layer_info(layer, layer_prop);
431
432 ALOGD_IF(isDebug(),"%s: prop for layer [%d]: %x", __FUNCTION__,
433 index, layer_prop);
434
435 //Both in cases of NON-CONTIGUOUS memory or SKIP layer,
436 //current version of mdp composition falls back completely to FB
437 //composition.
438 //TO DO: Support dual mode composition
439
440 if(layer_prop & MDPCOMP_LAYER_UNSUPPORTED_MEM) {
441 ALOGD_IF(isDebug(), "%s: Non contigous memory",__FUNCTION__);
442 return MDPCOMP_ABORT;
443 }
444
445 if(layer_prop & MDPCOMP_LAYER_SKIP) {
446 ALOGD_IF(isDebug(), "%s:skip layer",__FUNCTION__);
447 return MDPCOMP_ABORT;
448 }
449
450 //Request for MDP pipes
451 int pipe_pref = PIPE_REQ_VG;
452
453 if((layer_prop & MDPCOMP_LAYER_DOWNSCALE) &&
454 (layer_prop & MDPCOMP_LAYER_BLEND)) {
455 pipe_pref = PIPE_REQ_RGB;
456 }
457
458 int allocated_pipe = sPipeMgr.req_for_pipe( pipe_pref);
459 if(allocated_pipe) {
460 layer_info[index].can_use_mdp = true;
461 layer_info[index].pipe_pref = allocated_pipe;
462 current_frame.count++;
463 }else {
464 ALOGE("%s: pipe marking in mark layer fails for : %d",
465 __FUNCTION__, allocated_pipe);
466 return MDPCOMP_FAILURE;
467 }
468 }
469 return MDPCOMP_SUCCESS;
470}
471
472void MDPComp::reset_layer_mdp_info(layer_mdp_info* layer_info, int count) {
473 for(int i = 0 ; i < count; i++ ) {
474 layer_info[i].can_use_mdp = false;
475 layer_info[i].pipe_pref = PIPE_NONE;
476 }
477}
478
479bool MDPComp::alloc_layer_pipes(hwc_layer_list_t* list,
480 layer_mdp_info* layer_info, frame_info& current_frame) {
481
482 int layer_count = list->numHwLayers;
483 int mdp_count = current_frame.count;
484 int fallback_count = layer_count - mdp_count;
485 int frame_pipe_count = 0;
486
487 ALOGD_IF(isDebug(), "%s: dual mode: %d total count: %d \
488 mdp count: %d fallback count: %d",
489 __FUNCTION__, (layer_count != mdp_count),
490 layer_count, mdp_count, fallback_count);
491
492 for(int index = 0 ; index < layer_count ; index++ ) {
493 hwc_layer_t* layer = &list->hwLayers[index];
494
495 if(layer_info[index].can_use_mdp) {
496 pipe_layer_pair& info = current_frame.pipe_layer[frame_pipe_count];
497 mdp_pipe_info& pipe_info = info.pipe_index;
498
499 pipe_info.index = sPipeMgr.assign_pipe(layer_info[index].pipe_pref);
500 pipe_info.isVG = (layer_info[index].pipe_pref == PIPE_REQ_VG);
501 pipe_info.isFG = (frame_pipe_count == 0);
502 /* if VAR pipe is attached to FB, FB will be updated with
503 VSYNC WAIT flag, so no need to set VSYNC WAIT for any
504 bypass pipes. if not, set VSYNC WAIT to the last updating pipe*/
505 pipe_info.vsync_wait =
506 (sPipeMgr.getStatus(VAR_INDEX) == PIPE_IN_FB_MODE) ? false:
507 (frame_pipe_count == (mdp_count - 1));
508 /* All the layers composed on FB will have MDP zorder 0, so start
509 assigning from 1*/
510 pipe_info.z_order = index -
511 (fallback_count ? fallback_count - 1 : fallback_count);
512
513 info.layer_index = index;
514 frame_pipe_count++;
515 }
516 }
517 return 1;
518}
519
520//returns array of layers and their allocated pipes
521bool MDPComp::parse_and_allocate(hwc_context_t* ctx, hwc_layer_list_t* list,
522 frame_info& current_frame ) {
523
524 int layer_count = list->numHwLayers;
525
526 /* clear pipe status */
527 sPipeMgr.reset();
528
529 layer_mdp_info* bp_layer_info = (layer_mdp_info*)
530 malloc(sizeof(layer_mdp_info)* layer_count);
531
532 reset_layer_mdp_info(bp_layer_info, layer_count);
533
534 /* iterate through layer list to mark candidate */
535 if(mark_layers(list, bp_layer_info, current_frame) == MDPCOMP_ABORT) {
536 free(bp_layer_info);
537 current_frame.count = 0;
538 ALOGE_IF(isDebug(), "%s:mark_layers failed!!", __FUNCTION__);
539 return false;
540 }
541 current_frame.pipe_layer = (pipe_layer_pair*)
542 malloc(sizeof(pipe_layer_pair) * current_frame.count);
543
544 /* allocate MDP pipes for marked layers */
545 alloc_layer_pipes( list, bp_layer_info, current_frame);
546
547 free(bp_layer_info);
548 return true;
549}
550#if SUPPORT_4LAYER
551int MDPComp::configure_var_pipe(hwc_context_t* ctx) {
552
553 if(!ctx) {
554 ALOGE("%s: invalid context", __FUNCTION__);
555 return -1;
556 }
557
558 framebuffer_device_t *fbDev = ctx->fbDev;
559 if (!fbDev) {
560 ALOGE("%s: fbDev is NULL", __FUNCTION__);
561 return -1;
562 }
563
564 int new_mode = -1, cur_mode;
565 fbDev->perform(fbDev,EVENT_GET_VAR_PIPE_MODE, (void*)&cur_mode);
566
567 if(sPipeMgr.getStatus(VAR_INDEX) == PIPE_IN_FB_MODE) {
568 new_mode = VAR_PIPE_FB_ATTACH;
569 } else if(sPipeMgr.getStatus(VAR_INDEX) == PIPE_IN_BYP_MODE) {
570 new_mode = VAR_PIPE_FB_DETACH;
571 fbDev->perform(fbDev,EVENT_WAIT_POSTBUFFER,NULL);
572 }
573
574 ALOGD_IF(isDebug(),"%s: old_mode: %d new_mode: %d", __FUNCTION__,
575 cur_mode, new_mode);
576
577 if((new_mode != cur_mode) && (new_mode >= 0)) {
578 if(fbDev->perform(fbDev,EVENT_SET_VAR_PIPE_MODE,(void*)&new_mode) < 0) {
579 ALOGE("%s: Setting var pipe mode failed", __FUNCTION__);
580 }
581 }
582
583 return 0;
584}
585#endif
586
587bool MDPComp::setup(hwc_context_t* ctx, hwc_layer_list_t* list) {
588 int nPipeIndex, vsync_wait, isFG;
589 int numHwLayers = list->numHwLayers;
590
591 frame_info &current_frame = sCurrentFrame;
592 current_frame.count = 0;
593
594 if(!ctx) {
595 ALOGE("%s: invalid context", __FUNCTION__);
596 return -1;
597 }
598
599 framebuffer_device_t *fbDev = ctx->mFbDev;
600 if (!fbDev) {
601 ALOGE("%s: fbDev is NULL", __FUNCTION__);
602 return -1;
603 }
604
605 if(!parse_and_allocate(ctx, list, current_frame)) {
606#if SUPPORT_4LAYER
607 int mode = VAR_PIPE_FB_ATTACH;
608 if(fbDev->perform(fbDev,EVENT_SET_VAR_PIPE_MODE,(void*)&mode) < 0 ) {
609 ALOGE("%s: setting var pipe mode failed", __FUNCTION__);
610 }
611#endif
612 ALOGD_IF(isDebug(), "%s: Falling back to FB", __FUNCTION__);
613 return false;
614 }
615#if SUPPORT_4LAYER
616 configure_var_pipe(ctx);
617#endif
618
619 overlay::Overlay& ov = *(ctx->mOverlay);
620 ovutils::eOverlayState state = ov.getState();
621
622 if (current_frame.count == 1) {
623 state = ovutils::OV_BYPASS_1_LAYER;
624 } else if (current_frame.count == 2) {
625 state = ovutils::OV_BYPASS_2_LAYER;
626 } else if (current_frame.count == 3) {
627 state = ovutils::OV_BYPASS_3_LAYER;
628 }
629
630 ov.setState(state);
631
632
633 for (int index = 0 ; index < current_frame.count; index++) {
634 int layer_index = current_frame.pipe_layer[index].layer_index;
635 hwc_layer_t* layer = &list->hwLayers[layer_index];
636 mdp_pipe_info& cur_pipe = current_frame.pipe_layer[index].pipe_index;
637
638 if( prepare(ctx, layer, cur_pipe) != 0 ) {
639 ALOGD_IF(isDebug(), "%s: MDPComp failed to configure overlay for \
640 layer %d with pipe index:%d",__FUNCTION__,
641 index, cur_pipe.index);
642 return false;
643 } else {
644 setLayerIndex(layer, index);
645 }
646 }
647 return true;
648}
649
650void MDPComp::unsetMDPCompLayerFlags(hwc_context_t* ctx, hwc_layer_list_t* list)
651{
652 if (!list)
653 return;
654
655 for (int index = 0 ; index < sCurrentFrame.count; index++) {
656 int l_index = sCurrentFrame.pipe_layer[index].layer_index;
657 if(list->hwLayers[l_index].flags & HWC_MDPCOMP) {
658 list->hwLayers[l_index].flags &= ~HWC_MDPCOMP;
659 }
660 }
661}
662
663int MDPComp::draw(hwc_context_t *ctx, hwc_layer_list_t* list) {
664
665 if(!isEnabled()) {
666 ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled",__FUNCTION__);
667 return 0;
668 }
669
670 if(!ctx || !list) {
671 ALOGE("%s: invalid contxt or list",__FUNCTION__);
672 return -1;
673 }
674
675 overlay::Overlay& ov = *(ctx->mOverlay);
676
677 for(unsigned int i = 0; i < list->numHwLayers; i++ )
678 {
679 hwc_layer_t *layer = &list->hwLayers[i];
680
681 if(!(layer->flags & HWC_MDPCOMP)) {
682 ALOGD_IF(isDebug(), "%s: Layer Not flagged for MDP comp",
683 __FUNCTION__);
684 continue;
685 }
686
687 int data_index = getLayerIndex(layer);
688 mdp_pipe_info& pipe_info =
689 sCurrentFrame.pipe_layer[data_index].pipe_index;
690 int index = pipe_info.index;
691
692 if(index < 0) {
693 ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, index);
694 return -1;
695 }
696
697 /* reset Invalidator */
698 if(idleInvalidator)
699 idleInvalidator->markForSleep();
700
701 ovutils::eDest dest;
702
703 if (index == 0) {
704 dest = ovutils::OV_PIPE0;
705 } else if (index == 1) {
706 dest = ovutils::OV_PIPE1;
707 } else if (index == 2) {
708 dest = ovutils::OV_PIPE2;
709 }
710
711 if (ctx ) {
712 private_handle_t *hnd = (private_handle_t *)layer->handle;
713 if(!hnd) {
714 ALOGE("%s handle null", __FUNCTION__);
715 return -1;
716 }
717
718 //lock buffer before queue
719 //XXX: Handle lock failure
720 ctx->qbuf->lockAndAdd(hnd);
721
722 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
723 using pipe: %d", __FUNCTION__, layer,
724 hnd, index );
725
726 if (!ov.queueBuffer(hnd->fd, hnd->offset, dest)) {
727 ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
728 return -1;
729 }
730 }
731 layer->flags &= ~HWC_MDPCOMP;
732 layer->flags |= HWC_MDPCOMP_INDEX_MASK;
733 }
734 return 0;
735}
736
737bool MDPComp::init(hwc_context_t *dev) {
738
739 if(!dev) {
740 ALOGE("%s: Invalid hwc context!!",__FUNCTION__);
741 return false;
742 }
743
744#if SUPPORT_4LAYER
745 if(MAX_MDPCOMP_LAYERS > MAX_STATIC_PIPES) {
746 framebuffer_device_t *fbDev = dev->fbDevice;
747 if(fbDev == NULL) {
748 ALOGE("%s: FATAL: framebuffer device is NULL", __FUNCTION__);
749 return false;
750 }
751
752 //Receive VAR pipe object from framebuffer
753 if(fbDev->perform(fbDev,EVENT_GET_VAR_PIPE,(void*)&ov) < 0) {
754 ALOGE("%s: FATAL: getVariablePipe failed!!", __FUNCTION__);
755 return false;
756 }
757
758 sPipeMgr.setStatus(VAR_INDEX, PIPE_IN_FB_MODE);
759 }
760#endif
761 char property[PROPERTY_VALUE_MAX];
762
763 sMaxLayers = 0;
764 if(property_get("debug.mdpcomp.maxlayer", property, NULL) > 0) {
765 if(atoi(property) != 0)
766 sMaxLayers = atoi(property);
767 }
768
769 sDebugLogs = false;
770 if(property_get("debug.mdpcomp.logs", property, NULL) > 0) {
771 if(atoi(property) != 0)
772 sDebugLogs = true;
773 }
774
775 unsigned long idle_timeout = DEFAULT_IDLE_TIME;
776 if(property_get("debug.mdpcomp.idletime", property, NULL) > 0) {
777 if(atoi(property) != 0)
778 idle_timeout = atoi(property);
779 }
780
781 //create Idle Invalidator
782 idleInvalidator = IdleInvalidator::getInstance();
783
784 if(idleInvalidator == NULL) {
785 ALOGE("%s: failed to instantiate idleInvalidator object", __FUNCTION__);
786 } else {
787 idleInvalidator->init(timeout_handler, dev, idle_timeout);
788 }
789 return true;
790}
791
792bool MDPComp::configure(hwc_composer_device_t *dev, hwc_layer_list_t* list) {
793
794 if(!isEnabled()) {
795 ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
796 return false;
797 }
798
799 hwc_context_t* ctx = (hwc_context_t*)(dev);
800
801 bool isMDPCompUsed = true;
802 bool doable = is_doable(dev, list);
803
804 if(doable) {
805 if(setup(ctx, list)) {
806 setMDPCompLayerFlags(list);
807 sMDPCompState = MDPCOMP_ON;
808 } else {
809 ALOGD_IF(isDebug(),"%s: MDP Comp Failed",__FUNCTION__);
810 isMDPCompUsed = false;
811 }
812 } else {
813 ALOGD_IF( isDebug(),"%s: MDP Comp not possible[%d]",__FUNCTION__,
814 doable);
815 isMDPCompUsed = false;
816 }
817
818 //Reset states
819 if(!isMDPCompUsed) {
820 //Reset current frame
821 reset(ctx, list);
822 }
823
824 sIdleFallBack = false;
825
826 return isMDPCompUsed;
827}
828}; //namespace
829