• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012-2013, The Linux Foundation. All rights reserved.
3  * Not a Contribution, Apache license notifications and license are retained
4  * for attribution purposes only.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #include <math.h>
20 #include "hwc_mdpcomp.h"
21 #include <sys/ioctl.h>
22 #include "external.h"
23 #include "qdMetaData.h"
24 #include "mdp_version.h"
25 #include <overlayRotator.h>
26 
27 using overlay::Rotator;
28 using namespace overlay::utils;
29 namespace ovutils = overlay::utils;
30 
31 namespace qhwc {
32 
33 //==============MDPComp========================================================
34 
35 IdleInvalidator *MDPComp::idleInvalidator = NULL;
36 bool MDPComp::sIdleFallBack = false;
37 bool MDPComp::sDebugLogs = false;
38 bool MDPComp::sEnabled = false;
39 int MDPComp::sMaxPipesPerMixer = MAX_PIPES_PER_MIXER;
40 
getObject(const int & width,int dpy)41 MDPComp* MDPComp::getObject(const int& width, int dpy) {
42     if(width <= MAX_DISPLAY_DIM) {
43         return new MDPCompLowRes(dpy);
44     } else {
45         return new MDPCompHighRes(dpy);
46     }
47 }
48 
MDPComp(int dpy)49 MDPComp::MDPComp(int dpy):mDpy(dpy){};
50 
dump(android::String8 & buf)51 void MDPComp::dump(android::String8& buf)
52 {
53     dumpsys_log(buf,"HWC Map for Dpy: %s \n",
54                 mDpy ? "\"EXTERNAL\"" : "\"PRIMARY\"");
55     dumpsys_log(buf,"PREV_FRAME: layerCount:%2d    mdpCount:%2d \
56                 cacheCount:%2d \n", mCachedFrame.layerCount,
57                 mCachedFrame.mdpCount, mCachedFrame.cacheCount);
58     dumpsys_log(buf,"CURR_FRAME: layerCount:%2d    mdpCount:%2d \
59                 fbCount:%2d \n", mCurrentFrame.layerCount,
60                 mCurrentFrame.mdpCount, mCurrentFrame.fbCount);
61     dumpsys_log(buf,"needsFBRedraw:%3s  pipesUsed:%2d  MaxPipesPerMixer: %d \n",
62                 (mCurrentFrame.needsRedraw? "YES" : "NO"),
63                 mCurrentFrame.mdpCount, sMaxPipesPerMixer);
64     dumpsys_log(buf," ---------------------------------------------  \n");
65     dumpsys_log(buf," listIdx | cached? | mdpIndex | comptype  |  Z  \n");
66     dumpsys_log(buf," ---------------------------------------------  \n");
67     for(int index = 0; index < mCurrentFrame.layerCount; index++ )
68         dumpsys_log(buf," %7d | %7s | %8d | %9s | %2d \n",
69                     index,
70                     (mCurrentFrame.isFBComposed[index] ? "YES" : "NO"),
71                     mCurrentFrame.layerToMDP[index],
72                     (mCurrentFrame.isFBComposed[index] ?
73                      (mCurrentFrame.needsRedraw ? "GLES" : "CACHE") : "MDP"),
74                     (mCurrentFrame.isFBComposed[index] ? mCurrentFrame.fbZ :
75     mCurrentFrame.mdpToLayer[mCurrentFrame.layerToMDP[index]].pipeInfo->zOrder));
76     dumpsys_log(buf,"\n");
77 }
78 
init(hwc_context_t * ctx)79 bool MDPComp::init(hwc_context_t *ctx) {
80 
81     if(!ctx) {
82         ALOGE("%s: Invalid hwc context!!",__FUNCTION__);
83         return false;
84     }
85 
86     char property[PROPERTY_VALUE_MAX];
87 
88     sEnabled = false;
89     if((property_get("persist.hwc.mdpcomp.enable", property, NULL) > 0) &&
90        (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
91         (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
92         sEnabled = true;
93     }
94 
95     sDebugLogs = false;
96     if(property_get("debug.mdpcomp.logs", property, NULL) > 0) {
97         if(atoi(property) != 0)
98             sDebugLogs = true;
99     }
100 
101     sMaxPipesPerMixer = MAX_PIPES_PER_MIXER;
102     if(property_get("debug.mdpcomp.maxpermixer", property, NULL) > 0) {
103         if(atoi(property) != 0)
104             sMaxPipesPerMixer = true;
105     }
106 
107     if(ctx->mMDP.panel != MIPI_CMD_PANEL) {
108         // Idle invalidation is not necessary on command mode panels
109         long idle_timeout = DEFAULT_IDLE_TIME;
110         if(property_get("debug.mdpcomp.idletime", property, NULL) > 0) {
111             if(atoi(property) != 0)
112                 idle_timeout = atoi(property);
113         }
114 
115         //create Idle Invalidator only when not disabled through property
116         if(idle_timeout != -1)
117             idleInvalidator = IdleInvalidator::getInstance();
118 
119         if(idleInvalidator == NULL) {
120             ALOGE("%s: failed to instantiate idleInvalidator object",
121                   __FUNCTION__);
122         } else {
123             idleInvalidator->init(timeout_handler, ctx, idle_timeout);
124         }
125     }
126     return true;
127 }
128 
timeout_handler(void * udata)129 void MDPComp::timeout_handler(void *udata) {
130     struct hwc_context_t* ctx = (struct hwc_context_t*)(udata);
131 
132     if(!ctx) {
133         ALOGE("%s: received empty data in timer callback", __FUNCTION__);
134         return;
135     }
136 
137     if(!ctx->proc) {
138         ALOGE("%s: HWC proc not registered", __FUNCTION__);
139         return;
140     }
141     sIdleFallBack = true;
142     /* Trigger SF to redraw the current frame */
143     ctx->proc->invalidate(ctx->proc);
144 }
145 
setMDPCompLayerFlags(hwc_context_t * ctx,hwc_display_contents_1_t * list)146 void MDPComp::setMDPCompLayerFlags(hwc_context_t *ctx,
147                                    hwc_display_contents_1_t* list) {
148     LayerProp *layerProp = ctx->layerProp[mDpy];
149 
150     for(int index = 0; index < ctx->listStats[mDpy].numAppLayers; index++) {
151         hwc_layer_1_t* layer = &(list->hwLayers[index]);
152         if(!mCurrentFrame.isFBComposed[index]) {
153             layerProp[index].mFlags |= HWC_MDPCOMP;
154             layer->compositionType = HWC_OVERLAY;
155             layer->hints |= HWC_HINT_CLEAR_FB;
156             mCachedFrame.hnd[index] = NULL;
157         } else {
158             if(!mCurrentFrame.needsRedraw)
159                 layer->compositionType = HWC_OVERLAY;
160         }
161     }
162 }
163 
164 /*
165  * Sets up BORDERFILL as default base pipe and detaches RGB0.
166  * Framebuffer is always updated using PLAY ioctl.
167  */
setupBasePipe(hwc_context_t * ctx)168 bool MDPComp::setupBasePipe(hwc_context_t *ctx) {
169     const int dpy = HWC_DISPLAY_PRIMARY;
170     int fb_stride = ctx->dpyAttr[dpy].stride;
171     int fb_width = ctx->dpyAttr[dpy].xres;
172     int fb_height = ctx->dpyAttr[dpy].yres;
173     int fb_fd = ctx->dpyAttr[dpy].fd;
174 
175     mdp_overlay ovInfo;
176     msmfb_overlay_data ovData;
177     memset(&ovInfo, 0, sizeof(mdp_overlay));
178     memset(&ovData, 0, sizeof(msmfb_overlay_data));
179 
180     ovInfo.src.format = MDP_RGB_BORDERFILL;
181     ovInfo.src.width  = fb_width;
182     ovInfo.src.height = fb_height;
183     ovInfo.src_rect.w = fb_width;
184     ovInfo.src_rect.h = fb_height;
185     ovInfo.dst_rect.w = fb_width;
186     ovInfo.dst_rect.h = fb_height;
187     ovInfo.id = MSMFB_NEW_REQUEST;
188 
189     if (ioctl(fb_fd, MSMFB_OVERLAY_SET, &ovInfo) < 0) {
190         ALOGE("Failed to call ioctl MSMFB_OVERLAY_SET err=%s",
191               strerror(errno));
192         return false;
193     }
194 
195     ovData.id = ovInfo.id;
196     if (ioctl(fb_fd, MSMFB_OVERLAY_PLAY, &ovData) < 0) {
197         ALOGE("Failed to call ioctl MSMFB_OVERLAY_PLAY err=%s",
198               strerror(errno));
199         return false;
200     }
201     return true;
202 }
203 
FrameInfo()204 MDPComp::FrameInfo::FrameInfo() {
205     memset(&mdpToLayer, 0, sizeof(mdpToLayer));
206     reset(0);
207 }
208 
reset(const int & numLayers)209 void MDPComp::FrameInfo::reset(const int& numLayers) {
210     for(int i = 0 ; i < MAX_PIPES_PER_MIXER; i++ ) {
211         if(mdpToLayer[i].pipeInfo) {
212             delete mdpToLayer[i].pipeInfo;
213             mdpToLayer[i].pipeInfo = NULL;
214             //We dont own the rotator
215             mdpToLayer[i].rot = NULL;
216         }
217     }
218 
219     memset(&mdpToLayer, 0, sizeof(mdpToLayer));
220     memset(&layerToMDP, -1, sizeof(layerToMDP));
221     memset(&isFBComposed, 1, sizeof(isFBComposed));
222 
223     layerCount = numLayers;
224     fbCount = numLayers;
225     mdpCount = 0;
226     needsRedraw = true;
227     fbZ = 0;
228 }
229 
map()230 void MDPComp::FrameInfo::map() {
231     // populate layer and MDP maps
232     int mdpIdx = 0;
233     for(int idx = 0; idx < layerCount; idx++) {
234         if(!isFBComposed[idx]) {
235             mdpToLayer[mdpIdx].listIndex = idx;
236             layerToMDP[idx] = mdpIdx++;
237         }
238     }
239 }
240 
LayerCache()241 MDPComp::LayerCache::LayerCache() {
242     reset();
243 }
244 
reset()245 void MDPComp::LayerCache::reset() {
246     memset(&hnd, 0, sizeof(hnd));
247     mdpCount = 0;
248     cacheCount = 0;
249     layerCount = 0;
250     fbZ = -1;
251 }
252 
cacheAll(hwc_display_contents_1_t * list)253 void MDPComp::LayerCache::cacheAll(hwc_display_contents_1_t* list) {
254     const int numAppLayers = list->numHwLayers - 1;
255     for(int i = 0; i < numAppLayers; i++) {
256         hnd[i] = list->hwLayers[i].handle;
257     }
258 }
259 
updateCounts(const FrameInfo & curFrame)260 void MDPComp::LayerCache::updateCounts(const FrameInfo& curFrame) {
261     mdpCount = curFrame.mdpCount;
262     cacheCount = curFrame.fbCount;
263     layerCount = curFrame.layerCount;
264     fbZ = curFrame.fbZ;
265 }
266 
isValidDimension(hwc_context_t * ctx,hwc_layer_1_t * layer)267 bool MDPComp::isValidDimension(hwc_context_t *ctx, hwc_layer_1_t *layer) {
268     const int dpy = HWC_DISPLAY_PRIMARY;
269     private_handle_t *hnd = (private_handle_t *)layer->handle;
270 
271     if(!hnd) {
272         ALOGE("%s: layer handle is NULL", __FUNCTION__);
273         return false;
274     }
275 
276     int hw_w = ctx->dpyAttr[mDpy].xres;
277     int hw_h = ctx->dpyAttr[mDpy].yres;
278 
279     hwc_rect_t crop = layer->sourceCrop;
280     hwc_rect_t dst = layer->displayFrame;
281 
282     if(dst.left < 0 || dst.top < 0 || dst.right > hw_w || dst.bottom > hw_h) {
283        hwc_rect_t scissor = {0, 0, hw_w, hw_h };
284        qhwc::calculate_crop_rects(crop, dst, scissor, layer->transform);
285     }
286 
287     int crop_w = crop.right - crop.left;
288     int crop_h = crop.bottom - crop.top;
289     int dst_w = dst.right - dst.left;
290     int dst_h = dst.bottom - dst.top;
291     float w_dscale = ceilf((float)crop_w / (float)dst_w);
292     float h_dscale = ceilf((float)crop_h / (float)dst_h);
293 
294     //Workaround for MDP HW limitation in DSI command mode panels where
295     //FPS will not go beyond 30 if buffers on RGB pipes are of width < 5
296 
297     if((crop_w < 5)||(crop_h < 5))
298         return false;
299 
300     if(ctx->mMDP.version >= qdutils::MDSS_V5) {
301         /* Workaround for downscales larger than 4x.
302          * Will be removed once decimator block is enabled for MDSS
303          */
304         if(w_dscale > 4.0f || h_dscale > 4.0f)
305             return false;
306     } else {
307         if(w_dscale > 8.0f || h_dscale > 8.0f)
308             // MDP 4 supports 1/8 downscale
309             return false;
310     }
311 
312     return true;
313 }
314 
getMdpPipe(hwc_context_t * ctx,ePipeType type)315 ovutils::eDest MDPComp::getMdpPipe(hwc_context_t *ctx, ePipeType type) {
316     overlay::Overlay& ov = *ctx->mOverlay;
317     ovutils::eDest mdp_pipe = ovutils::OV_INVALID;
318 
319     switch(type) {
320     case MDPCOMP_OV_DMA:
321         mdp_pipe = ov.nextPipe(ovutils::OV_MDP_PIPE_DMA, mDpy);
322         if(mdp_pipe != ovutils::OV_INVALID) {
323             ctx->mDMAInUse = true;
324             return mdp_pipe;
325         }
326     case MDPCOMP_OV_ANY:
327     case MDPCOMP_OV_RGB:
328         mdp_pipe = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, mDpy);
329         if(mdp_pipe != ovutils::OV_INVALID) {
330             return mdp_pipe;
331         }
332 
333         if(type == MDPCOMP_OV_RGB) {
334             //Requested only for RGB pipe
335             break;
336         }
337     case  MDPCOMP_OV_VG:
338         return ov.nextPipe(ovutils::OV_MDP_PIPE_VG, mDpy);
339     default:
340         ALOGE("%s: Invalid pipe type",__FUNCTION__);
341         return ovutils::OV_INVALID;
342     };
343     return ovutils::OV_INVALID;
344 }
345 
isFrameDoable(hwc_context_t * ctx)346 bool MDPComp::isFrameDoable(hwc_context_t *ctx) {
347     const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
348     bool ret = true;
349 
350     if(!isEnabled()) {
351         ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
352         ret = false;
353     } else if(ctx->mExtDispConfiguring) {
354         ALOGD_IF( isDebug(),"%s: External Display connection is pending",
355                   __FUNCTION__);
356         ret = false;
357     } else if(ctx->mVideoTransFlag) {
358         ALOGD_IF(isDebug(), "%s: MDP Comp. video transition padding round",
359                 __FUNCTION__);
360     }
361     return ret;
362 }
363 
364 /* Checks for conditions where all the layers marked for MDP comp cannot be
365  * bypassed. On such conditions we try to bypass atleast YUV layers */
isFullFrameDoable(hwc_context_t * ctx,hwc_display_contents_1_t * list)366 bool MDPComp::isFullFrameDoable(hwc_context_t *ctx,
367                                 hwc_display_contents_1_t* list){
368 
369     const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
370 
371     if(sIdleFallBack) {
372         ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
373         return false;
374     }
375 
376     if(mDpy > HWC_DISPLAY_PRIMARY){
377         ALOGD_IF(isDebug(), "%s: Cannot support External display(s)",
378                  __FUNCTION__);
379         return false;
380     }
381 
382     if(isSkipPresent(ctx, mDpy)) {
383         ALOGD_IF(isDebug(),"%s: SKIP present: %d",
384                 __FUNCTION__,
385                 isSkipPresent(ctx, mDpy));
386         return false;
387     }
388 
389     if(ctx->listStats[mDpy].planeAlpha
390                      && ctx->mMDP.version >= qdutils::MDSS_V5) {
391         ALOGD_IF(isDebug(), "%s: plane alpha not implemented on MDSS",
392                  __FUNCTION__);
393         return false;
394     }
395 
396     if(ctx->listStats[mDpy].needsAlphaScale
397        && ctx->mMDP.version < qdutils::MDSS_V5) {
398         ALOGD_IF(isDebug(), "%s: frame needs alpha downscaling",__FUNCTION__);
399         return false;
400     }
401 
402     //MDP composition is not efficient if layer needs rotator.
403     for(int i = 0; i < numAppLayers; ++i) {
404         // As MDP h/w supports flip operation, use MDP comp only for
405         // 180 transforms. Fail for any transform involving 90 (90, 270).
406         hwc_layer_1_t* layer = &list->hwLayers[i];
407         private_handle_t *hnd = (private_handle_t *)layer->handle;
408         if(isYuvBuffer(hnd) ) {
409             if(isSecuring(ctx, layer)) {
410                 ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
411                 return false;
412             }
413         } else if(layer->transform & HWC_TRANSFORM_ROT_90) {
414             ALOGD_IF(isDebug(), "%s: orientation involved",__FUNCTION__);
415             return false;
416         }
417 
418         if(!isValidDimension(ctx,layer)) {
419             ALOGD_IF(isDebug(), "%s: Buffer is of invalid width",
420                 __FUNCTION__);
421             return false;
422         }
423     }
424 
425     //If all above hard conditions are met we can do full or partial MDP comp.
426     bool ret = false;
427     if(fullMDPComp(ctx, list)) {
428         ret = true;
429     } else if (partialMDPComp(ctx, list)) {
430         ret = true;
431     }
432     return ret;
433 }
434 
fullMDPComp(hwc_context_t * ctx,hwc_display_contents_1_t * list)435 bool MDPComp::fullMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
436     //Setup mCurrentFrame
437     mCurrentFrame.mdpCount = mCurrentFrame.layerCount;
438     mCurrentFrame.fbCount = 0;
439     mCurrentFrame.fbZ = -1;
440     memset(&mCurrentFrame.isFBComposed, 0, sizeof(mCurrentFrame.isFBComposed));
441 
442     int mdpCount = mCurrentFrame.mdpCount;
443     if(mdpCount > sMaxPipesPerMixer) {
444         ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
445         return false;
446     }
447 
448     int numPipesNeeded = pipesNeeded(ctx, list);
449     int availPipes = getAvailablePipes(ctx);
450 
451     if(numPipesNeeded > availPipes) {
452         ALOGD_IF(isDebug(), "%s: Insufficient MDP pipes, needed %d, avail %d",
453                 __FUNCTION__, numPipesNeeded, availPipes);
454         return false;
455     }
456 
457     return true;
458 }
459 
partialMDPComp(hwc_context_t * ctx,hwc_display_contents_1_t * list)460 bool MDPComp::partialMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list)
461 {
462     int numAppLayers = ctx->listStats[mDpy].numAppLayers;
463     //Setup mCurrentFrame
464     mCurrentFrame.reset(numAppLayers);
465     updateLayerCache(ctx, list);
466     updateYUV(ctx, list);
467     batchLayers(); //sets up fbZ also
468 
469     int mdpCount = mCurrentFrame.mdpCount;
470     if(mdpCount > (sMaxPipesPerMixer - 1)) { // -1 since FB is used
471         ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
472         return false;
473     }
474 
475     int numPipesNeeded = pipesNeeded(ctx, list);
476     int availPipes = getAvailablePipes(ctx);
477 
478     if(numPipesNeeded > availPipes) {
479         ALOGD_IF(isDebug(), "%s: Insufficient MDP pipes, needed %d, avail %d",
480                 __FUNCTION__, numPipesNeeded, availPipes);
481         return false;
482     }
483 
484     return true;
485 }
486 
isOnlyVideoDoable(hwc_context_t * ctx,hwc_display_contents_1_t * list)487 bool MDPComp::isOnlyVideoDoable(hwc_context_t *ctx,
488         hwc_display_contents_1_t* list){
489     int numAppLayers = ctx->listStats[mDpy].numAppLayers;
490     mCurrentFrame.reset(numAppLayers);
491     updateYUV(ctx, list);
492     int mdpCount = mCurrentFrame.mdpCount;
493     int fbNeeded = int(mCurrentFrame.fbCount != 0);
494 
495     if(!isYuvPresent(ctx, mDpy)) {
496         return false;
497     }
498 
499     if(!mdpCount)
500         return false;
501 
502     if(mdpCount > (sMaxPipesPerMixer - fbNeeded)) {
503         ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
504         return false;
505     }
506 
507     int numPipesNeeded = pipesNeeded(ctx, list);
508     int availPipes = getAvailablePipes(ctx);
509     if(numPipesNeeded > availPipes) {
510         ALOGD_IF(isDebug(), "%s: Insufficient MDP pipes, needed %d, avail %d",
511                 __FUNCTION__, numPipesNeeded, availPipes);
512         return false;
513     }
514 
515     int nYuvCount = ctx->listStats[mDpy].yuvCount;
516     for(int index = 0; index < nYuvCount ; index ++) {
517         int nYuvIndex = ctx->listStats[mDpy].yuvIndices[index];
518         hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
519         if(layer->planeAlpha < 0xFF) {
520             ALOGD_IF(isDebug(), "%s: Cannot handle YUV layer with plane alpha\
521                     when sandwiched",
522                     __FUNCTION__);
523             return false;
524         }
525     }
526 
527     return true;
528 }
529 
530 /* Checks for conditions where YUV layers cannot be bypassed */
isYUVDoable(hwc_context_t * ctx,hwc_layer_1_t * layer)531 bool MDPComp::isYUVDoable(hwc_context_t* ctx, hwc_layer_1_t* layer) {
532 
533     if(isSkipLayer(layer)) {
534         ALOGE("%s: Unable to bypass skipped YUV", __FUNCTION__);
535         return false;
536     }
537 
538     if(ctx->mNeedsRotator && ctx->mDMAInUse) {
539         ALOGE("%s: No DMA for Rotator",__FUNCTION__);
540         return false;
541     }
542 
543     if(isSecuring(ctx, layer)) {
544         ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
545         return false;
546     }
547 
548     if(!isValidDimension(ctx, layer)) {
549         ALOGD_IF(isDebug(), "%s: Buffer is of invalid width",
550             __FUNCTION__);
551         return false;
552     }
553 
554     return true;
555 }
556 
batchLayers()557 void  MDPComp::batchLayers() {
558     /* Idea is to keep as many contiguous non-updating(cached) layers in FB and
559      * send rest of them through MDP. NEVER mark an updating layer for caching.
560      * But cached ones can be marked for MDP*/
561 
562     int maxBatchStart = -1;
563     int maxBatchCount = 0;
564 
565     /* All or Nothing is cached. No batching needed */
566     if(!mCurrentFrame.fbCount) {
567         mCurrentFrame.fbZ = -1;
568         return;
569     }
570     if(!mCurrentFrame.mdpCount) {
571         mCurrentFrame.fbZ = 0;
572         return;
573     }
574 
575     /* Search for max number of contiguous (cached) layers */
576     int i = 0;
577     while (i < mCurrentFrame.layerCount) {
578         int count = 0;
579         while(mCurrentFrame.isFBComposed[i] && i < mCurrentFrame.layerCount) {
580             count++; i++;
581         }
582         if(count > maxBatchCount) {
583             maxBatchCount = count;
584             maxBatchStart = i - count;
585             mCurrentFrame.fbZ = maxBatchStart;
586         }
587         if(i < mCurrentFrame.layerCount) i++;
588     }
589 
590     /* reset rest of the layers for MDP comp */
591     for(int i = 0; i < mCurrentFrame.layerCount; i++) {
592         if(i != maxBatchStart){
593             mCurrentFrame.isFBComposed[i] = false;
594         } else {
595             i += maxBatchCount;
596         }
597     }
598 
599     mCurrentFrame.fbCount = maxBatchCount;
600     mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
601             mCurrentFrame.fbCount;
602 
603     ALOGD_IF(isDebug(),"%s: cached count: %d",__FUNCTION__,
604              mCurrentFrame.fbCount);
605 }
606 
updateLayerCache(hwc_context_t * ctx,hwc_display_contents_1_t * list)607 void MDPComp::updateLayerCache(hwc_context_t* ctx,
608                                hwc_display_contents_1_t* list) {
609 
610     int numAppLayers = ctx->listStats[mDpy].numAppLayers;
611     int numCacheableLayers = 0;
612 
613     for(int i = 0; i < numAppLayers; i++) {
614         if (mCachedFrame.hnd[i] == list->hwLayers[i].handle) {
615             numCacheableLayers++;
616             mCurrentFrame.isFBComposed[i] = true;
617         } else {
618             mCurrentFrame.isFBComposed[i] = false;
619             mCachedFrame.hnd[i] = list->hwLayers[i].handle;
620         }
621     }
622 
623     mCurrentFrame.fbCount = numCacheableLayers;
624     mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
625             mCurrentFrame.fbCount;
626     ALOGD_IF(isDebug(),"%s: cached count: %d",__FUNCTION__, numCacheableLayers);
627 }
628 
getAvailablePipes(hwc_context_t * ctx)629 int MDPComp::getAvailablePipes(hwc_context_t* ctx) {
630     int numDMAPipes = qdutils::MDPVersion::getInstance().getDMAPipes();
631     overlay::Overlay& ov = *ctx->mOverlay;
632 
633     int numAvailable = ov.availablePipes(mDpy);
634 
635     //Reserve DMA for rotator
636     if(ctx->mNeedsRotator)
637         numAvailable -= numDMAPipes;
638 
639     //Reserve pipe(s)for FB
640     if(mCurrentFrame.fbCount)
641         numAvailable -= pipesForFB();
642 
643     return numAvailable;
644 }
645 
updateYUV(hwc_context_t * ctx,hwc_display_contents_1_t * list)646 void MDPComp::updateYUV(hwc_context_t* ctx, hwc_display_contents_1_t* list) {
647 
648     int nYuvCount = ctx->listStats[mDpy].yuvCount;
649     for(int index = 0;index < nYuvCount; index++){
650         int nYuvIndex = ctx->listStats[mDpy].yuvIndices[index];
651         hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
652 
653         if(!isYUVDoable(ctx, layer)) {
654             if(!mCurrentFrame.isFBComposed[nYuvIndex]) {
655                 mCurrentFrame.isFBComposed[nYuvIndex] = true;
656                 mCurrentFrame.fbCount++;
657             }
658         } else {
659             if(mCurrentFrame.isFBComposed[nYuvIndex]) {
660                 mCurrentFrame.isFBComposed[nYuvIndex] = false;
661                 mCurrentFrame.fbCount--;
662             }
663         }
664     }
665 
666     mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
667             mCurrentFrame.fbCount;
668     ALOGD_IF(isDebug(),"%s: cached count: %d",__FUNCTION__,
669              mCurrentFrame.fbCount);
670 }
671 
programMDP(hwc_context_t * ctx,hwc_display_contents_1_t * list)672 bool MDPComp::programMDP(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
673     ctx->mDMAInUse = false;
674     if(!allocLayerPipes(ctx, list)) {
675         ALOGD_IF(isDebug(), "%s: Unable to allocate MDP pipes", __FUNCTION__);
676         return false;
677     }
678 
679     bool fbBatch = false;
680     for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
681             index++) {
682         if(!mCurrentFrame.isFBComposed[index]) {
683             int mdpIndex = mCurrentFrame.layerToMDP[index];
684             hwc_layer_1_t* layer = &list->hwLayers[index];
685 
686             MdpPipeInfo* cur_pipe = mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
687             cur_pipe->zOrder = mdpNextZOrder++;
688 
689             if(configure(ctx, layer, mCurrentFrame.mdpToLayer[mdpIndex]) != 0 ){
690                 ALOGD_IF(isDebug(), "%s: Failed to configure overlay for \
691                          layer %d",__FUNCTION__, index);
692                 return false;
693             }
694         } else if(fbBatch == false) {
695                 mdpNextZOrder++;
696                 fbBatch = true;
697         }
698     }
699 
700     return true;
701 }
702 
programYUV(hwc_context_t * ctx,hwc_display_contents_1_t * list)703 bool MDPComp::programYUV(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
704     if(!allocLayerPipes(ctx, list)) {
705         ALOGD_IF(isDebug(), "%s: Unable to allocate MDP pipes", __FUNCTION__);
706         return false;
707     }
708     //If we are in this block, it means we have yuv + rgb layers both
709     int mdpIdx = 0;
710     for (int index = 0; index < mCurrentFrame.layerCount; index++) {
711         if(!mCurrentFrame.isFBComposed[index]) {
712             hwc_layer_1_t* layer = &list->hwLayers[index];
713             int mdpIndex = mCurrentFrame.layerToMDP[index];
714             MdpPipeInfo* cur_pipe =
715                     mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
716             cur_pipe->zOrder = mdpIdx++;
717 
718             if(configure(ctx, layer,
719                         mCurrentFrame.mdpToLayer[mdpIndex]) != 0 ){
720                 ALOGD_IF(isDebug(), "%s: Failed to configure overlay for \
721                         layer %d",__FUNCTION__, index);
722                 return false;
723             }
724         }
725     }
726     return true;
727 }
728 
prepare(hwc_context_t * ctx,hwc_display_contents_1_t * list)729 int MDPComp::prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
730 
731     const int numLayers = ctx->listStats[mDpy].numAppLayers;
732 
733     //reset old data
734     mCurrentFrame.reset(numLayers);
735 
736     //number of app layers exceeds MAX_NUM_APP_LAYERS fall back to GPU
737     //do not cache the information for next draw cycle.
738     if(numLayers > MAX_NUM_APP_LAYERS) {
739         ALOGD_IF(isDebug(), "%s: Number of App layers exceeded the limit ",
740                  __FUNCTION__);
741         return 0;
742     }
743 
744     //Hard conditions, if not met, cannot do MDP comp
745     if(!isFrameDoable(ctx)) {
746         ALOGD_IF( isDebug(),"%s: MDP Comp not possible for this frame",
747                   __FUNCTION__);
748         mCurrentFrame.reset(numLayers);
749         mCachedFrame.cacheAll(list);
750         mCachedFrame.updateCounts(mCurrentFrame);
751         return 0;
752     }
753 
754     //Check whether layers marked for MDP Composition is actually doable.
755     if(isFullFrameDoable(ctx, list)){
756         mCurrentFrame.map();
757         //Acquire and Program MDP pipes
758         if(!programMDP(ctx, list)) {
759             mCurrentFrame.reset(numLayers);
760             mCachedFrame.cacheAll(list);
761         } else { //Success
762             //Any change in composition types needs an FB refresh
763             mCurrentFrame.needsRedraw = false;
764             if(mCurrentFrame.fbCount &&
765                     ((mCurrentFrame.mdpCount != mCachedFrame.mdpCount) ||
766                      (mCurrentFrame.fbCount != mCachedFrame.cacheCount) ||
767                      (mCurrentFrame.fbZ != mCachedFrame.fbZ) ||
768                      (!mCurrentFrame.mdpCount) ||
769                      (list->flags & HWC_GEOMETRY_CHANGED) ||
770                      isSkipPresent(ctx, mDpy) ||
771                      (mDpy > HWC_DISPLAY_PRIMARY))) {
772                 mCurrentFrame.needsRedraw = true;
773             }
774         }
775     } else if(isOnlyVideoDoable(ctx, list)) {
776         //All layers marked for MDP comp cannot be bypassed.
777         //Try to compose atleast YUV layers through MDP comp and let
778         //all the RGB layers compose in FB
779         //Destination over
780         mCurrentFrame.fbZ = -1;
781         if(mCurrentFrame.fbCount)
782             mCurrentFrame.fbZ = ctx->listStats[mDpy].yuvCount;
783 
784         mCurrentFrame.map();
785         if(!programYUV(ctx, list)) {
786             mCurrentFrame.reset(numLayers);
787             mCachedFrame.cacheAll(list);
788         }
789     } else {
790         mCurrentFrame.reset(numLayers);
791         mCachedFrame.cacheAll(list);
792     }
793 
794     //UpdateLayerFlags
795     setMDPCompLayerFlags(ctx, list);
796     mCachedFrame.updateCounts(mCurrentFrame);
797 
798     if(isDebug()) {
799         ALOGD("GEOMETRY change: %d", (list->flags & HWC_GEOMETRY_CHANGED));
800         android::String8 sDump("");
801         dump(sDump);
802         ALOGE("%s",sDump.string());
803     }
804 
805     return mCurrentFrame.fbZ;
806 }
807 
808 //=============MDPCompLowRes===================================================
809 
810 /*
811  * Configures pipe(s) for MDP composition
812  */
configure(hwc_context_t * ctx,hwc_layer_1_t * layer,PipeLayerPair & PipeLayerPair)813 int MDPCompLowRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
814                              PipeLayerPair& PipeLayerPair) {
815     MdpPipeInfoLowRes& mdp_info =
816         *(static_cast<MdpPipeInfoLowRes*>(PipeLayerPair.pipeInfo));
817     eMdpFlags mdpFlags = OV_MDP_BACKEND_COMPOSITION;
818     eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
819     eIsFg isFg = IS_FG_OFF;
820     eDest dest = mdp_info.index;
821 
822     ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipe: %d",
823              __FUNCTION__, layer, zOrder, dest);
824 
825     return configureLowRes(ctx, layer, mDpy, mdpFlags, zOrder, isFg, dest,
826                            &PipeLayerPair.rot);
827 }
828 
pipesNeeded(hwc_context_t * ctx,hwc_display_contents_1_t * list)829 int MDPCompLowRes::pipesNeeded(hwc_context_t *ctx,
830                                hwc_display_contents_1_t* list) {
831     return mCurrentFrame.mdpCount;
832 }
833 
allocLayerPipes(hwc_context_t * ctx,hwc_display_contents_1_t * list)834 bool MDPCompLowRes::allocLayerPipes(hwc_context_t *ctx,
835                                     hwc_display_contents_1_t* list) {
836     if(isYuvPresent(ctx, mDpy)) {
837         int nYuvCount = ctx->listStats[mDpy].yuvCount;
838 
839         for(int index = 0; index < nYuvCount ; index ++) {
840             int nYuvIndex = ctx->listStats[mDpy].yuvIndices[index];
841 
842             if(mCurrentFrame.isFBComposed[nYuvIndex])
843                 continue;
844 
845             hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
846 
847             int mdpIndex = mCurrentFrame.layerToMDP[nYuvIndex];
848 
849             PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
850             info.pipeInfo = new MdpPipeInfoLowRes;
851             info.rot = NULL;
852             MdpPipeInfoLowRes& pipe_info = *(MdpPipeInfoLowRes*)info.pipeInfo;
853 
854             pipe_info.index = getMdpPipe(ctx, MDPCOMP_OV_VG);
855             if(pipe_info.index == ovutils::OV_INVALID) {
856                 ALOGD_IF(isDebug(), "%s: Unable to get pipe for Videos",
857                          __FUNCTION__);
858                 return false;
859             }
860         }
861     }
862 
863     for(int index = 0 ; index < mCurrentFrame.layerCount; index++ ) {
864         if(mCurrentFrame.isFBComposed[index]) continue;
865         hwc_layer_1_t* layer = &list->hwLayers[index];
866         private_handle_t *hnd = (private_handle_t *)layer->handle;
867 
868         if(isYuvBuffer(hnd))
869             continue;
870 
871         int mdpIndex = mCurrentFrame.layerToMDP[index];
872 
873         PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
874         info.pipeInfo = new MdpPipeInfoLowRes;
875         info.rot = NULL;
876         MdpPipeInfoLowRes& pipe_info = *(MdpPipeInfoLowRes*)info.pipeInfo;
877 
878         ePipeType type = MDPCOMP_OV_ANY;
879 
880         if(!qhwc::needsScaling(layer) && !ctx->mNeedsRotator
881            && ctx->mMDP.version >= qdutils::MDSS_V5) {
882             type = MDPCOMP_OV_DMA;
883         }
884 
885         pipe_info.index = getMdpPipe(ctx, type);
886         if(pipe_info.index == ovutils::OV_INVALID) {
887             ALOGD_IF(isDebug(), "%s: Unable to get pipe for UI", __FUNCTION__);
888             return false;
889         }
890     }
891     return true;
892 }
893 
draw(hwc_context_t * ctx,hwc_display_contents_1_t * list)894 bool MDPCompLowRes::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
895 
896     if(!isEnabled()) {
897         ALOGD_IF(isDebug(),"%s: MDP Comp not configured", __FUNCTION__);
898         return true;
899     }
900 
901     if(!ctx || !list) {
902         ALOGE("%s: invalid contxt or list",__FUNCTION__);
903         return false;
904     }
905 
906     /* reset Invalidator */
907     if(idleInvalidator && !sIdleFallBack && mCurrentFrame.mdpCount)
908         idleInvalidator->markForSleep();
909 
910     overlay::Overlay& ov = *ctx->mOverlay;
911     LayerProp *layerProp = ctx->layerProp[mDpy];
912 
913     int numHwLayers = ctx->listStats[mDpy].numAppLayers;
914     for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ )
915     {
916         if(mCurrentFrame.isFBComposed[i]) continue;
917 
918         hwc_layer_1_t *layer = &list->hwLayers[i];
919         private_handle_t *hnd = (private_handle_t *)layer->handle;
920         if(!hnd) {
921             ALOGE("%s handle null", __FUNCTION__);
922             return false;
923         }
924 
925         int mdpIndex = mCurrentFrame.layerToMDP[i];
926 
927         MdpPipeInfoLowRes& pipe_info =
928             *(MdpPipeInfoLowRes*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
929         ovutils::eDest dest = pipe_info.index;
930         if(dest == ovutils::OV_INVALID) {
931             ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, dest);
932             return false;
933         }
934 
935         if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
936             continue;
937         }
938 
939         ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
940                  using  pipe: %d", __FUNCTION__, layer,
941                  hnd, dest );
942 
943         int fd = hnd->fd;
944         uint32_t offset = hnd->offset;
945         Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
946         if(rot) {
947             if(!rot->queueBuffer(fd, offset))
948                 return false;
949             fd = rot->getDstMemId();
950             offset = rot->getDstOffset();
951         }
952 
953         if (!ov.queueBuffer(fd, offset, dest)) {
954             ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
955             return false;
956         }
957 
958         layerProp[i].mFlags &= ~HWC_MDPCOMP;
959     }
960     return true;
961 }
962 
963 //=============MDPCompHighRes===================================================
964 
pipesNeeded(hwc_context_t * ctx,hwc_display_contents_1_t * list)965 int MDPCompHighRes::pipesNeeded(hwc_context_t *ctx,
966                                 hwc_display_contents_1_t* list) {
967     int pipesNeeded = 0;
968     int hw_w = ctx->dpyAttr[mDpy].xres;
969 
970     for(int i = 0; i < mCurrentFrame.layerCount; ++i) {
971         if(!mCurrentFrame.isFBComposed[i]) {
972             hwc_layer_1_t* layer = &list->hwLayers[i];
973             hwc_rect_t dst = layer->displayFrame;
974             if(dst.left > hw_w/2) {
975                 pipesNeeded++;
976             } else if(dst.right <= hw_w/2) {
977                 pipesNeeded++;
978             } else {
979                 pipesNeeded += 2;
980             }
981         }
982     }
983     return pipesNeeded;
984 }
985 
acquireMDPPipes(hwc_context_t * ctx,hwc_layer_1_t * layer,MdpPipeInfoHighRes & pipe_info,ePipeType type)986 bool MDPCompHighRes::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
987                                      MdpPipeInfoHighRes& pipe_info,
988                                      ePipeType type) {
989     int hw_w = ctx->dpyAttr[mDpy].xres;
990 
991     hwc_rect_t dst = layer->displayFrame;
992     if(dst.left > hw_w/2) {
993         pipe_info.lIndex = ovutils::OV_INVALID;
994         pipe_info.rIndex = getMdpPipe(ctx, type);
995         if(pipe_info.rIndex == ovutils::OV_INVALID)
996             return false;
997     } else if (dst.right <= hw_w/2) {
998         pipe_info.rIndex = ovutils::OV_INVALID;
999         pipe_info.lIndex = getMdpPipe(ctx, type);
1000         if(pipe_info.lIndex == ovutils::OV_INVALID)
1001             return false;
1002     } else {
1003         pipe_info.rIndex = getMdpPipe(ctx, type);
1004         pipe_info.lIndex = getMdpPipe(ctx, type);
1005         if(pipe_info.rIndex == ovutils::OV_INVALID ||
1006            pipe_info.lIndex == ovutils::OV_INVALID)
1007             return false;
1008     }
1009     return true;
1010 }
1011 
allocLayerPipes(hwc_context_t * ctx,hwc_display_contents_1_t * list)1012 bool MDPCompHighRes::allocLayerPipes(hwc_context_t *ctx,
1013                                      hwc_display_contents_1_t* list) {
1014     overlay::Overlay& ov = *ctx->mOverlay;
1015     int layer_count = ctx->listStats[mDpy].numAppLayers;
1016 
1017     if(isYuvPresent(ctx, mDpy)) {
1018         int nYuvCount = ctx->listStats[mDpy].yuvCount;
1019 
1020         for(int index = 0; index < nYuvCount; index ++) {
1021             int nYuvIndex = ctx->listStats[mDpy].yuvIndices[index];
1022             hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
1023             PipeLayerPair& info = mCurrentFrame.mdpToLayer[nYuvIndex];
1024             info.pipeInfo = new MdpPipeInfoHighRes;
1025             info.rot = NULL;
1026             MdpPipeInfoHighRes& pipe_info = *(MdpPipeInfoHighRes*)info.pipeInfo;
1027             if(!acquireMDPPipes(ctx, layer, pipe_info,MDPCOMP_OV_VG)) {
1028                 ALOGD_IF(isDebug(),"%s: Unable to get pipe for videos",
1029                          __FUNCTION__);
1030                 //TODO: windback pipebook data on fail
1031                 return false;
1032             }
1033             pipe_info.zOrder = nYuvIndex;
1034         }
1035     }
1036 
1037     for(int index = 0 ; index < layer_count ; index++ ) {
1038         hwc_layer_1_t* layer = &list->hwLayers[index];
1039         private_handle_t *hnd = (private_handle_t *)layer->handle;
1040 
1041         if(isYuvBuffer(hnd))
1042             continue;
1043 
1044         int mdpIndex = mCurrentFrame.layerToMDP[index];
1045         PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
1046         info.pipeInfo = new MdpPipeInfoHighRes;
1047         info.rot = NULL;
1048         MdpPipeInfoHighRes& pipe_info = *(MdpPipeInfoHighRes*)info.pipeInfo;
1049 
1050         ePipeType type = MDPCOMP_OV_ANY;
1051 
1052         if(!qhwc::needsScaling(layer) && !ctx->mNeedsRotator
1053            && ctx->mMDP.version >= qdutils::MDSS_V5)
1054             type = MDPCOMP_OV_DMA;
1055 
1056         if(!acquireMDPPipes(ctx, layer, pipe_info, type)) {
1057             ALOGD_IF(isDebug(), "%s: Unable to get pipe for UI", __FUNCTION__);
1058             //TODO: windback pipebook data on fail
1059             return false;
1060         }
1061         pipe_info.zOrder = index;
1062     }
1063     return true;
1064 }
1065 /*
1066  * Configures pipe(s) for MDP composition
1067  */
configure(hwc_context_t * ctx,hwc_layer_1_t * layer,PipeLayerPair & PipeLayerPair)1068 int MDPCompHighRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
1069                               PipeLayerPair& PipeLayerPair) {
1070     MdpPipeInfoHighRes& mdp_info =
1071         *(static_cast<MdpPipeInfoHighRes*>(PipeLayerPair.pipeInfo));
1072     eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
1073     eIsFg isFg = IS_FG_OFF;
1074     eMdpFlags mdpFlagsL = OV_MDP_BACKEND_COMPOSITION;
1075     eDest lDest = mdp_info.lIndex;
1076     eDest rDest = mdp_info.rIndex;
1077 
1078     ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
1079              "dest_pipeR: %d",__FUNCTION__, layer, zOrder, lDest, rDest);
1080 
1081     return configureHighRes(ctx, layer, mDpy, mdpFlagsL, zOrder, isFg, lDest,
1082                             rDest, &PipeLayerPair.rot);
1083 }
1084 
draw(hwc_context_t * ctx,hwc_display_contents_1_t * list)1085 bool MDPCompHighRes::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
1086 
1087     if(!isEnabled()) {
1088         ALOGD_IF(isDebug(),"%s: MDP Comp not configured", __FUNCTION__);
1089         return true;
1090     }
1091 
1092     if(!ctx || !list) {
1093         ALOGE("%s: invalid contxt or list",__FUNCTION__);
1094         return false;
1095     }
1096 
1097     /* reset Invalidator */
1098     if(idleInvalidator && !sIdleFallBack && mCurrentFrame.mdpCount)
1099         idleInvalidator->markForSleep();
1100 
1101     overlay::Overlay& ov = *ctx->mOverlay;
1102     LayerProp *layerProp = ctx->layerProp[mDpy];
1103 
1104     int numHwLayers = ctx->listStats[mDpy].numAppLayers;
1105     for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ )
1106     {
1107         if(mCurrentFrame.isFBComposed[i]) continue;
1108 
1109         hwc_layer_1_t *layer = &list->hwLayers[i];
1110         private_handle_t *hnd = (private_handle_t *)layer->handle;
1111         if(!hnd) {
1112             ALOGE("%s handle null", __FUNCTION__);
1113             return false;
1114         }
1115 
1116         if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
1117             continue;
1118         }
1119 
1120         int mdpIndex = mCurrentFrame.layerToMDP[i];
1121 
1122         MdpPipeInfoHighRes& pipe_info =
1123             *(MdpPipeInfoHighRes*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
1124         Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
1125 
1126         ovutils::eDest indexL = pipe_info.lIndex;
1127         ovutils::eDest indexR = pipe_info.rIndex;
1128 
1129         int fd = hnd->fd;
1130         int offset = hnd->offset;
1131 
1132         if(rot) {
1133             rot->queueBuffer(fd, offset);
1134             fd = rot->getDstMemId();
1135             offset = rot->getDstOffset();
1136         }
1137 
1138         //************* play left mixer **********
1139         if(indexL != ovutils::OV_INVALID) {
1140             ovutils::eDest destL = (ovutils::eDest)indexL;
1141             ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
1142                      using  pipe: %d", __FUNCTION__, layer, hnd, indexL );
1143             if (!ov.queueBuffer(fd, offset, destL)) {
1144                 ALOGE("%s: queueBuffer failed for left mixer", __FUNCTION__);
1145                 return false;
1146             }
1147         }
1148 
1149         //************* play right mixer **********
1150         if(indexR != ovutils::OV_INVALID) {
1151             ovutils::eDest destR = (ovutils::eDest)indexR;
1152             ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
1153                      using  pipe: %d", __FUNCTION__, layer, hnd, indexR );
1154             if (!ov.queueBuffer(fd, offset, destR)) {
1155                 ALOGE("%s: queueBuffer failed for right mixer", __FUNCTION__);
1156                 return false;
1157             }
1158         }
1159 
1160         layerProp[i].mFlags &= ~HWC_MDPCOMP;
1161     }
1162 
1163     return true;
1164 }
1165 }; //namespace
1166 
1167