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