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