blob: aa59cbd0546b847cd75efbfbec4b7b4b2d1fa206 [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
Naseer Ahmedfb4cbdd2012-08-16 15:54:53 -0700128void MDPComp::reset(hwc_context_t *ctx, hwc_display_contents_1_t* list ) {
129 //Reset flags and states
130 unsetMDPCompLayerFlags(ctx, list);
131 if(sMDPCompState == MDPCOMP_ON) {
132 sMDPCompState = MDPCOMP_OFF_PENDING;
133 }
134
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700135 sCurrentFrame.count = 0;
136 free(sCurrentFrame.pipe_layer);
137 sCurrentFrame.pipe_layer = NULL;
138
139 //Reset MDP pipes
140 sPipeMgr.reset();
141 sPipeMgr.setStatus(VAR_INDEX, PIPE_IN_FB_MODE);
142
143#if SUPPORT_4LAYER
144 configure_var_pipe(ctx);
145#endif
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700146}
147
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700148void MDPComp::setLayerIndex(hwc_layer_1_t* layer, const int pipe_index)
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700149{
150 layer->flags &= ~HWC_MDPCOMP_INDEX_MASK;
151 layer->flags |= pipe_index << MDPCOMP_INDEX_OFFSET;
152}
153
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700154int MDPComp::getLayerIndex(hwc_layer_1_t* layer)
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700155{
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}
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700165void MDPComp::print_info(hwc_layer_1_t* layer)
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700166{
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 */
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700188int MDPComp::prepare(hwc_context_t *ctx, hwc_layer_1_t *layer,
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700189 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
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700336bool MDPComp::is_doable(hwc_composer_device_1_t *dev,
Naseer Ahmedfb4cbdd2012-08-16 15:54:53 -0700337 hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700338 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
Naseer Ahmedb90d0912012-07-31 13:09:51 -0700346 if(list->numHwLayers < 1 || list->numHwLayers > (uint32_t)sMaxLayers) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700347 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__);
Saurabh Shahb45b8812012-08-19 18:36:59 +0530354 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700355 }
356
357 //FB composition on idle timeout
358 if(sIdleFallBack) {
359 ALOGD_IF(isDebug(), "%s: idle fallback",__FUNCTION__);
360 return false;
361 }
362
363 //MDP composition is not efficient if rotation is needed.
364 for(unsigned int i = 0; i < list->numHwLayers; ++i) {
365 if(list->hwLayers[i].transform) {
366 ALOGD_IF(isDebug(), "%s: orientation involved",__FUNCTION__);
367 return false;
368 }
369 }
370
371 return true;
372}
373
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700374void MDPComp::setMDPCompLayerFlags(hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700375
376 for(int index = 0 ; index < sCurrentFrame.count; index++ )
377 {
378 int layer_index = sCurrentFrame.pipe_layer[index].layer_index;
379 if(layer_index >= 0) {
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700380 hwc_layer_1_t* layer = &(list->hwLayers[layer_index]);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700381
382 layer->flags |= HWC_MDPCOMP;
383 layer->compositionType = HWC_OVERLAY;
384 layer->hints |= HWC_HINT_CLEAR_FB;
385 }
386 }
387}
388
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700389void MDPComp::get_layer_info(hwc_layer_1_t* layer, int& flags) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700390
391 private_handle_t* hnd = (private_handle_t*)layer->handle;
392
393 if(layer->flags & HWC_SKIP_LAYER) {
394 flags |= MDPCOMP_LAYER_SKIP;
395 } else if(hnd != NULL &&
396 (hnd->flags & private_handle_t::PRIV_FLAGS_NONCONTIGUOUS_MEM )) {
397 flags |= MDPCOMP_LAYER_UNSUPPORTED_MEM;
398 }
399
400 if(layer->blending != HWC_BLENDING_NONE)
401 flags |= MDPCOMP_LAYER_BLEND;
402
403 int dst_w, dst_h;
404 getLayerResolution(layer, dst_w, dst_h);
405
406 hwc_rect_t sourceCrop = layer->sourceCrop;
407 const int src_w = sourceCrop.right - sourceCrop.left;
408 const int src_h = sourceCrop.bottom - sourceCrop.top;
409 if(((src_w > dst_w) || (src_h > dst_h))) {
410 flags |= MDPCOMP_LAYER_DOWNSCALE;
411 }
412}
413
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700414int MDPComp::mark_layers(hwc_display_contents_1_t* list, layer_mdp_info* layer_info,
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700415 frame_info& current_frame) {
416
417 int layer_count = list->numHwLayers;
418
419 if(layer_count > sMaxLayers) {
420 if(!sPipeMgr.req_for_pipe(PIPE_REQ_FB)) {
421 ALOGE("%s: binding var pipe to FB failed!!", __FUNCTION__);
422 return 0;
423 }
424 }
425
426 //Parse layers from higher z-order
427 for(int index = layer_count - 1 ; index >= 0; index-- ) {
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700428 hwc_layer_1_t* layer = &list->hwLayers[index];
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700429
430 int layer_prop = 0;
431 get_layer_info(layer, layer_prop);
432
433 ALOGD_IF(isDebug(),"%s: prop for layer [%d]: %x", __FUNCTION__,
434 index, layer_prop);
435
436 //Both in cases of NON-CONTIGUOUS memory or SKIP layer,
437 //current version of mdp composition falls back completely to FB
438 //composition.
439 //TO DO: Support dual mode composition
440
441 if(layer_prop & MDPCOMP_LAYER_UNSUPPORTED_MEM) {
442 ALOGD_IF(isDebug(), "%s: Non contigous memory",__FUNCTION__);
443 return MDPCOMP_ABORT;
444 }
445
446 if(layer_prop & MDPCOMP_LAYER_SKIP) {
447 ALOGD_IF(isDebug(), "%s:skip layer",__FUNCTION__);
448 return MDPCOMP_ABORT;
449 }
450
451 //Request for MDP pipes
452 int pipe_pref = PIPE_REQ_VG;
453
454 if((layer_prop & MDPCOMP_LAYER_DOWNSCALE) &&
455 (layer_prop & MDPCOMP_LAYER_BLEND)) {
456 pipe_pref = PIPE_REQ_RGB;
457 }
458
459 int allocated_pipe = sPipeMgr.req_for_pipe( pipe_pref);
460 if(allocated_pipe) {
461 layer_info[index].can_use_mdp = true;
462 layer_info[index].pipe_pref = allocated_pipe;
463 current_frame.count++;
464 }else {
465 ALOGE("%s: pipe marking in mark layer fails for : %d",
466 __FUNCTION__, allocated_pipe);
467 return MDPCOMP_FAILURE;
468 }
469 }
470 return MDPCOMP_SUCCESS;
471}
472
473void MDPComp::reset_layer_mdp_info(layer_mdp_info* layer_info, int count) {
474 for(int i = 0 ; i < count; i++ ) {
475 layer_info[i].can_use_mdp = false;
476 layer_info[i].pipe_pref = PIPE_NONE;
477 }
478}
479
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700480bool MDPComp::alloc_layer_pipes(hwc_display_contents_1_t* list,
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700481 layer_mdp_info* layer_info, frame_info& current_frame) {
482
483 int layer_count = list->numHwLayers;
484 int mdp_count = current_frame.count;
485 int fallback_count = layer_count - mdp_count;
486 int frame_pipe_count = 0;
487
488 ALOGD_IF(isDebug(), "%s: dual mode: %d total count: %d \
489 mdp count: %d fallback count: %d",
490 __FUNCTION__, (layer_count != mdp_count),
491 layer_count, mdp_count, fallback_count);
492
493 for(int index = 0 ; index < layer_count ; index++ ) {
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700494 hwc_layer_1_t* layer = &list->hwLayers[index];
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700495
496 if(layer_info[index].can_use_mdp) {
497 pipe_layer_pair& info = current_frame.pipe_layer[frame_pipe_count];
498 mdp_pipe_info& pipe_info = info.pipe_index;
499
500 pipe_info.index = sPipeMgr.assign_pipe(layer_info[index].pipe_pref);
501 pipe_info.isVG = (layer_info[index].pipe_pref == PIPE_REQ_VG);
502 pipe_info.isFG = (frame_pipe_count == 0);
503 /* if VAR pipe is attached to FB, FB will be updated with
504 VSYNC WAIT flag, so no need to set VSYNC WAIT for any
505 bypass pipes. if not, set VSYNC WAIT to the last updating pipe*/
506 pipe_info.vsync_wait =
507 (sPipeMgr.getStatus(VAR_INDEX) == PIPE_IN_FB_MODE) ? false:
508 (frame_pipe_count == (mdp_count - 1));
509 /* All the layers composed on FB will have MDP zorder 0, so start
510 assigning from 1*/
511 pipe_info.z_order = index -
512 (fallback_count ? fallback_count - 1 : fallback_count);
513
514 info.layer_index = index;
515 frame_pipe_count++;
516 }
517 }
518 return 1;
519}
520
521//returns array of layers and their allocated pipes
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700522bool MDPComp::parse_and_allocate(hwc_context_t* ctx, hwc_display_contents_1_t* list,
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700523 frame_info& current_frame ) {
524
525 int layer_count = list->numHwLayers;
526
527 /* clear pipe status */
528 sPipeMgr.reset();
529
530 layer_mdp_info* bp_layer_info = (layer_mdp_info*)
531 malloc(sizeof(layer_mdp_info)* layer_count);
532
533 reset_layer_mdp_info(bp_layer_info, layer_count);
534
535 /* iterate through layer list to mark candidate */
536 if(mark_layers(list, bp_layer_info, current_frame) == MDPCOMP_ABORT) {
537 free(bp_layer_info);
538 current_frame.count = 0;
539 ALOGE_IF(isDebug(), "%s:mark_layers failed!!", __FUNCTION__);
540 return false;
541 }
542 current_frame.pipe_layer = (pipe_layer_pair*)
543 malloc(sizeof(pipe_layer_pair) * current_frame.count);
544
545 /* allocate MDP pipes for marked layers */
546 alloc_layer_pipes( list, bp_layer_info, current_frame);
547
548 free(bp_layer_info);
549 return true;
550}
551#if SUPPORT_4LAYER
552int MDPComp::configure_var_pipe(hwc_context_t* ctx) {
553
554 if(!ctx) {
555 ALOGE("%s: invalid context", __FUNCTION__);
556 return -1;
557 }
558
559 framebuffer_device_t *fbDev = ctx->fbDev;
560 if (!fbDev) {
561 ALOGE("%s: fbDev is NULL", __FUNCTION__);
562 return -1;
563 }
564
565 int new_mode = -1, cur_mode;
566 fbDev->perform(fbDev,EVENT_GET_VAR_PIPE_MODE, (void*)&cur_mode);
567
568 if(sPipeMgr.getStatus(VAR_INDEX) == PIPE_IN_FB_MODE) {
569 new_mode = VAR_PIPE_FB_ATTACH;
570 } else if(sPipeMgr.getStatus(VAR_INDEX) == PIPE_IN_BYP_MODE) {
571 new_mode = VAR_PIPE_FB_DETACH;
572 fbDev->perform(fbDev,EVENT_WAIT_POSTBUFFER,NULL);
573 }
574
575 ALOGD_IF(isDebug(),"%s: old_mode: %d new_mode: %d", __FUNCTION__,
576 cur_mode, new_mode);
577
578 if((new_mode != cur_mode) && (new_mode >= 0)) {
579 if(fbDev->perform(fbDev,EVENT_SET_VAR_PIPE_MODE,(void*)&new_mode) < 0) {
580 ALOGE("%s: Setting var pipe mode failed", __FUNCTION__);
581 }
582 }
583
584 return 0;
585}
586#endif
587
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700588bool MDPComp::setup(hwc_context_t* ctx, hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700589 int nPipeIndex, vsync_wait, isFG;
590 int numHwLayers = list->numHwLayers;
591
592 frame_info &current_frame = sCurrentFrame;
593 current_frame.count = 0;
594
595 if(!ctx) {
596 ALOGE("%s: invalid context", __FUNCTION__);
597 return -1;
598 }
599
600 framebuffer_device_t *fbDev = ctx->mFbDev;
601 if (!fbDev) {
602 ALOGE("%s: fbDev is NULL", __FUNCTION__);
603 return -1;
604 }
605
606 if(!parse_and_allocate(ctx, list, current_frame)) {
607#if SUPPORT_4LAYER
608 int mode = VAR_PIPE_FB_ATTACH;
609 if(fbDev->perform(fbDev,EVENT_SET_VAR_PIPE_MODE,(void*)&mode) < 0 ) {
610 ALOGE("%s: setting var pipe mode failed", __FUNCTION__);
611 }
612#endif
613 ALOGD_IF(isDebug(), "%s: Falling back to FB", __FUNCTION__);
614 return false;
615 }
616#if SUPPORT_4LAYER
617 configure_var_pipe(ctx);
618#endif
619
620 overlay::Overlay& ov = *(ctx->mOverlay);
621 ovutils::eOverlayState state = ov.getState();
622
623 if (current_frame.count == 1) {
624 state = ovutils::OV_BYPASS_1_LAYER;
625 } else if (current_frame.count == 2) {
626 state = ovutils::OV_BYPASS_2_LAYER;
627 } else if (current_frame.count == 3) {
628 state = ovutils::OV_BYPASS_3_LAYER;
629 }
630
631 ov.setState(state);
632
633
634 for (int index = 0 ; index < current_frame.count; index++) {
635 int layer_index = current_frame.pipe_layer[index].layer_index;
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700636 hwc_layer_1_t* layer = &list->hwLayers[layer_index];
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700637 mdp_pipe_info& cur_pipe = current_frame.pipe_layer[index].pipe_index;
638
639 if( prepare(ctx, layer, cur_pipe) != 0 ) {
640 ALOGD_IF(isDebug(), "%s: MDPComp failed to configure overlay for \
641 layer %d with pipe index:%d",__FUNCTION__,
642 index, cur_pipe.index);
643 return false;
644 } else {
645 setLayerIndex(layer, index);
646 }
647 }
648 return true;
649}
650
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700651void MDPComp::unsetMDPCompLayerFlags(hwc_context_t* ctx, hwc_display_contents_1_t* list)
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700652{
653 if (!list)
654 return;
655
656 for (int index = 0 ; index < sCurrentFrame.count; index++) {
657 int l_index = sCurrentFrame.pipe_layer[index].layer_index;
658 if(list->hwLayers[l_index].flags & HWC_MDPCOMP) {
659 list->hwLayers[l_index].flags &= ~HWC_MDPCOMP;
660 }
Naseer Ahmedfb4cbdd2012-08-16 15:54:53 -0700661
662 if(list->hwLayers[l_index].compositionType == HWC_OVERLAY) {
663 list->hwLayers[l_index].compositionType = HWC_FRAMEBUFFER;
664 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700665 }
666}
667
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700668int MDPComp::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700669
670 if(!isEnabled()) {
671 ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled",__FUNCTION__);
672 return 0;
673 }
674
675 if(!ctx || !list) {
676 ALOGE("%s: invalid contxt or list",__FUNCTION__);
677 return -1;
678 }
679
680 overlay::Overlay& ov = *(ctx->mOverlay);
681
682 for(unsigned int i = 0; i < list->numHwLayers; i++ )
683 {
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700684 hwc_layer_1_t *layer = &list->hwLayers[i];
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700685
686 if(!(layer->flags & HWC_MDPCOMP)) {
687 ALOGD_IF(isDebug(), "%s: Layer Not flagged for MDP comp",
688 __FUNCTION__);
689 continue;
690 }
691
692 int data_index = getLayerIndex(layer);
693 mdp_pipe_info& pipe_info =
694 sCurrentFrame.pipe_layer[data_index].pipe_index;
695 int index = pipe_info.index;
696
697 if(index < 0) {
698 ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, index);
699 return -1;
700 }
701
702 /* reset Invalidator */
703 if(idleInvalidator)
704 idleInvalidator->markForSleep();
705
706 ovutils::eDest dest;
707
708 if (index == 0) {
709 dest = ovutils::OV_PIPE0;
710 } else if (index == 1) {
711 dest = ovutils::OV_PIPE1;
712 } else if (index == 2) {
713 dest = ovutils::OV_PIPE2;
714 }
715
716 if (ctx ) {
717 private_handle_t *hnd = (private_handle_t *)layer->handle;
718 if(!hnd) {
719 ALOGE("%s handle null", __FUNCTION__);
720 return -1;
721 }
722
723 //lock buffer before queue
724 //XXX: Handle lock failure
725 ctx->qbuf->lockAndAdd(hnd);
726
727 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
728 using pipe: %d", __FUNCTION__, layer,
729 hnd, index );
730
731 if (!ov.queueBuffer(hnd->fd, hnd->offset, dest)) {
732 ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
733 return -1;
734 }
735 }
736 layer->flags &= ~HWC_MDPCOMP;
737 layer->flags |= HWC_MDPCOMP_INDEX_MASK;
738 }
739 return 0;
740}
741
742bool MDPComp::init(hwc_context_t *dev) {
743
744 if(!dev) {
745 ALOGE("%s: Invalid hwc context!!",__FUNCTION__);
746 return false;
747 }
748
749#if SUPPORT_4LAYER
750 if(MAX_MDPCOMP_LAYERS > MAX_STATIC_PIPES) {
751 framebuffer_device_t *fbDev = dev->fbDevice;
752 if(fbDev == NULL) {
753 ALOGE("%s: FATAL: framebuffer device is NULL", __FUNCTION__);
754 return false;
755 }
756
757 //Receive VAR pipe object from framebuffer
758 if(fbDev->perform(fbDev,EVENT_GET_VAR_PIPE,(void*)&ov) < 0) {
759 ALOGE("%s: FATAL: getVariablePipe failed!!", __FUNCTION__);
760 return false;
761 }
762
763 sPipeMgr.setStatus(VAR_INDEX, PIPE_IN_FB_MODE);
764 }
765#endif
766 char property[PROPERTY_VALUE_MAX];
767
768 sMaxLayers = 0;
769 if(property_get("debug.mdpcomp.maxlayer", property, NULL) > 0) {
770 if(atoi(property) != 0)
771 sMaxLayers = atoi(property);
772 }
773
774 sDebugLogs = false;
775 if(property_get("debug.mdpcomp.logs", property, NULL) > 0) {
776 if(atoi(property) != 0)
777 sDebugLogs = true;
778 }
779
780 unsigned long idle_timeout = DEFAULT_IDLE_TIME;
781 if(property_get("debug.mdpcomp.idletime", property, NULL) > 0) {
782 if(atoi(property) != 0)
783 idle_timeout = atoi(property);
784 }
785
786 //create Idle Invalidator
787 idleInvalidator = IdleInvalidator::getInstance();
788
789 if(idleInvalidator == NULL) {
790 ALOGE("%s: failed to instantiate idleInvalidator object", __FUNCTION__);
791 } else {
792 idleInvalidator->init(timeout_handler, dev, idle_timeout);
793 }
794 return true;
795}
796
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700797bool MDPComp::configure(hwc_composer_device_1_t *dev, hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700798
799 if(!isEnabled()) {
800 ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
801 return false;
802 }
803
804 hwc_context_t* ctx = (hwc_context_t*)(dev);
805
806 bool isMDPCompUsed = true;
807 bool doable = is_doable(dev, list);
808
809 if(doable) {
810 if(setup(ctx, list)) {
811 setMDPCompLayerFlags(list);
812 sMDPCompState = MDPCOMP_ON;
813 } else {
814 ALOGD_IF(isDebug(),"%s: MDP Comp Failed",__FUNCTION__);
815 isMDPCompUsed = false;
816 }
817 } else {
818 ALOGD_IF( isDebug(),"%s: MDP Comp not possible[%d]",__FUNCTION__,
819 doable);
820 isMDPCompUsed = false;
821 }
822
823 //Reset states
824 if(!isMDPCompUsed) {
825 //Reset current frame
826 reset(ctx, list);
827 }
828
829 sIdleFallBack = false;
830
831 return isMDPCompUsed;
832}
833}; //namespace
834