blob: d5266c24b5b625d8000af1803379d582b6a5e9d1 [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;
Naseer Ahmed52ca6d22012-10-08 14:03:01 -0400133 if(sCurrentFrame.pipe_layer) {
134 free(sCurrentFrame.pipe_layer);
135 sCurrentFrame.pipe_layer = NULL;
136 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700137
138 //Reset MDP pipes
139 sPipeMgr.reset();
140 sPipeMgr.setStatus(VAR_INDEX, PIPE_IN_FB_MODE);
141
142#if SUPPORT_4LAYER
143 configure_var_pipe(ctx);
144#endif
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700145}
146
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700147void MDPComp::setLayerIndex(hwc_layer_1_t* layer, const int pipe_index)
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700148{
149 layer->flags &= ~HWC_MDPCOMP_INDEX_MASK;
150 layer->flags |= pipe_index << MDPCOMP_INDEX_OFFSET;
151}
152
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700153int MDPComp::getLayerIndex(hwc_layer_1_t* layer)
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700154{
155 int byp_index = -1;
156
157 if(layer->flags & HWC_MDPCOMP) {
158 byp_index = ((layer->flags & HWC_MDPCOMP_INDEX_MASK) >>
159 MDPCOMP_INDEX_OFFSET);
160 byp_index = (byp_index < sMaxLayers ? byp_index : -1 );
161 }
162 return byp_index;
163}
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700164void MDPComp::print_info(hwc_layer_1_t* layer)
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700165{
166 hwc_rect_t sourceCrop = layer->sourceCrop;
167 hwc_rect_t displayFrame = layer->displayFrame;
168
169 int s_l = sourceCrop.left;
170 int s_t = sourceCrop.top;
171 int s_r = sourceCrop.right;
172 int s_b = sourceCrop.bottom;
173
174 int d_l = displayFrame.left;
175 int d_t = displayFrame.top;
176 int d_r = displayFrame.right;
177 int d_b = displayFrame.bottom;
178
179 ALOGD_IF(isDebug(), "src:[%d,%d,%d,%d] (%d x %d) \
180 dst:[%d,%d,%d,%d] (%d x %d)",
181 s_l, s_t, s_r, s_b, (s_r - s_l), (s_b - s_t),
182 d_l, d_t, d_r, d_b, (d_r - d_l), (d_b - d_t));
183}
184/*
185 * Configures pipe(s) for MDP composition
186 */
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700187int MDPComp::prepare(hwc_context_t *ctx, hwc_layer_1_t *layer,
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700188 mdp_pipe_info& mdp_info) {
189
190 int nPipeIndex = mdp_info.index;
191
192 if (ctx) {
193
194 private_handle_t *hnd = (private_handle_t *)layer->handle;
195
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700196 overlay::Overlay& ov = *(ctx->mOverlay[HWC_DISPLAY_PRIMARY]);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700197
198 if(!hnd) {
199 ALOGE("%s: layer handle is NULL", __FUNCTION__);
200 return -1;
201 }
202
203
204 int hw_w = ctx->mFbDev->width;
205 int hw_h = ctx->mFbDev->height;
206
207
208 hwc_rect_t sourceCrop = layer->sourceCrop;
209 hwc_rect_t displayFrame = layer->displayFrame;
210
211 const int src_w = sourceCrop.right - sourceCrop.left;
212 const int src_h = sourceCrop.bottom - sourceCrop.top;
213
214 hwc_rect_t crop = sourceCrop;
215 int crop_w = crop.right - crop.left;
216 int crop_h = crop.bottom - crop.top;
217
218 hwc_rect_t dst = displayFrame;
219 int dst_w = dst.right - dst.left;
220 int dst_h = dst.bottom - dst.top;
221
222 //REDUNDANT ??
223 if(hnd != NULL &&
224 (hnd->flags & private_handle_t::PRIV_FLAGS_NONCONTIGUOUS_MEM )) {
225 ALOGE("%s: failed due to non-pmem memory",__FUNCTION__);
226 return -1;
227 }
228
229 if(dst.left < 0 || dst.top < 0 ||
230 dst.right > hw_w || dst.bottom > hw_h) {
231 ALOGD_IF(isDebug(),"%s: Destination has negative coordinates",
232 __FUNCTION__);
233
234 qhwc::calculate_crop_rects(crop, dst, hw_w, hw_h);
235
236 //Update calulated width and height
237 crop_w = crop.right - crop.left;
238 crop_h = crop.bottom - crop.top;
239
240 dst_w = dst.right - dst.left;
241 dst_h = dst.bottom - dst.top;
242 }
243
244 if( (dst_w > hw_w)|| (dst_h > hw_h)) {
245 ALOGD_IF(isDebug(),"%s: Dest rect exceeds FB", __FUNCTION__);
246 print_info(layer);
247 dst_w = hw_w;
248 dst_h = hw_h;
249 }
250
251 // Determine pipe to set based on pipe index
252 ovutils::eDest dest = ovutils::OV_PIPE_ALL;
253 if (nPipeIndex == 0) {
254 dest = ovutils::OV_PIPE0;
255 } else if (nPipeIndex == 1) {
256 dest = ovutils::OV_PIPE1;
257 } else if (nPipeIndex == 2) {
258 dest = ovutils::OV_PIPE2;
259 }
260
261 ovutils::eZorder zOrder = ovutils::ZORDER_0;
262
263 if(mdp_info.z_order == 0 ) {
264 zOrder = ovutils::ZORDER_0;
265 } else if(mdp_info.z_order == 1 ) {
266 zOrder = ovutils::ZORDER_1;
267 } else if(mdp_info.z_order == 2 ) {
268 zOrder = ovutils::ZORDER_2;
269 }
270
271 // Order order order
272 // setSource - just setting source
273 // setParameter - changes src w/h/f accordingly
274 // setCrop - ROI - src_rect
275 // setPosition - dst_rect
276 // commit - commit changes to mdp driver
277 // queueBuffer - not here, happens when draw is called
278
279 ovutils::eTransform orient =
280 static_cast<ovutils::eTransform>(layer->transform);
281
282 ov.setTransform(orient, dest);
283 ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
284 ovutils::eMdpFlags mdpFlags = mdp_info.isVG ? ovutils::OV_MDP_PIPE_SHARE
285 : ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shah799a3972012-09-01 12:16:12 -0700286 ovutils::setMdpFlags(mdpFlags,ovutils::OV_MDP_BACKEND_COMPOSITION);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700287 ovutils::eIsFg isFG = mdp_info.isFG ? ovutils::IS_FG_SET
Saurabh Shah91a6a992012-08-20 15:25:28 -0700288 : ovutils::IS_FG_OFF;
289
290 if(layer->blending == HWC_BLENDING_PREMULT) {
291 ovutils::setMdpFlags(mdpFlags,
292 ovutils::OV_MDP_BLEND_FG_PREMULT);
293 }
294
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700295 ovutils::PipeArgs parg(mdpFlags,
296 info,
297 zOrder,
298 isFG,
299 ovutils::ROT_FLAG_DISABLED);
300
301 ovutils::PipeArgs pargs[MAX_PIPES] = { parg, parg, parg };
302 if (!ov.setSource(pargs, dest)) {
303 ALOGE("%s: setSource failed", __FUNCTION__);
304 return -1;
305 }
306
307 ovutils::Dim dcrop(crop.left, crop.top, crop_w, crop_h);
308 if (!ov.setCrop(dcrop, dest)) {
309 ALOGE("%s: setCrop failed", __FUNCTION__);
310 return -1;
311 }
312
313 ovutils::Dim dim(dst.left, dst.top, dst_w, dst_h);
314 if (!ov.setPosition(dim, dest)) {
315 ALOGE("%s: setPosition failed", __FUNCTION__);
316 return -1;
317 }
318
319 ALOGD_IF(isDebug(),"%s: MDP set: crop[%d,%d,%d,%d] dst[%d,%d,%d,%d] \
320 nPipe: %d isFG: %d zorder: %d",__FUNCTION__, dcrop.x,
321 dcrop.y,dcrop.w, dcrop.h, dim.x, dim.y, dim.w, dim.h,
322 nPipeIndex,mdp_info.isFG, mdp_info.z_order);
323
324 if (!ov.commit(dest)) {
325 ALOGE("%s: commit failed", __FUNCTION__);
326 return -1;
327 }
328 }
329 return 0;
330}
331
332/*
333 * MDPComp not possible when
334 * 1. We have more than sMaxLayers
335 * 2. External display connected
336 * 3. Composition is triggered by
337 * Idle timer expiry
338 * 4. Rotation is needed
339 * 5. Overlay in use
340 */
341
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700342bool MDPComp::is_doable(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700343 //Number of layers
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700344 int numAppLayers = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
345 if(numAppLayers < 1 || numAppLayers > (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
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700351 if(isExternalActive(ctx)) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700352 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.
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700363 for(int i = 0; i < numAppLayers; ++i) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700364 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
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700413int MDPComp::mark_layers(hwc_context_t *ctx,
414 hwc_display_contents_1_t* list, layer_mdp_info* layer_info,
415 frame_info& current_frame) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700416
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700417 int layer_count = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700418
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
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700480bool MDPComp::alloc_layer_pipes(hwc_context_t *ctx,
481 hwc_display_contents_1_t* list,
482 layer_mdp_info* layer_info, frame_info& current_frame) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700483
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700484 int layer_count = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700485 int mdp_count = current_frame.count;
486 int fallback_count = layer_count - mdp_count;
487 int frame_pipe_count = 0;
488
489 ALOGD_IF(isDebug(), "%s: dual mode: %d total count: %d \
490 mdp count: %d fallback count: %d",
491 __FUNCTION__, (layer_count != mdp_count),
492 layer_count, mdp_count, fallback_count);
493
494 for(int index = 0 ; index < layer_count ; index++ ) {
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700495 hwc_layer_1_t* layer = &list->hwLayers[index];
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700496
497 if(layer_info[index].can_use_mdp) {
498 pipe_layer_pair& info = current_frame.pipe_layer[frame_pipe_count];
499 mdp_pipe_info& pipe_info = info.pipe_index;
500
501 pipe_info.index = sPipeMgr.assign_pipe(layer_info[index].pipe_pref);
502 pipe_info.isVG = (layer_info[index].pipe_pref == PIPE_REQ_VG);
503 pipe_info.isFG = (frame_pipe_count == 0);
504 /* if VAR pipe is attached to FB, FB will be updated with
505 VSYNC WAIT flag, so no need to set VSYNC WAIT for any
506 bypass pipes. if not, set VSYNC WAIT to the last updating pipe*/
507 pipe_info.vsync_wait =
508 (sPipeMgr.getStatus(VAR_INDEX) == PIPE_IN_FB_MODE) ? false:
509 (frame_pipe_count == (mdp_count - 1));
510 /* All the layers composed on FB will have MDP zorder 0, so start
511 assigning from 1*/
512 pipe_info.z_order = index -
513 (fallback_count ? fallback_count - 1 : fallback_count);
514
515 info.layer_index = index;
516 frame_pipe_count++;
517 }
518 }
519 return 1;
520}
521
522//returns array of layers and their allocated pipes
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700523bool MDPComp::parse_and_allocate(hwc_context_t* ctx,
524 hwc_display_contents_1_t* list, frame_info& current_frame ) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700525
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700526 int layer_count = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700527
528 /* clear pipe status */
529 sPipeMgr.reset();
530
531 layer_mdp_info* bp_layer_info = (layer_mdp_info*)
532 malloc(sizeof(layer_mdp_info)* layer_count);
533
534 reset_layer_mdp_info(bp_layer_info, layer_count);
535
536 /* iterate through layer list to mark candidate */
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700537 if(mark_layers(ctx, list, bp_layer_info, current_frame) == MDPCOMP_ABORT) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700538 free(bp_layer_info);
539 current_frame.count = 0;
540 ALOGE_IF(isDebug(), "%s:mark_layers failed!!", __FUNCTION__);
541 return false;
542 }
543 current_frame.pipe_layer = (pipe_layer_pair*)
544 malloc(sizeof(pipe_layer_pair) * current_frame.count);
545
546 /* allocate MDP pipes for marked layers */
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700547 alloc_layer_pipes(ctx, list, bp_layer_info, current_frame);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700548
549 free(bp_layer_info);
550 return true;
551}
552#if SUPPORT_4LAYER
553int MDPComp::configure_var_pipe(hwc_context_t* ctx) {
554
555 if(!ctx) {
556 ALOGE("%s: invalid context", __FUNCTION__);
557 return -1;
558 }
559
560 framebuffer_device_t *fbDev = ctx->fbDev;
561 if (!fbDev) {
562 ALOGE("%s: fbDev is NULL", __FUNCTION__);
563 return -1;
564 }
565
566 int new_mode = -1, cur_mode;
567 fbDev->perform(fbDev,EVENT_GET_VAR_PIPE_MODE, (void*)&cur_mode);
568
569 if(sPipeMgr.getStatus(VAR_INDEX) == PIPE_IN_FB_MODE) {
570 new_mode = VAR_PIPE_FB_ATTACH;
571 } else if(sPipeMgr.getStatus(VAR_INDEX) == PIPE_IN_BYP_MODE) {
572 new_mode = VAR_PIPE_FB_DETACH;
573 fbDev->perform(fbDev,EVENT_WAIT_POSTBUFFER,NULL);
574 }
575
576 ALOGD_IF(isDebug(),"%s: old_mode: %d new_mode: %d", __FUNCTION__,
577 cur_mode, new_mode);
578
579 if((new_mode != cur_mode) && (new_mode >= 0)) {
580 if(fbDev->perform(fbDev,EVENT_SET_VAR_PIPE_MODE,(void*)&new_mode) < 0) {
581 ALOGE("%s: Setting var pipe mode failed", __FUNCTION__);
582 }
583 }
584
585 return 0;
586}
587#endif
588
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700589bool MDPComp::setup(hwc_context_t* ctx, hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700590 int nPipeIndex, vsync_wait, isFG;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700591 int numHwLayers = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700592
593 frame_info &current_frame = sCurrentFrame;
594 current_frame.count = 0;
595
Naseer Ahmed52ca6d22012-10-08 14:03:01 -0400596 if(current_frame.pipe_layer) {
597 free(current_frame.pipe_layer);
598 current_frame.pipe_layer = NULL;
599 }
600
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700601 if(!ctx) {
602 ALOGE("%s: invalid context", __FUNCTION__);
603 return -1;
604 }
605
606 framebuffer_device_t *fbDev = ctx->mFbDev;
607 if (!fbDev) {
608 ALOGE("%s: fbDev is NULL", __FUNCTION__);
609 return -1;
610 }
611
612 if(!parse_and_allocate(ctx, list, current_frame)) {
613#if SUPPORT_4LAYER
614 int mode = VAR_PIPE_FB_ATTACH;
615 if(fbDev->perform(fbDev,EVENT_SET_VAR_PIPE_MODE,(void*)&mode) < 0 ) {
616 ALOGE("%s: setting var pipe mode failed", __FUNCTION__);
617 }
618#endif
619 ALOGD_IF(isDebug(), "%s: Falling back to FB", __FUNCTION__);
620 return false;
621 }
622#if SUPPORT_4LAYER
623 configure_var_pipe(ctx);
624#endif
625
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700626 overlay::Overlay& ov = *(ctx->mOverlay[HWC_DISPLAY_PRIMARY]);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700627 ovutils::eOverlayState state = ov.getState();
628
629 if (current_frame.count == 1) {
630 state = ovutils::OV_BYPASS_1_LAYER;
631 } else if (current_frame.count == 2) {
632 state = ovutils::OV_BYPASS_2_LAYER;
633 } else if (current_frame.count == 3) {
634 state = ovutils::OV_BYPASS_3_LAYER;
635 }
636
637 ov.setState(state);
638
639
640 for (int index = 0 ; index < current_frame.count; index++) {
641 int layer_index = current_frame.pipe_layer[index].layer_index;
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700642 hwc_layer_1_t* layer = &list->hwLayers[layer_index];
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700643 mdp_pipe_info& cur_pipe = current_frame.pipe_layer[index].pipe_index;
644
645 if( prepare(ctx, layer, cur_pipe) != 0 ) {
646 ALOGD_IF(isDebug(), "%s: MDPComp failed to configure overlay for \
647 layer %d with pipe index:%d",__FUNCTION__,
648 index, cur_pipe.index);
649 return false;
650 } else {
651 setLayerIndex(layer, index);
652 }
653 }
654 return true;
655}
656
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700657void MDPComp::unsetMDPCompLayerFlags(hwc_context_t* ctx, hwc_display_contents_1_t* list)
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700658{
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700659 for (int index = 0 ; index < sCurrentFrame.count; index++) {
660 int l_index = sCurrentFrame.pipe_layer[index].layer_index;
661 if(list->hwLayers[l_index].flags & HWC_MDPCOMP) {
662 list->hwLayers[l_index].flags &= ~HWC_MDPCOMP;
663 }
Naseer Ahmedfb4cbdd2012-08-16 15:54:53 -0700664
665 if(list->hwLayers[l_index].compositionType == HWC_OVERLAY) {
666 list->hwLayers[l_index].compositionType = HWC_FRAMEBUFFER;
667 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700668 }
669}
670
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700671int MDPComp::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700672
673 if(!isEnabled()) {
674 ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled",__FUNCTION__);
675 return 0;
676 }
677
678 if(!ctx || !list) {
679 ALOGE("%s: invalid contxt or list",__FUNCTION__);
680 return -1;
681 }
682
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700683 overlay::Overlay& ov = *(ctx->mOverlay[HWC_DISPLAY_PRIMARY]);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700684
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700685 int numHwLayers = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
686 for(int i = 0; i < numHwLayers; i++ )
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700687 {
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700688 hwc_layer_1_t *layer = &list->hwLayers[i];
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700689
690 if(!(layer->flags & HWC_MDPCOMP)) {
691 ALOGD_IF(isDebug(), "%s: Layer Not flagged for MDP comp",
692 __FUNCTION__);
693 continue;
694 }
695
696 int data_index = getLayerIndex(layer);
697 mdp_pipe_info& pipe_info =
698 sCurrentFrame.pipe_layer[data_index].pipe_index;
699 int index = pipe_info.index;
700
701 if(index < 0) {
702 ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, index);
703 return -1;
704 }
705
706 /* reset Invalidator */
707 if(idleInvalidator)
708 idleInvalidator->markForSleep();
709
710 ovutils::eDest dest;
711
712 if (index == 0) {
713 dest = ovutils::OV_PIPE0;
714 } else if (index == 1) {
715 dest = ovutils::OV_PIPE1;
716 } else if (index == 2) {
717 dest = ovutils::OV_PIPE2;
718 }
719
720 if (ctx ) {
721 private_handle_t *hnd = (private_handle_t *)layer->handle;
722 if(!hnd) {
723 ALOGE("%s handle null", __FUNCTION__);
724 return -1;
725 }
726
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700727 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
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700797bool MDPComp::configure(hwc_context_t *ctx, 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
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700804 bool isMDPCompUsed = true;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700805 bool doable = is_doable(ctx, list);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700806
807 if(doable) {
808 if(setup(ctx, list)) {
809 setMDPCompLayerFlags(list);
810 sMDPCompState = MDPCOMP_ON;
811 } else {
812 ALOGD_IF(isDebug(),"%s: MDP Comp Failed",__FUNCTION__);
813 isMDPCompUsed = false;
814 }
815 } else {
816 ALOGD_IF( isDebug(),"%s: MDP Comp not possible[%d]",__FUNCTION__,
817 doable);
818 isMDPCompUsed = false;
819 }
820
821 //Reset states
822 if(!isMDPCompUsed) {
823 //Reset current frame
824 reset(ctx, list);
825 }
826
827 sIdleFallBack = false;
828
829 return isMDPCompUsed;
830}
831}; //namespace
832