blob: 7f80be6525b197837e715eb357496bab343bc184 [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__);
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
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700373void MDPComp::setMDPCompLayerFlags(hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700374
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) {
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700379 hwc_layer_1_t* layer = &(list->hwLayers[layer_index]);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700380
381 layer->flags |= HWC_MDPCOMP;
382 layer->compositionType = HWC_OVERLAY;
383 layer->hints |= HWC_HINT_CLEAR_FB;
384 }
385 }
386}
387
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700388void MDPComp::get_layer_info(hwc_layer_1_t* layer, int& flags) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700389
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
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700413int MDPComp::mark_layers(hwc_display_contents_1_t* list, layer_mdp_info* layer_info,
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700414 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-- ) {
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700427 hwc_layer_1_t* layer = &list->hwLayers[index];
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700428
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
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700479bool MDPComp::alloc_layer_pipes(hwc_display_contents_1_t* list,
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700480 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++ ) {
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700493 hwc_layer_1_t* layer = &list->hwLayers[index];
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700494
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
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700521bool MDPComp::parse_and_allocate(hwc_context_t* ctx, hwc_display_contents_1_t* list,
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700522 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
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700587bool MDPComp::setup(hwc_context_t* ctx, hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700588 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;
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700635 hwc_layer_1_t* layer = &list->hwLayers[layer_index];
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700636 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
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700650void MDPComp::unsetMDPCompLayerFlags(hwc_context_t* ctx, hwc_display_contents_1_t* list)
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700651{
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 }
Naseer Ahmedfb4cbdd2012-08-16 15:54:53 -0700660
661 if(list->hwLayers[l_index].compositionType == HWC_OVERLAY) {
662 list->hwLayers[l_index].compositionType = HWC_FRAMEBUFFER;
663 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700664 }
665}
666
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700667int MDPComp::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700668
669 if(!isEnabled()) {
670 ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled",__FUNCTION__);
671 return 0;
672 }
673
674 if(!ctx || !list) {
675 ALOGE("%s: invalid contxt or list",__FUNCTION__);
676 return -1;
677 }
678
679 overlay::Overlay& ov = *(ctx->mOverlay);
680
681 for(unsigned int i = 0; i < list->numHwLayers; i++ )
682 {
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700683 hwc_layer_1_t *layer = &list->hwLayers[i];
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700684
685 if(!(layer->flags & HWC_MDPCOMP)) {
686 ALOGD_IF(isDebug(), "%s: Layer Not flagged for MDP comp",
687 __FUNCTION__);
688 continue;
689 }
690
691 int data_index = getLayerIndex(layer);
692 mdp_pipe_info& pipe_info =
693 sCurrentFrame.pipe_layer[data_index].pipe_index;
694 int index = pipe_info.index;
695
696 if(index < 0) {
697 ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, index);
698 return -1;
699 }
700
701 /* reset Invalidator */
702 if(idleInvalidator)
703 idleInvalidator->markForSleep();
704
705 ovutils::eDest dest;
706
707 if (index == 0) {
708 dest = ovutils::OV_PIPE0;
709 } else if (index == 1) {
710 dest = ovutils::OV_PIPE1;
711 } else if (index == 2) {
712 dest = ovutils::OV_PIPE2;
713 }
714
715 if (ctx ) {
716 private_handle_t *hnd = (private_handle_t *)layer->handle;
717 if(!hnd) {
718 ALOGE("%s handle null", __FUNCTION__);
719 return -1;
720 }
721
722 //lock buffer before queue
723 //XXX: Handle lock failure
724 ctx->qbuf->lockAndAdd(hnd);
725
726 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
727 using pipe: %d", __FUNCTION__, layer,
728 hnd, index );
729
730 if (!ov.queueBuffer(hnd->fd, hnd->offset, dest)) {
731 ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
732 return -1;
733 }
734 }
735 layer->flags &= ~HWC_MDPCOMP;
736 layer->flags |= HWC_MDPCOMP_INDEX_MASK;
737 }
738 return 0;
739}
740
741bool MDPComp::init(hwc_context_t *dev) {
742
743 if(!dev) {
744 ALOGE("%s: Invalid hwc context!!",__FUNCTION__);
745 return false;
746 }
747
748#if SUPPORT_4LAYER
749 if(MAX_MDPCOMP_LAYERS > MAX_STATIC_PIPES) {
750 framebuffer_device_t *fbDev = dev->fbDevice;
751 if(fbDev == NULL) {
752 ALOGE("%s: FATAL: framebuffer device is NULL", __FUNCTION__);
753 return false;
754 }
755
756 //Receive VAR pipe object from framebuffer
757 if(fbDev->perform(fbDev,EVENT_GET_VAR_PIPE,(void*)&ov) < 0) {
758 ALOGE("%s: FATAL: getVariablePipe failed!!", __FUNCTION__);
759 return false;
760 }
761
762 sPipeMgr.setStatus(VAR_INDEX, PIPE_IN_FB_MODE);
763 }
764#endif
765 char property[PROPERTY_VALUE_MAX];
766
767 sMaxLayers = 0;
768 if(property_get("debug.mdpcomp.maxlayer", property, NULL) > 0) {
769 if(atoi(property) != 0)
770 sMaxLayers = atoi(property);
771 }
772
773 sDebugLogs = false;
774 if(property_get("debug.mdpcomp.logs", property, NULL) > 0) {
775 if(atoi(property) != 0)
776 sDebugLogs = true;
777 }
778
779 unsigned long idle_timeout = DEFAULT_IDLE_TIME;
780 if(property_get("debug.mdpcomp.idletime", property, NULL) > 0) {
781 if(atoi(property) != 0)
782 idle_timeout = atoi(property);
783 }
784
785 //create Idle Invalidator
786 idleInvalidator = IdleInvalidator::getInstance();
787
788 if(idleInvalidator == NULL) {
789 ALOGE("%s: failed to instantiate idleInvalidator object", __FUNCTION__);
790 } else {
791 idleInvalidator->init(timeout_handler, dev, idle_timeout);
792 }
793 return true;
794}
795
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700796bool MDPComp::configure(hwc_composer_device_1_t *dev, hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700797
798 if(!isEnabled()) {
799 ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
800 return false;
801 }
802
803 hwc_context_t* ctx = (hwc_context_t*)(dev);
804
805 bool isMDPCompUsed = true;
806 bool doable = is_doable(dev, list);
807
808 if(doable) {
809 if(setup(ctx, list)) {
810 setMDPCompLayerFlags(list);
811 sMDPCompState = MDPCOMP_ON;
812 } else {
813 ALOGD_IF(isDebug(),"%s: MDP Comp Failed",__FUNCTION__);
814 isMDPCompUsed = false;
815 }
816 } else {
817 ALOGD_IF( isDebug(),"%s: MDP Comp not possible[%d]",__FUNCTION__,
818 doable);
819 isMDPCompUsed = false;
820 }
821
822 //Reset states
823 if(!isMDPCompUsed) {
824 //Reset current frame
825 reset(ctx, list);
826 }
827
828 sIdleFallBack = false;
829
830 return isMDPCompUsed;
831}
832}; //namespace
833