blob: 146b6f268ac8d75c882fd1b6e2d48208eaa93280 [file] [log] [blame]
Naseer Ahmed7c958d42012-07-31 18:57:03 -07001/*
Saurabh Shah56f610d2012-08-07 15:27:06 -07002 * Copyright (C) 2012, The Linux Foundation. All rights reserved.
Naseer Ahmed7c958d42012-07-31 18:57:03 -07003 * Not a Contribution, Apache license notifications and license are retained
4 * for attribution purposes only.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19#include "hwc_mdpcomp.h"
20#include "hwc_qbuf.h"
Saurabh Shah56f610d2012-08-07 15:27:06 -070021#include "external.h"
Naseer Ahmed7c958d42012-07-31 18:57:03 -070022
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;
Saurabh Shah799a3972012-09-01 12:16:12 -0700285 ovutils::setMdpFlags(mdpFlags,ovutils::OV_MDP_BACKEND_COMPOSITION);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700286 ovutils::eIsFg isFG = mdp_info.isFG ? ovutils::IS_FG_SET
287 : ovutils::IS_FG_OFF;
288 ovutils::PipeArgs parg(mdpFlags,
289 info,
290 zOrder,
291 isFG,
292 ovutils::ROT_FLAG_DISABLED);
293
294 ovutils::PipeArgs pargs[MAX_PIPES] = { parg, parg, parg };
295 if (!ov.setSource(pargs, dest)) {
296 ALOGE("%s: setSource failed", __FUNCTION__);
297 return -1;
298 }
299
300 ovutils::Dim dcrop(crop.left, crop.top, crop_w, crop_h);
301 if (!ov.setCrop(dcrop, dest)) {
302 ALOGE("%s: setCrop failed", __FUNCTION__);
303 return -1;
304 }
305
306 ovutils::Dim dim(dst.left, dst.top, dst_w, dst_h);
307 if (!ov.setPosition(dim, dest)) {
308 ALOGE("%s: setPosition failed", __FUNCTION__);
309 return -1;
310 }
311
312 ALOGD_IF(isDebug(),"%s: MDP set: crop[%d,%d,%d,%d] dst[%d,%d,%d,%d] \
313 nPipe: %d isFG: %d zorder: %d",__FUNCTION__, dcrop.x,
314 dcrop.y,dcrop.w, dcrop.h, dim.x, dim.y, dim.w, dim.h,
315 nPipeIndex,mdp_info.isFG, mdp_info.z_order);
316
317 if (!ov.commit(dest)) {
318 ALOGE("%s: commit failed", __FUNCTION__);
319 return -1;
320 }
321 }
322 return 0;
323}
324
325/*
326 * MDPComp not possible when
327 * 1. We have more than sMaxLayers
328 * 2. External display connected
329 * 3. Composition is triggered by
330 * Idle timer expiry
331 * 4. Rotation is needed
332 * 5. Overlay in use
333 */
334
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700335bool MDPComp::is_doable(hwc_composer_device_1_t *dev,
Naseer Ahmedfb4cbdd2012-08-16 15:54:53 -0700336 hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700337 hwc_context_t* ctx = (hwc_context_t*)(dev);
338
339 if(!ctx) {
340 ALOGE("%s: hwc context is NULL", __FUNCTION__);
341 return false;
342 }
343
344 //Number of layers
Naseer Ahmedb90d0912012-07-31 13:09:51 -0700345 if(list->numHwLayers < 1 || list->numHwLayers > (uint32_t)sMaxLayers) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700346 ALOGD_IF(isDebug(), "%s: Unsupported number of layers",__FUNCTION__);
347 return false;
348 }
349
350 //Disable MDPComp when ext display connected
351 if(ctx->mExtDisplay->getExternalDisplay()) {
352 ALOGD_IF(isDebug(), "%s: External display connected.", __FUNCTION__);
Saurabh Shahb45b8812012-08-19 18:36:59 +0530353 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700354 }
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