blob: 213b74e104f93b360ed264463e893c44c0df7657 [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
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
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700336bool MDPComp::is_doable(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700337 //Number of layers
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700338 int numAppLayers = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
339 if(numAppLayers < 1 || numAppLayers > (uint32_t)sMaxLayers) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700340 ALOGD_IF(isDebug(), "%s: Unsupported number of layers",__FUNCTION__);
341 return false;
342 }
343
344 //Disable MDPComp when ext display connected
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700345 if(isExternalActive(ctx)) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700346 ALOGD_IF(isDebug(), "%s: External display connected.", __FUNCTION__);
Saurabh Shahb45b8812012-08-19 18:36:59 +0530347 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700348 }
349
350 //FB composition on idle timeout
351 if(sIdleFallBack) {
352 ALOGD_IF(isDebug(), "%s: idle fallback",__FUNCTION__);
353 return false;
354 }
355
356 //MDP composition is not efficient if rotation is needed.
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700357 for(int i = 0; i < numAppLayers; ++i) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700358 if(list->hwLayers[i].transform) {
359 ALOGD_IF(isDebug(), "%s: orientation involved",__FUNCTION__);
360 return false;
361 }
362 }
363
364 return true;
365}
366
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700367void MDPComp::setMDPCompLayerFlags(hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700368
369 for(int index = 0 ; index < sCurrentFrame.count; index++ )
370 {
371 int layer_index = sCurrentFrame.pipe_layer[index].layer_index;
372 if(layer_index >= 0) {
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700373 hwc_layer_1_t* layer = &(list->hwLayers[layer_index]);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700374
375 layer->flags |= HWC_MDPCOMP;
376 layer->compositionType = HWC_OVERLAY;
377 layer->hints |= HWC_HINT_CLEAR_FB;
378 }
379 }
380}
381
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700382void MDPComp::get_layer_info(hwc_layer_1_t* layer, int& flags) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700383
384 private_handle_t* hnd = (private_handle_t*)layer->handle;
385
386 if(layer->flags & HWC_SKIP_LAYER) {
387 flags |= MDPCOMP_LAYER_SKIP;
388 } else if(hnd != NULL &&
389 (hnd->flags & private_handle_t::PRIV_FLAGS_NONCONTIGUOUS_MEM )) {
390 flags |= MDPCOMP_LAYER_UNSUPPORTED_MEM;
391 }
392
393 if(layer->blending != HWC_BLENDING_NONE)
394 flags |= MDPCOMP_LAYER_BLEND;
395
396 int dst_w, dst_h;
397 getLayerResolution(layer, dst_w, dst_h);
398
399 hwc_rect_t sourceCrop = layer->sourceCrop;
400 const int src_w = sourceCrop.right - sourceCrop.left;
401 const int src_h = sourceCrop.bottom - sourceCrop.top;
402 if(((src_w > dst_w) || (src_h > dst_h))) {
403 flags |= MDPCOMP_LAYER_DOWNSCALE;
404 }
405}
406
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700407int MDPComp::mark_layers(hwc_context_t *ctx,
408 hwc_display_contents_1_t* list, layer_mdp_info* layer_info,
409 frame_info& current_frame) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700410
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700411 int layer_count = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700412
413 if(layer_count > sMaxLayers) {
414 if(!sPipeMgr.req_for_pipe(PIPE_REQ_FB)) {
415 ALOGE("%s: binding var pipe to FB failed!!", __FUNCTION__);
416 return 0;
417 }
418 }
419
420 //Parse layers from higher z-order
421 for(int index = layer_count - 1 ; index >= 0; index-- ) {
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700422 hwc_layer_1_t* layer = &list->hwLayers[index];
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700423
424 int layer_prop = 0;
425 get_layer_info(layer, layer_prop);
426
427 ALOGD_IF(isDebug(),"%s: prop for layer [%d]: %x", __FUNCTION__,
428 index, layer_prop);
429
430 //Both in cases of NON-CONTIGUOUS memory or SKIP layer,
431 //current version of mdp composition falls back completely to FB
432 //composition.
433 //TO DO: Support dual mode composition
434
435 if(layer_prop & MDPCOMP_LAYER_UNSUPPORTED_MEM) {
436 ALOGD_IF(isDebug(), "%s: Non contigous memory",__FUNCTION__);
437 return MDPCOMP_ABORT;
438 }
439
440 if(layer_prop & MDPCOMP_LAYER_SKIP) {
441 ALOGD_IF(isDebug(), "%s:skip layer",__FUNCTION__);
442 return MDPCOMP_ABORT;
443 }
444
445 //Request for MDP pipes
446 int pipe_pref = PIPE_REQ_VG;
447
448 if((layer_prop & MDPCOMP_LAYER_DOWNSCALE) &&
449 (layer_prop & MDPCOMP_LAYER_BLEND)) {
450 pipe_pref = PIPE_REQ_RGB;
451 }
452
453 int allocated_pipe = sPipeMgr.req_for_pipe( pipe_pref);
454 if(allocated_pipe) {
455 layer_info[index].can_use_mdp = true;
456 layer_info[index].pipe_pref = allocated_pipe;
457 current_frame.count++;
458 }else {
459 ALOGE("%s: pipe marking in mark layer fails for : %d",
460 __FUNCTION__, allocated_pipe);
461 return MDPCOMP_FAILURE;
462 }
463 }
464 return MDPCOMP_SUCCESS;
465}
466
467void MDPComp::reset_layer_mdp_info(layer_mdp_info* layer_info, int count) {
468 for(int i = 0 ; i < count; i++ ) {
469 layer_info[i].can_use_mdp = false;
470 layer_info[i].pipe_pref = PIPE_NONE;
471 }
472}
473
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700474bool MDPComp::alloc_layer_pipes(hwc_context_t *ctx,
475 hwc_display_contents_1_t* list,
476 layer_mdp_info* layer_info, frame_info& current_frame) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700477
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700478 int layer_count = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700479 int mdp_count = current_frame.count;
480 int fallback_count = layer_count - mdp_count;
481 int frame_pipe_count = 0;
482
483 ALOGD_IF(isDebug(), "%s: dual mode: %d total count: %d \
484 mdp count: %d fallback count: %d",
485 __FUNCTION__, (layer_count != mdp_count),
486 layer_count, mdp_count, fallback_count);
487
488 for(int index = 0 ; index < layer_count ; index++ ) {
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700489 hwc_layer_1_t* layer = &list->hwLayers[index];
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700490
491 if(layer_info[index].can_use_mdp) {
492 pipe_layer_pair& info = current_frame.pipe_layer[frame_pipe_count];
493 mdp_pipe_info& pipe_info = info.pipe_index;
494
495 pipe_info.index = sPipeMgr.assign_pipe(layer_info[index].pipe_pref);
496 pipe_info.isVG = (layer_info[index].pipe_pref == PIPE_REQ_VG);
497 pipe_info.isFG = (frame_pipe_count == 0);
498 /* if VAR pipe is attached to FB, FB will be updated with
499 VSYNC WAIT flag, so no need to set VSYNC WAIT for any
500 bypass pipes. if not, set VSYNC WAIT to the last updating pipe*/
501 pipe_info.vsync_wait =
502 (sPipeMgr.getStatus(VAR_INDEX) == PIPE_IN_FB_MODE) ? false:
503 (frame_pipe_count == (mdp_count - 1));
504 /* All the layers composed on FB will have MDP zorder 0, so start
505 assigning from 1*/
506 pipe_info.z_order = index -
507 (fallback_count ? fallback_count - 1 : fallback_count);
508
509 info.layer_index = index;
510 frame_pipe_count++;
511 }
512 }
513 return 1;
514}
515
516//returns array of layers and their allocated pipes
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700517bool MDPComp::parse_and_allocate(hwc_context_t* ctx,
518 hwc_display_contents_1_t* list, frame_info& current_frame ) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700519
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700520 int layer_count = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700521
522 /* clear pipe status */
523 sPipeMgr.reset();
524
525 layer_mdp_info* bp_layer_info = (layer_mdp_info*)
526 malloc(sizeof(layer_mdp_info)* layer_count);
527
528 reset_layer_mdp_info(bp_layer_info, layer_count);
529
530 /* iterate through layer list to mark candidate */
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700531 if(mark_layers(ctx, list, bp_layer_info, current_frame) == MDPCOMP_ABORT) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700532 free(bp_layer_info);
533 current_frame.count = 0;
534 ALOGE_IF(isDebug(), "%s:mark_layers failed!!", __FUNCTION__);
535 return false;
536 }
537 current_frame.pipe_layer = (pipe_layer_pair*)
538 malloc(sizeof(pipe_layer_pair) * current_frame.count);
539
540 /* allocate MDP pipes for marked layers */
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700541 alloc_layer_pipes(ctx, list, bp_layer_info, current_frame);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700542
543 free(bp_layer_info);
544 return true;
545}
546#if SUPPORT_4LAYER
547int MDPComp::configure_var_pipe(hwc_context_t* ctx) {
548
549 if(!ctx) {
550 ALOGE("%s: invalid context", __FUNCTION__);
551 return -1;
552 }
553
554 framebuffer_device_t *fbDev = ctx->fbDev;
555 if (!fbDev) {
556 ALOGE("%s: fbDev is NULL", __FUNCTION__);
557 return -1;
558 }
559
560 int new_mode = -1, cur_mode;
561 fbDev->perform(fbDev,EVENT_GET_VAR_PIPE_MODE, (void*)&cur_mode);
562
563 if(sPipeMgr.getStatus(VAR_INDEX) == PIPE_IN_FB_MODE) {
564 new_mode = VAR_PIPE_FB_ATTACH;
565 } else if(sPipeMgr.getStatus(VAR_INDEX) == PIPE_IN_BYP_MODE) {
566 new_mode = VAR_PIPE_FB_DETACH;
567 fbDev->perform(fbDev,EVENT_WAIT_POSTBUFFER,NULL);
568 }
569
570 ALOGD_IF(isDebug(),"%s: old_mode: %d new_mode: %d", __FUNCTION__,
571 cur_mode, new_mode);
572
573 if((new_mode != cur_mode) && (new_mode >= 0)) {
574 if(fbDev->perform(fbDev,EVENT_SET_VAR_PIPE_MODE,(void*)&new_mode) < 0) {
575 ALOGE("%s: Setting var pipe mode failed", __FUNCTION__);
576 }
577 }
578
579 return 0;
580}
581#endif
582
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700583bool MDPComp::setup(hwc_context_t* ctx, hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700584 int nPipeIndex, vsync_wait, isFG;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700585 int numHwLayers = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700586
587 frame_info &current_frame = sCurrentFrame;
588 current_frame.count = 0;
589
Naseer Ahmed52ca6d22012-10-08 14:03:01 -0400590 if(current_frame.pipe_layer) {
591 free(current_frame.pipe_layer);
592 current_frame.pipe_layer = NULL;
593 }
594
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700595 if(!ctx) {
596 ALOGE("%s: invalid context", __FUNCTION__);
597 return -1;
598 }
599
600 framebuffer_device_t *fbDev = ctx->mFbDev;
601 if (!fbDev) {
602 ALOGE("%s: fbDev is NULL", __FUNCTION__);
603 return -1;
604 }
605
606 if(!parse_and_allocate(ctx, list, current_frame)) {
607#if SUPPORT_4LAYER
608 int mode = VAR_PIPE_FB_ATTACH;
609 if(fbDev->perform(fbDev,EVENT_SET_VAR_PIPE_MODE,(void*)&mode) < 0 ) {
610 ALOGE("%s: setting var pipe mode failed", __FUNCTION__);
611 }
612#endif
613 ALOGD_IF(isDebug(), "%s: Falling back to FB", __FUNCTION__);
614 return false;
615 }
616#if SUPPORT_4LAYER
617 configure_var_pipe(ctx);
618#endif
619
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700620 overlay::Overlay& ov = *(ctx->mOverlay[HWC_DISPLAY_PRIMARY]);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700621 ovutils::eOverlayState state = ov.getState();
622
623 if (current_frame.count == 1) {
624 state = ovutils::OV_BYPASS_1_LAYER;
625 } else if (current_frame.count == 2) {
626 state = ovutils::OV_BYPASS_2_LAYER;
627 } else if (current_frame.count == 3) {
628 state = ovutils::OV_BYPASS_3_LAYER;
629 }
630
631 ov.setState(state);
632
633
634 for (int index = 0 ; index < current_frame.count; index++) {
635 int layer_index = current_frame.pipe_layer[index].layer_index;
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700636 hwc_layer_1_t* layer = &list->hwLayers[layer_index];
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700637 mdp_pipe_info& cur_pipe = current_frame.pipe_layer[index].pipe_index;
638
639 if( prepare(ctx, layer, cur_pipe) != 0 ) {
640 ALOGD_IF(isDebug(), "%s: MDPComp failed to configure overlay for \
641 layer %d with pipe index:%d",__FUNCTION__,
642 index, cur_pipe.index);
643 return false;
644 } else {
645 setLayerIndex(layer, index);
646 }
647 }
648 return true;
649}
650
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700651void MDPComp::unsetMDPCompLayerFlags(hwc_context_t* ctx, hwc_display_contents_1_t* list)
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700652{
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700653 for (int index = 0 ; index < sCurrentFrame.count; index++) {
654 int l_index = sCurrentFrame.pipe_layer[index].layer_index;
655 if(list->hwLayers[l_index].flags & HWC_MDPCOMP) {
656 list->hwLayers[l_index].flags &= ~HWC_MDPCOMP;
657 }
Naseer Ahmedfb4cbdd2012-08-16 15:54:53 -0700658
659 if(list->hwLayers[l_index].compositionType == HWC_OVERLAY) {
660 list->hwLayers[l_index].compositionType = HWC_FRAMEBUFFER;
661 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700662 }
663}
664
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700665int MDPComp::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700666
667 if(!isEnabled()) {
668 ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled",__FUNCTION__);
669 return 0;
670 }
671
672 if(!ctx || !list) {
673 ALOGE("%s: invalid contxt or list",__FUNCTION__);
674 return -1;
675 }
676
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700677 overlay::Overlay& ov = *(ctx->mOverlay[HWC_DISPLAY_PRIMARY]);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700678
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700679 int numHwLayers = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
680 for(int i = 0; i < numHwLayers; i++ )
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700681 {
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700682 hwc_layer_1_t *layer = &list->hwLayers[i];
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700683
684 if(!(layer->flags & HWC_MDPCOMP)) {
685 ALOGD_IF(isDebug(), "%s: Layer Not flagged for MDP comp",
686 __FUNCTION__);
687 continue;
688 }
689
690 int data_index = getLayerIndex(layer);
691 mdp_pipe_info& pipe_info =
692 sCurrentFrame.pipe_layer[data_index].pipe_index;
693 int index = pipe_info.index;
694
695 if(index < 0) {
696 ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, index);
697 return -1;
698 }
699
700 /* reset Invalidator */
701 if(idleInvalidator)
702 idleInvalidator->markForSleep();
703
704 ovutils::eDest dest;
705
706 if (index == 0) {
707 dest = ovutils::OV_PIPE0;
708 } else if (index == 1) {
709 dest = ovutils::OV_PIPE1;
710 } else if (index == 2) {
711 dest = ovutils::OV_PIPE2;
712 }
713
714 if (ctx ) {
715 private_handle_t *hnd = (private_handle_t *)layer->handle;
716 if(!hnd) {
717 ALOGE("%s handle null", __FUNCTION__);
718 return -1;
719 }
720
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700721 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
722 using pipe: %d", __FUNCTION__, layer,
723 hnd, index );
724
725 if (!ov.queueBuffer(hnd->fd, hnd->offset, dest)) {
726 ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
727 return -1;
728 }
729 }
730 layer->flags &= ~HWC_MDPCOMP;
731 layer->flags |= HWC_MDPCOMP_INDEX_MASK;
732 }
733 return 0;
734}
735
736bool MDPComp::init(hwc_context_t *dev) {
737
738 if(!dev) {
739 ALOGE("%s: Invalid hwc context!!",__FUNCTION__);
740 return false;
741 }
742
743#if SUPPORT_4LAYER
744 if(MAX_MDPCOMP_LAYERS > MAX_STATIC_PIPES) {
745 framebuffer_device_t *fbDev = dev->fbDevice;
746 if(fbDev == NULL) {
747 ALOGE("%s: FATAL: framebuffer device is NULL", __FUNCTION__);
748 return false;
749 }
750
751 //Receive VAR pipe object from framebuffer
752 if(fbDev->perform(fbDev,EVENT_GET_VAR_PIPE,(void*)&ov) < 0) {
753 ALOGE("%s: FATAL: getVariablePipe failed!!", __FUNCTION__);
754 return false;
755 }
756
757 sPipeMgr.setStatus(VAR_INDEX, PIPE_IN_FB_MODE);
758 }
759#endif
760 char property[PROPERTY_VALUE_MAX];
761
762 sMaxLayers = 0;
763 if(property_get("debug.mdpcomp.maxlayer", property, NULL) > 0) {
764 if(atoi(property) != 0)
765 sMaxLayers = atoi(property);
766 }
767
768 sDebugLogs = false;
769 if(property_get("debug.mdpcomp.logs", property, NULL) > 0) {
770 if(atoi(property) != 0)
771 sDebugLogs = true;
772 }
773
774 unsigned long idle_timeout = DEFAULT_IDLE_TIME;
775 if(property_get("debug.mdpcomp.idletime", property, NULL) > 0) {
776 if(atoi(property) != 0)
777 idle_timeout = atoi(property);
778 }
779
780 //create Idle Invalidator
781 idleInvalidator = IdleInvalidator::getInstance();
782
783 if(idleInvalidator == NULL) {
784 ALOGE("%s: failed to instantiate idleInvalidator object", __FUNCTION__);
785 } else {
786 idleInvalidator->init(timeout_handler, dev, idle_timeout);
787 }
788 return true;
789}
790
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700791bool MDPComp::configure(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700792
793 if(!isEnabled()) {
794 ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
795 return false;
796 }
797
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700798 bool isMDPCompUsed = true;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700799 bool doable = is_doable(ctx, list);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700800
801 if(doable) {
802 if(setup(ctx, list)) {
803 setMDPCompLayerFlags(list);
804 sMDPCompState = MDPCOMP_ON;
805 } else {
806 ALOGD_IF(isDebug(),"%s: MDP Comp Failed",__FUNCTION__);
807 isMDPCompUsed = false;
808 }
809 } else {
810 ALOGD_IF( isDebug(),"%s: MDP Comp not possible[%d]",__FUNCTION__,
811 doable);
812 isMDPCompUsed = false;
813 }
814
815 //Reset states
816 if(!isMDPCompUsed) {
817 //Reset current frame
818 reset(ctx, list);
819 }
820
821 sIdleFallBack = false;
822
823 return isMDPCompUsed;
824}
825}; //namespace
826