• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  * Copyright (C) 2012-2013, The Linux Foundation All rights reserved.
4  *
5  * Not a Contribution, Apache license notifications and license are retained
6  * for attribution purposes only.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 #define HWC_UTILS_DEBUG 0
21 #include <sys/ioctl.h>
22 #include <binder/IServiceManager.h>
23 #include <EGL/egl.h>
24 #include <cutils/properties.h>
25 #include <gralloc_priv.h>
26 #include <overlay.h>
27 #include <overlayRotator.h>
28 #include "hwc_utils.h"
29 #include "hwc_mdpcomp.h"
30 #include "hwc_fbupdate.h"
31 #include "mdp_version.h"
32 #include "hwc_copybit.h"
33 #include "external.h"
34 #include "hwc_qclient.h"
35 #include "QService.h"
36 #include "comptype.h"
37 
38 using namespace qClient;
39 using namespace qService;
40 using namespace android;
41 using namespace overlay;
42 using namespace overlay::utils;
43 namespace ovutils = overlay::utils;
44 
45 namespace qhwc {
46 
openFramebufferDevice(hwc_context_t * ctx)47 static int openFramebufferDevice(hwc_context_t *ctx)
48 {
49     struct fb_fix_screeninfo finfo;
50     struct fb_var_screeninfo info;
51 
52     int fb_fd = openFb(HWC_DISPLAY_PRIMARY);
53 
54     if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &info) == -1)
55         return -errno;
56 
57     if (int(info.width) <= 0 || int(info.height) <= 0) {
58         // the driver doesn't return that information
59         // default to 160 dpi
60         info.width  = ((info.xres * 25.4f)/160.0f + 0.5f);
61         info.height = ((info.yres * 25.4f)/160.0f + 0.5f);
62     }
63 
64     float xdpi = (info.xres * 25.4f) / info.width;
65     float ydpi = (info.yres * 25.4f) / info.height;
66 
67 #ifdef MSMFB_METADATA_GET
68     struct msmfb_metadata metadata;
69     memset(&metadata, 0 , sizeof(metadata));
70     metadata.op = metadata_op_frame_rate;
71 
72     if (ioctl(fb_fd, MSMFB_METADATA_GET, &metadata) == -1) {
73         ALOGE("Error retrieving panel frame rate");
74         return -errno;
75     }
76 
77     float fps  = metadata.data.panel_frame_rate;
78 #else
79     //XXX: Remove reserved field usage on all baselines
80     //The reserved[3] field is used to store FPS by the driver.
81     float fps  = info.reserved[3] & 0xFF;
82 #endif
83 
84     if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &finfo) == -1)
85         return -errno;
86 
87     if (finfo.smem_len <= 0)
88         return -errno;
89 
90     ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd = fb_fd;
91     //xres, yres may not be 32 aligned
92     ctx->dpyAttr[HWC_DISPLAY_PRIMARY].stride = finfo.line_length /(info.xres/8);
93     ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres = info.xres;
94     ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres = info.yres;
95     ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xdpi = xdpi;
96     ctx->dpyAttr[HWC_DISPLAY_PRIMARY].ydpi = ydpi;
97     ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period = 1000000000l / fps;
98 
99     //Unblank primary on first boot
100     if(ioctl(fb_fd, FBIOBLANK,FB_BLANK_UNBLANK) < 0) {
101         ALOGE("%s: Failed to unblank display", __FUNCTION__);
102         return -errno;
103     }
104     ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isActive = true;
105 
106     return 0;
107 }
108 
initContext(hwc_context_t * ctx)109 void initContext(hwc_context_t *ctx)
110 {
111     if(openFramebufferDevice(ctx) < 0) {
112         ALOGE("%s: failed to open framebuffer!!", __FUNCTION__);
113     }
114 
115     overlay::Overlay::initOverlay();
116     ctx->mOverlay = overlay::Overlay::getInstance();
117     ctx->mRotMgr = new RotMgr();
118     ctx->mMDP.version = qdutils::MDPVersion::getInstance().getMDPVersion();
119     ctx->mMDP.hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay();
120     ctx->mMDP.panel = qdutils::MDPVersion::getInstance().getPanelType();
121     overlay::Overlay::initOverlay();
122     ctx->mOverlay = overlay::Overlay::getInstance();
123     ctx->mRotMgr = new RotMgr();
124 
125     //Is created and destroyed only once for primary
126     //For external it could get created and destroyed multiple times depending
127     //on what external we connect to.
128     ctx->mFBUpdate[HWC_DISPLAY_PRIMARY] =
129         IFBUpdate::getObject(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres,
130         HWC_DISPLAY_PRIMARY);
131 
132     // Check if the target supports copybit compostion (dyn/mdp/c2d) to
133     // decide if we need to open the copybit module.
134     int compositionType =
135         qdutils::QCCompositionType::getInstance().getCompositionType();
136 
137     if (compositionType & (qdutils::COMPOSITION_TYPE_DYN |
138                            qdutils::COMPOSITION_TYPE_MDP |
139                            qdutils::COMPOSITION_TYPE_C2D)) {
140             ctx->mCopyBit[HWC_DISPLAY_PRIMARY] = new CopyBit();
141     }
142 
143     ctx->mExtDisplay = new ExternalDisplay(ctx);
144 
145     for (uint32_t i = 0; i < MAX_DISPLAYS; i++) {
146         ctx->mLayerRotMap[i] = new LayerRotMap();
147     }
148 
149     ctx->mMDPComp[HWC_DISPLAY_PRIMARY] =
150          MDPComp::getObject(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres,
151          HWC_DISPLAY_PRIMARY);
152 
153     MDPComp::init(ctx);
154 
155     ctx->vstate.enable = false;
156     ctx->vstate.fakevsync = false;
157     ctx->mExtDispConfiguring = false;
158     ctx->mBasePipeSetup = false;
159 
160     //Right now hwc starts the service but anybody could do it, or it could be
161     //independent process as well.
162     QService::init();
163     sp<IQClient> client = new QClient(ctx);
164     interface_cast<IQService>(
165             defaultServiceManager()->getService(
166             String16("display.qservice")))->connect(client);
167 
168     ALOGI("Initializing Qualcomm Hardware Composer");
169     ALOGI("MDP version: %d", ctx->mMDP.version);
170 }
171 
closeContext(hwc_context_t * ctx)172 void closeContext(hwc_context_t *ctx)
173 {
174     if(ctx->mOverlay) {
175         delete ctx->mOverlay;
176         ctx->mOverlay = NULL;
177     }
178 
179     if(ctx->mRotMgr) {
180         delete ctx->mRotMgr;
181         ctx->mRotMgr = NULL;
182     }
183 
184     for(int i = 0; i < MAX_DISPLAYS; i++) {
185         if(ctx->mCopyBit[i]) {
186             delete ctx->mCopyBit[i];
187             ctx->mCopyBit[i] = NULL;
188         }
189     }
190 
191     if(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd) {
192         close(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd);
193         ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd = -1;
194     }
195 
196     if(ctx->mExtDisplay) {
197         delete ctx->mExtDisplay;
198         ctx->mExtDisplay = NULL;
199     }
200 
201     for(int i = 0; i < MAX_DISPLAYS; i++) {
202         if(ctx->mFBUpdate[i]) {
203             delete ctx->mFBUpdate[i];
204             ctx->mFBUpdate[i] = NULL;
205         }
206         if(ctx->mMDPComp[i]) {
207             delete ctx->mMDPComp[i];
208             ctx->mMDPComp[i] = NULL;
209         }
210         if(ctx->mLayerRotMap[i]) {
211             delete ctx->mLayerRotMap[i];
212             ctx->mLayerRotMap[i] = NULL;
213         }
214     }
215 }
216 
217 
dumpsys_log(android::String8 & buf,const char * fmt,...)218 void dumpsys_log(android::String8& buf, const char* fmt, ...)
219 {
220     va_list varargs;
221     va_start(varargs, fmt);
222     buf.appendFormatV(fmt, varargs);
223     va_end(varargs);
224 }
225 
226 /* Calculates the destination position based on the action safe rectangle */
getActionSafePosition(hwc_context_t * ctx,int dpy,uint32_t & x,uint32_t & y,uint32_t & w,uint32_t & h)227 void getActionSafePosition(hwc_context_t *ctx, int dpy, uint32_t& x,
228                            uint32_t& y, uint32_t& w, uint32_t& h) {
229 
230     // if external supports underscan, do nothing
231     // it will be taken care in the driver
232     if(ctx->mExtDisplay->isCEUnderscanSupported())
233         return;
234 
235     float wRatio = 1.0;
236     float hRatio = 1.0;
237     float xRatio = 1.0;
238     float yRatio = 1.0;
239 
240     float fbWidth = ctx->dpyAttr[dpy].xres;
241     float fbHeight = ctx->dpyAttr[dpy].yres;
242 
243     float asX = 0;
244     float asY = 0;
245     float asW = fbWidth;
246     float asH= fbHeight;
247     char value[PROPERTY_VALUE_MAX];
248 
249     // Apply action safe parameters
250     property_get("hw.actionsafe.width", value, "0");
251     int asWidthRatio = atoi(value);
252     property_get("hw.actionsafe.height", value, "0");
253     int asHeightRatio = atoi(value);
254     // based on the action safe ratio, get the Action safe rectangle
255     asW = fbWidth * (1.0f -  asWidthRatio / 100.0f);
256     asH = fbHeight * (1.0f -  asHeightRatio / 100.0f);
257     asX = (fbWidth - asW) / 2;
258     asY = (fbHeight - asH) / 2;
259 
260     // calculate the position ratio
261     xRatio = (float)x/fbWidth;
262     yRatio = (float)y/fbHeight;
263     wRatio = (float)w/fbWidth;
264     hRatio = (float)h/fbHeight;
265 
266     //Calculate the position...
267     x = (xRatio * asW) + asX;
268     y = (yRatio * asH) + asY;
269     w = (wRatio * asW);
270     h = (hRatio * asH);
271 
272     return;
273 }
274 
needsScaling(hwc_layer_1_t const * layer)275 bool needsScaling(hwc_layer_1_t const* layer) {
276     int dst_w, dst_h, src_w, src_h;
277 
278     hwc_rect_t displayFrame  = layer->displayFrame;
279     hwc_rect_t sourceCrop = layer->sourceCrop;
280 
281     dst_w = displayFrame.right - displayFrame.left;
282     dst_h = displayFrame.bottom - displayFrame.top;
283 
284     src_w = sourceCrop.right - sourceCrop.left;
285     src_h = sourceCrop.bottom - sourceCrop.top;
286 
287     if(((src_w != dst_w) || (src_h != dst_h)))
288         return true;
289 
290     return false;
291 }
292 
isAlphaScaled(hwc_layer_1_t const * layer)293 bool isAlphaScaled(hwc_layer_1_t const* layer) {
294     if(needsScaling(layer) && isAlphaPresent(layer)) {
295         return true;
296     }
297     return false;
298 }
299 
isAlphaPresent(hwc_layer_1_t const * layer)300 bool isAlphaPresent(hwc_layer_1_t const* layer) {
301     private_handle_t *hnd = (private_handle_t *)layer->handle;
302     if(hnd) {
303         int format = hnd->format;
304         switch(format) {
305         case HAL_PIXEL_FORMAT_RGBA_8888:
306         case HAL_PIXEL_FORMAT_BGRA_8888:
307             // In any more formats with Alpha go here..
308             return true;
309         default : return false;
310         }
311     }
312     return false;
313 }
314 
315 // Let CABL know we have a YUV layer
setYUVProp(int yuvCount)316 static void setYUVProp(int yuvCount) {
317     static char property[PROPERTY_VALUE_MAX];
318     if(yuvCount > 0) {
319         if (property_get("hw.cabl.yuv", property, NULL) > 0) {
320             if (atoi(property) != 1) {
321                 property_set("hw.cabl.yuv", "1");
322             }
323         }
324     } else {
325         if (property_get("hw.cabl.yuv", property, NULL) > 0) {
326             if (atoi(property) != 0) {
327                 property_set("hw.cabl.yuv", "0");
328             }
329         }
330     }
331 }
332 
setListStats(hwc_context_t * ctx,const hwc_display_contents_1_t * list,int dpy)333 void setListStats(hwc_context_t *ctx,
334         const hwc_display_contents_1_t *list, int dpy) {
335 
336     ctx->listStats[dpy].numAppLayers = list->numHwLayers - 1;
337     ctx->listStats[dpy].fbLayerIndex = list->numHwLayers - 1;
338     ctx->listStats[dpy].skipCount = 0;
339     ctx->listStats[dpy].needsAlphaScale = false;
340     ctx->listStats[dpy].preMultipliedAlpha = false;
341     ctx->listStats[dpy].planeAlpha = false;
342     ctx->listStats[dpy].yuvCount = 0;
343 
344     for (size_t i = 0; i < list->numHwLayers; i++) {
345         hwc_layer_1_t const* layer = &list->hwLayers[i];
346         private_handle_t *hnd = (private_handle_t *)layer->handle;
347 
348         //reset stored yuv index
349         ctx->listStats[dpy].yuvIndices[i] = -1;
350 
351         if(list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
352             continue;
353         //We disregard FB being skip for now! so the else if
354         } else if (isSkipLayer(&list->hwLayers[i])) {
355             ctx->listStats[dpy].skipCount++;
356         } else if (UNLIKELY(isYuvBuffer(hnd))) {
357             int& yuvCount = ctx->listStats[dpy].yuvCount;
358             ctx->listStats[dpy].yuvIndices[yuvCount] = i;
359             yuvCount++;
360 
361             if(layer->transform & HWC_TRANSFORM_ROT_90)
362                 ctx->mNeedsRotator = true;
363         }
364         if(layer->blending == HWC_BLENDING_PREMULT)
365             ctx->listStats[dpy].preMultipliedAlpha = true;
366         if(layer->planeAlpha < 0xFF)
367             ctx->listStats[dpy].planeAlpha = true;
368         if(!ctx->listStats[dpy].needsAlphaScale)
369             ctx->listStats[dpy].needsAlphaScale = isAlphaScaled(layer);
370     }
371     setYUVProp(ctx->listStats[dpy].yuvCount);
372 }
373 
374 
calc_cut(float & leftCutRatio,float & topCutRatio,float & rightCutRatio,float & bottomCutRatio,int orient)375 static inline void calc_cut(float& leftCutRatio, float& topCutRatio,
376         float& rightCutRatio, float& bottomCutRatio, int orient) {
377     if(orient & HAL_TRANSFORM_FLIP_H) {
378         swap(leftCutRatio, rightCutRatio);
379     }
380     if(orient & HAL_TRANSFORM_FLIP_V) {
381         swap(topCutRatio, bottomCutRatio);
382     }
383     if(orient & HAL_TRANSFORM_ROT_90) {
384         //Anti clock swapping
385         float tmpCutRatio = leftCutRatio;
386         leftCutRatio = topCutRatio;
387         topCutRatio = rightCutRatio;
388         rightCutRatio = bottomCutRatio;
389         bottomCutRatio = tmpCutRatio;
390     }
391 }
392 
isSecuring(hwc_context_t * ctx,hwc_layer_1_t const * layer)393 bool isSecuring(hwc_context_t* ctx, hwc_layer_1_t const* layer) {
394     if((ctx->mMDP.version < qdutils::MDSS_V5) &&
395        (ctx->mMDP.version > qdutils::MDP_V3_0) &&
396         ctx->mSecuring) {
397         return true;
398     }
399     //  On A-Family, Secure policy is applied system wide and not on
400     //  buffers.
401     if (isSecureModePolicy(ctx->mMDP.version)) {
402         private_handle_t *hnd = (private_handle_t *)layer->handle;
403         if(ctx->mSecureMode) {
404             if (! isSecureBuffer(hnd)) {
405                 // This code path executes for the following usecase:
406                 // Some Apps in which first few seconds, framework
407                 // sends non-secure buffer and with out destroying
408                 // surfaces, switches to secure buffer thereby exposing
409                 // vulnerability on A-family devices. Catch this situation
410                 // and handle it gracefully by allowing it to be composed by
411                 // GPU.
412                 ALOGD_IF(HWC_UTILS_DEBUG, "%s: Handle non-secure video layer"
413                          "during secure playback gracefully", __FUNCTION__);
414                 return true;
415             }
416         } else {
417             if (isSecureBuffer(hnd)) {
418                 // This code path executes for the following usecase:
419                 // For some Apps, when User terminates playback, Framework
420                 // doesnt destroy video surface and video surface still
421                 // comes to Display HAL. This exposes vulnerability on
422                 // A-family. Catch this situation and handle it gracefully
423                 // by allowing it to be composed by GPU.
424                 ALOGD_IF(HWC_UTILS_DEBUG, "%s: Handle secure video layer"
425                          "during non-secure playback gracefully", __FUNCTION__);
426                 return true;
427             }
428         }
429     }
430     return false;
431 }
432 
isSecureModePolicy(int mdpVersion)433 bool isSecureModePolicy(int mdpVersion) {
434     if (mdpVersion < qdutils::MDSS_V5)
435         return true;
436     else
437         return false;
438 }
439 
getBlending(int blending)440 int getBlending(int blending) {
441     switch(blending) {
442     case HWC_BLENDING_NONE:
443         return overlay::utils::OVERLAY_BLENDING_OPAQUE;
444     case HWC_BLENDING_PREMULT:
445         return overlay::utils::OVERLAY_BLENDING_PREMULT;
446     case HWC_BLENDING_COVERAGE :
447     default:
448         return overlay::utils::OVERLAY_BLENDING_COVERAGE;
449     }
450 }
451 
452 //Crops source buffer against destination and FB boundaries
calculate_crop_rects(hwc_rect_t & crop,hwc_rect_t & dst,const hwc_rect_t & scissor,int orient)453 void calculate_crop_rects(hwc_rect_t& crop, hwc_rect_t& dst,
454                           const hwc_rect_t& scissor, int orient) {
455 
456     int& crop_l = crop.left;
457     int& crop_t = crop.top;
458     int& crop_r = crop.right;
459     int& crop_b = crop.bottom;
460     int crop_w = crop.right - crop.left;
461     int crop_h = crop.bottom - crop.top;
462 
463     int& dst_l = dst.left;
464     int& dst_t = dst.top;
465     int& dst_r = dst.right;
466     int& dst_b = dst.bottom;
467     int dst_w = abs(dst.right - dst.left);
468     int dst_h = abs(dst.bottom - dst.top);
469 
470     const int& sci_l = scissor.left;
471     const int& sci_t = scissor.top;
472     const int& sci_r = scissor.right;
473     const int& sci_b = scissor.bottom;
474     int sci_w = abs(sci_r - sci_l);
475     int sci_h = abs(sci_b - sci_t);
476 
477     float leftCutRatio = 0.0f, rightCutRatio = 0.0f, topCutRatio = 0.0f,
478             bottomCutRatio = 0.0f;
479 
480     if(dst_l < sci_l) {
481         leftCutRatio = (float)(sci_l - dst_l) / (float)dst_w;
482         dst_l = sci_l;
483     }
484 
485     if(dst_r > sci_r) {
486         rightCutRatio = (float)(dst_r - sci_r) / (float)dst_w;
487         dst_r = sci_r;
488     }
489 
490     if(dst_t < sci_t) {
491         topCutRatio = (float)(sci_t - dst_t) / (float)dst_h;
492         dst_t = sci_t;
493     }
494 
495     if(dst_b > sci_b) {
496         bottomCutRatio = (float)(dst_b - sci_b) / (float)dst_h;
497         dst_b = sci_b;
498     }
499 
500     calc_cut(leftCutRatio, topCutRatio, rightCutRatio, bottomCutRatio, orient);
501     crop_l += crop_w * leftCutRatio;
502     crop_t += crop_h * topCutRatio;
503     crop_r -= crop_w * rightCutRatio;
504     crop_b -= crop_h * bottomCutRatio;
505 }
506 
getNonWormholeRegion(hwc_display_contents_1_t * list,hwc_rect_t & nwr)507 void getNonWormholeRegion(hwc_display_contents_1_t* list,
508                               hwc_rect_t& nwr)
509 {
510     uint32_t last = list->numHwLayers - 1;
511     hwc_rect_t fbDisplayFrame = list->hwLayers[last].displayFrame;
512     //Initiliaze nwr to first frame
513     nwr.left =  list->hwLayers[0].displayFrame.left;
514     nwr.top =  list->hwLayers[0].displayFrame.top;
515     nwr.right =  list->hwLayers[0].displayFrame.right;
516     nwr.bottom =  list->hwLayers[0].displayFrame.bottom;
517 
518     for (uint32_t i = 1; i < last; i++) {
519         hwc_rect_t displayFrame = list->hwLayers[i].displayFrame;
520         nwr.left   = min(nwr.left, displayFrame.left);
521         nwr.top    = min(nwr.top, displayFrame.top);
522         nwr.right  = max(nwr.right, displayFrame.right);
523         nwr.bottom = max(nwr.bottom, displayFrame.bottom);
524     }
525 
526     //Intersect with the framebuffer
527     nwr.left   = max(nwr.left, fbDisplayFrame.left);
528     nwr.top    = max(nwr.top, fbDisplayFrame.top);
529     nwr.right  = min(nwr.right, fbDisplayFrame.right);
530     nwr.bottom = min(nwr.bottom, fbDisplayFrame.bottom);
531 
532 }
533 
isExternalActive(hwc_context_t * ctx)534 bool isExternalActive(hwc_context_t* ctx) {
535     return ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive;
536 }
537 
closeAcquireFds(hwc_display_contents_1_t * list)538 void closeAcquireFds(hwc_display_contents_1_t* list) {
539     if(LIKELY(list)) {
540         for(uint32_t i = 0; i < list->numHwLayers; i++) {
541             //Close the acquireFenceFds
542             //HWC_FRAMEBUFFER are -1 already by SF, rest we close.
543             if(list->hwLayers[i].acquireFenceFd >= 0) {
544                 close(list->hwLayers[i].acquireFenceFd);
545                 list->hwLayers[i].acquireFenceFd = -1;
546             }
547         }
548     }
549 }
550 
hwc_sync(hwc_context_t * ctx,hwc_display_contents_1_t * list,int dpy,int fd)551 int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy,
552         int fd) {
553     int ret = 0;
554 
555     int acquireFd[MAX_NUM_LAYERS];
556     int count = 0;
557     int releaseFd = -1;
558     int fbFd = -1;
559     int rotFd = -1;
560     bool swapzero = false;
561     int mdpVersion = qdutils::MDPVersion::getInstance().getMDPVersion();
562 
563     struct mdp_buf_sync data;
564     memset(&data, 0, sizeof(data));
565     //Until B-family supports sync for rotator
566     if(mdpVersion >= qdutils::MDSS_V5) {
567         data.flags = MDP_BUF_SYNC_FLAG_WAIT;
568     }
569     data.acq_fen_fd = acquireFd;
570     data.rel_fen_fd = &releaseFd;
571 
572     char property[PROPERTY_VALUE_MAX];
573     if(property_get("debug.egl.swapinterval", property, "1") > 0) {
574         if(atoi(property) == 0)
575             swapzero = true;
576     }
577 
578 #ifndef MDSS_TARGET
579     //Send acquireFenceFds to rotator
580     if(mdpVersion < qdutils::MDSS_V5) {
581         //A-family
582         int rotFd = ctx->mRotMgr->getRotDevFd();
583         struct msm_rotator_buf_sync rotData;
584 
585         for(uint32_t i = 0; i < ctx->mLayerRotMap[dpy]->getCount(); i++) {
586             memset(&rotData, 0, sizeof(rotData));
587             int& acquireFenceFd =
588                 ctx->mLayerRotMap[dpy]->getLayer(i)->acquireFenceFd;
589             rotData.acq_fen_fd = acquireFenceFd;
590             rotData.session_id = ctx->mLayerRotMap[dpy]->getRot(i)->getSessId();
591             ioctl(rotFd, MSM_ROTATOR_IOCTL_BUFFER_SYNC, &rotData);
592             close(acquireFenceFd);
593              //For MDP to wait on.
594             acquireFenceFd = dup(rotData.rel_fen_fd);
595             //A buffer is free to be used by producer as soon as its copied to
596             //rotator.
597             ctx->mLayerRotMap[dpy]->getLayer(i)->releaseFenceFd =
598                     rotData.rel_fen_fd;
599         }
600     } else {
601         //TODO B-family
602     }
603 
604 #endif
605     //Accumulate acquireFenceFds for MDP
606     for(uint32_t i = 0; i < list->numHwLayers; i++) {
607         if(list->hwLayers[i].compositionType == HWC_OVERLAY &&
608                         list->hwLayers[i].acquireFenceFd >= 0) {
609             if(UNLIKELY(swapzero))
610                 acquireFd[count++] = -1;
611             else
612                 acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
613         }
614         if(list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
615             if(UNLIKELY(swapzero))
616                 acquireFd[count++] = -1;
617             else if(fd >= 0) {
618                 //set the acquireFD from fd - which is coming from c2d
619                 acquireFd[count++] = fd;
620                 // Buffer sync IOCTL should be async when using c2d fence is
621                 // used
622                 data.flags &= ~MDP_BUF_SYNC_FLAG_WAIT;
623             } else if(list->hwLayers[i].acquireFenceFd >= 0)
624                 acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
625         }
626     }
627 
628     data.acq_fen_fd_cnt = count;
629     fbFd = ctx->dpyAttr[dpy].fd;
630 
631     //Waits for acquire fences, returns a release fence
632     if(LIKELY(!swapzero)) {
633         uint64_t start = systemTime();
634         ret = ioctl(fbFd, MSMFB_BUFFER_SYNC, &data);
635         ALOGD_IF(HWC_UTILS_DEBUG, "%s: time taken for MSMFB_BUFFER_SYNC IOCTL = %d",
636                             __FUNCTION__, (size_t) ns2ms(systemTime() - start));
637     }
638 
639     if(ret < 0) {
640         ALOGE("ioctl MSMFB_BUFFER_SYNC failed, err=%s",
641                 strerror(errno));
642     }
643 
644     for(uint32_t i = 0; i < list->numHwLayers; i++) {
645         if(list->hwLayers[i].compositionType == HWC_OVERLAY ||
646            list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
647             //Populate releaseFenceFds.
648             if(UNLIKELY(swapzero)) {
649                 list->hwLayers[i].releaseFenceFd = -1;
650             } else if(list->hwLayers[i].releaseFenceFd < 0) {
651                 //If rotator has not already populated this field.
652                 list->hwLayers[i].releaseFenceFd = dup(releaseFd);
653             }
654         }
655     }
656 
657     if(fd >= 0) {
658         close(fd);
659         fd = -1;
660     }
661 
662     if (ctx->mCopyBit[dpy])
663         ctx->mCopyBit[dpy]->setReleaseFd(releaseFd);
664 
665     //A-family
666     if(mdpVersion < qdutils::MDSS_V5) {
667         //Signals when MDP finishes reading rotator buffers.
668         ctx->mLayerRotMap[dpy]->setReleaseFd(releaseFd);
669     }
670 
671     if(UNLIKELY(swapzero)){
672         list->retireFenceFd = -1;
673         close(releaseFd);
674     } else {
675         list->retireFenceFd = releaseFd;
676     }
677 
678     return ret;
679 }
680 
trimLayer(hwc_context_t * ctx,const int & dpy,const int & transform,hwc_rect_t & crop,hwc_rect_t & dst)681 void trimLayer(hwc_context_t *ctx, const int& dpy, const int& transform,
682         hwc_rect_t& crop, hwc_rect_t& dst) {
683     int hw_w = ctx->dpyAttr[dpy].xres;
684     int hw_h = ctx->dpyAttr[dpy].yres;
685     if(dst.left < 0 || dst.top < 0 ||
686             dst.right > hw_w || dst.bottom > hw_h) {
687         hwc_rect_t scissor = {0, 0, hw_w, hw_h };
688         qhwc::calculate_crop_rects(crop, dst, scissor, transform);
689     }
690 }
691 
setMdpFlags(hwc_layer_1_t * layer,ovutils::eMdpFlags & mdpFlags,int rotDownscale)692 void setMdpFlags(hwc_layer_1_t *layer,
693         ovutils::eMdpFlags &mdpFlags,
694         int rotDownscale) {
695     private_handle_t *hnd = (private_handle_t *)layer->handle;
696     MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
697     const int& transform = layer->transform;
698 
699     if(layer->blending == HWC_BLENDING_PREMULT) {
700         ovutils::setMdpFlags(mdpFlags,
701                 ovutils::OV_MDP_BLEND_FG_PREMULT);
702     }
703 
704     if(isYuvBuffer(hnd)) {
705         if(isSecureBuffer(hnd)) {
706             ovutils::setMdpFlags(mdpFlags,
707                     ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
708         }
709         if(metadata && (metadata->operation & PP_PARAM_INTERLACED) &&
710                 metadata->interlaced) {
711             ovutils::setMdpFlags(mdpFlags,
712                     ovutils::OV_MDP_DEINTERLACE);
713         }
714         //Pre-rotation will be used using rotator.
715         if(transform & HWC_TRANSFORM_ROT_90) {
716             ovutils::setMdpFlags(mdpFlags,
717                     ovutils::OV_MDP_SOURCE_ROTATED_90);
718         }
719     }
720 
721     //No 90 component and no rot-downscale then flips done by MDP
722     //If we use rot then it might as well do flips
723     if(!(layer->transform & HWC_TRANSFORM_ROT_90) && !rotDownscale) {
724         if(layer->transform & HWC_TRANSFORM_FLIP_H) {
725             ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_FLIP_H);
726         }
727 
728         if(layer->transform & HWC_TRANSFORM_FLIP_V) {
729             ovutils::setMdpFlags(mdpFlags,  ovutils::OV_MDP_FLIP_V);
730         }
731     }
732 
733     if(metadata &&
734         ((metadata->operation & PP_PARAM_HSIC)
735         || (metadata->operation & PP_PARAM_IGC)
736         || (metadata->operation & PP_PARAM_SHARP2))) {
737         ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_PP_EN);
738     }
739 }
740 
configRotator(Rotator * rot,const Whf & whf,const eMdpFlags & mdpFlags,const eTransform & orient,const int & downscale)741 static inline int configRotator(Rotator *rot, const Whf& whf,
742         const eMdpFlags& mdpFlags, const eTransform& orient,
743         const int& downscale) {
744     rot->setSource(whf);
745     rot->setFlags(mdpFlags);
746     rot->setTransform(orient);
747     rot->setDownscale(downscale);
748     if(!rot->commit()) return -1;
749     return 0;
750 }
751 
752 /*
753  * Sets up BORDERFILL as default base pipe and detaches RGB0.
754  * Framebuffer is always updated using PLAY ioctl.
755  */
setupBasePipe(hwc_context_t * ctx)756 bool setupBasePipe(hwc_context_t *ctx) {
757     const int dpy = HWC_DISPLAY_PRIMARY;
758     int fb_stride = ctx->dpyAttr[dpy].stride;
759     int fb_width = ctx->dpyAttr[dpy].xres;
760     int fb_height = ctx->dpyAttr[dpy].yres;
761     int fb_fd = ctx->dpyAttr[dpy].fd;
762 
763     mdp_overlay ovInfo;
764     msmfb_overlay_data ovData;
765     memset(&ovInfo, 0, sizeof(mdp_overlay));
766     memset(&ovData, 0, sizeof(msmfb_overlay_data));
767 
768     ovInfo.src.format = MDP_RGB_BORDERFILL;
769     ovInfo.src.width  = fb_width;
770     ovInfo.src.height = fb_height;
771     ovInfo.src_rect.w = fb_width;
772     ovInfo.src_rect.h = fb_height;
773     ovInfo.dst_rect.w = fb_width;
774     ovInfo.dst_rect.h = fb_height;
775     ovInfo.id = MSMFB_NEW_REQUEST;
776 
777     if (ioctl(fb_fd, MSMFB_OVERLAY_SET, &ovInfo) < 0) {
778         ALOGE("Failed to call ioctl MSMFB_OVERLAY_SET err=%s",
779                 strerror(errno));
780         return false;
781     }
782 
783     ovData.id = ovInfo.id;
784     if (ioctl(fb_fd, MSMFB_OVERLAY_PLAY, &ovData) < 0) {
785         ALOGE("Failed to call ioctl MSMFB_OVERLAY_PLAY err=%s",
786                 strerror(errno));
787         return false;
788     }
789     ctx->mBasePipeSetup = true;
790     return true;
791 }
792 
793 
configMdp(Overlay * ov,const PipeArgs & parg,const eTransform & orient,const hwc_rect_t & crop,const hwc_rect_t & pos,const MetaData_t * metadata,const eDest & dest)794 static inline int configMdp(Overlay *ov, const PipeArgs& parg,
795         const eTransform& orient, const hwc_rect_t& crop,
796         const hwc_rect_t& pos, const MetaData_t *metadata,
797         const eDest& dest) {
798     ov->setSource(parg, dest);
799     ov->setTransform(orient, dest);
800 
801     int crop_w = crop.right - crop.left;
802     int crop_h = crop.bottom - crop.top;
803     Dim dcrop(crop.left, crop.top, crop_w, crop_h);
804     ov->setCrop(dcrop, dest);
805 
806     int posW = pos.right - pos.left;
807     int posH = pos.bottom - pos.top;
808     Dim position(pos.left, pos.top, posW, posH);
809     ov->setPosition(position, dest);
810 
811     if (metadata)
812         ov->setVisualParams(*metadata, dest);
813 
814     if (!ov->commit(dest)) {
815         return -1;
816     }
817     return 0;
818 }
819 
updateSource(eTransform & orient,Whf & whf,hwc_rect_t & crop)820 static inline void updateSource(eTransform& orient, Whf& whf,
821         hwc_rect_t& crop) {
822     Dim srcCrop(crop.left, crop.top,
823             crop.right - crop.left,
824             crop.bottom - crop.top);
825     //getMdpOrient will switch the flips if the source is 90 rotated.
826     //Clients in Android dont factor in 90 rotation while deciding the flip.
827     orient = static_cast<eTransform>(ovutils::getMdpOrient(orient));
828     preRotateSource(orient, whf, srcCrop);
829     crop.left = srcCrop.x;
830     crop.top = srcCrop.y;
831     crop.right = srcCrop.x + srcCrop.w;
832     crop.bottom = srcCrop.y + srcCrop.h;
833 }
834 
configureLowRes(hwc_context_t * ctx,hwc_layer_1_t * layer,const int & dpy,eMdpFlags & mdpFlags,const eZorder & z,const eIsFg & isFg,const eDest & dest,Rotator ** rot)835 int configureLowRes(hwc_context_t *ctx, hwc_layer_1_t *layer,
836         const int& dpy, eMdpFlags& mdpFlags, const eZorder& z,
837         const eIsFg& isFg, const eDest& dest, Rotator **rot) {
838 
839     private_handle_t *hnd = (private_handle_t *)layer->handle;
840     if(!hnd) {
841         ALOGE("%s: layer handle is NULL", __FUNCTION__);
842         return -1;
843     }
844 
845     MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
846 
847     hwc_rect_t crop = layer->sourceCrop;
848     hwc_rect_t dst = layer->displayFrame;
849     int transform = layer->transform;
850     eTransform orient = static_cast<eTransform>(transform);
851     int downscale = 0;
852     int rotFlags = ovutils::ROT_FLAGS_NONE;
853     Whf whf(hnd->width, hnd->height,
854             getMdpFormat(hnd->format), hnd->size);
855 
856     if(isYuvBuffer(hnd) && ctx->mMDP.version >= qdutils::MDP_V4_2 &&
857        ctx->mMDP.version < qdutils::MDSS_V5) {
858         downscale =  getDownscaleFactor(
859             crop.right - crop.left,
860             crop.bottom - crop.top,
861             dst.right - dst.left,
862             dst.bottom - dst.top);
863         if(downscale) {
864             rotFlags = ROT_DOWNSCALE_ENABLED;
865         }
866     }
867 
868     setMdpFlags(layer, mdpFlags, downscale);
869     trimLayer(ctx, dpy, transform, crop, dst);
870 
871     if(isYuvBuffer(hnd) && //if 90 component or downscale, use rot
872             ((transform & HWC_TRANSFORM_ROT_90) || downscale)) {
873         *rot = ctx->mRotMgr->getNext();
874         if(*rot == NULL) return -1;
875         //Configure rotator for pre-rotation
876         if(configRotator(*rot, whf, mdpFlags, orient, downscale) < 0)
877             return -1;
878         ctx->mLayerRotMap[dpy]->add(layer, *rot);
879         whf.format = (*rot)->getDstFormat();
880         updateSource(orient, whf, crop);
881         rotFlags |= ovutils::ROT_PREROTATED;
882     }
883 
884     //For the mdp, since either we are pre-rotating or MDP does flips
885     orient = OVERLAY_TRANSFORM_0;
886     transform = 0;
887 
888     PipeArgs parg(mdpFlags, whf, z, isFg,
889                   static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
890                   (ovutils::eBlending) getBlending(layer->blending));
891 
892     if(configMdp(ctx->mOverlay, parg, orient, crop, dst, metadata, dest) < 0) {
893         ALOGE("%s: commit failed for low res panel", __FUNCTION__);
894         ctx->mLayerRotMap[dpy]->reset();
895         return -1;
896     }
897     return 0;
898 }
899 
configureHighRes(hwc_context_t * ctx,hwc_layer_1_t * layer,const int & dpy,eMdpFlags & mdpFlagsL,const eZorder & z,const eIsFg & isFg,const eDest & lDest,const eDest & rDest,Rotator ** rot)900 int configureHighRes(hwc_context_t *ctx, hwc_layer_1_t *layer,
901         const int& dpy, eMdpFlags& mdpFlagsL, const eZorder& z,
902         const eIsFg& isFg, const eDest& lDest, const eDest& rDest,
903         Rotator **rot) {
904     private_handle_t *hnd = (private_handle_t *)layer->handle;
905     if(!hnd) {
906         ALOGE("%s: layer handle is NULL", __FUNCTION__);
907         return -1;
908     }
909 
910     MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
911 
912     int hw_w = ctx->dpyAttr[dpy].xres;
913     int hw_h = ctx->dpyAttr[dpy].yres;
914     hwc_rect_t crop = layer->sourceCrop;
915     hwc_rect_t dst = layer->displayFrame;
916     int transform = layer->transform;
917     eTransform orient = static_cast<eTransform>(transform);
918     const int downscale = 0;
919     int rotFlags = ROT_FLAGS_NONE;
920 
921     Whf whf(hnd->width, hnd->height,
922             getMdpFormat(hnd->format), hnd->size);
923 
924     setMdpFlags(layer, mdpFlagsL);
925     trimLayer(ctx, dpy, transform, crop, dst);
926 
927     if(isYuvBuffer(hnd) && (transform & HWC_TRANSFORM_ROT_90)) {
928         (*rot) = ctx->mRotMgr->getNext();
929         if((*rot) == NULL) return -1;
930         //Configure rotator for pre-rotation
931         if(configRotator(*rot, whf, mdpFlagsL, orient, downscale) < 0)
932             return -1;
933         ctx->mLayerRotMap[dpy]->add(layer, *rot);
934         whf.format = (*rot)->getDstFormat();
935         updateSource(orient, whf, crop);
936         rotFlags |= ROT_PREROTATED;
937     }
938 
939     eMdpFlags mdpFlagsR = mdpFlagsL;
940     setMdpFlags(mdpFlagsR, OV_MDSS_MDP_RIGHT_MIXER);
941 
942     hwc_rect_t tmp_cropL, tmp_dstL;
943     hwc_rect_t tmp_cropR, tmp_dstR;
944 
945     if(lDest != OV_INVALID) {
946         tmp_cropL = crop;
947         tmp_dstL = dst;
948         hwc_rect_t scissor = {0, 0, hw_w/2, hw_h };
949         qhwc::calculate_crop_rects(tmp_cropL, tmp_dstL, scissor, 0);
950     }
951     if(rDest != OV_INVALID) {
952         tmp_cropR = crop;
953         tmp_dstR = dst;
954         hwc_rect_t scissor = {hw_w/2, 0, hw_w, hw_h };
955         qhwc::calculate_crop_rects(tmp_cropR, tmp_dstR, scissor, 0);
956     }
957 
958     //When buffer is flipped, contents of mixer config also needs to swapped.
959     //Not needed if the layer is confined to one half of the screen.
960     //If rotator has been used then it has also done the flips, so ignore them.
961     if((orient & OVERLAY_TRANSFORM_FLIP_V) && lDest != OV_INVALID
962             && rDest != OV_INVALID && rot == NULL) {
963         hwc_rect_t new_cropR;
964         new_cropR.left = tmp_cropL.left;
965         new_cropR.right = new_cropR.left + (tmp_cropR.right - tmp_cropR.left);
966 
967         hwc_rect_t new_cropL;
968         new_cropL.left  = new_cropR.right;
969         new_cropL.right = tmp_cropR.right;
970 
971         tmp_cropL.left =  new_cropL.left;
972         tmp_cropL.right =  new_cropL.right;
973 
974         tmp_cropR.left = new_cropR.left;
975         tmp_cropR.right =  new_cropR.right;
976 
977     }
978 
979     //For the mdp, since either we are pre-rotating or MDP does flips
980     orient = OVERLAY_TRANSFORM_0;
981     transform = 0;
982 
983     //configure left mixer
984     if(lDest != OV_INVALID) {
985         PipeArgs pargL(mdpFlagsL, whf, z, isFg,
986                        static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
987                        (ovutils::eBlending) getBlending(layer->blending));
988 
989         if(configMdp(ctx->mOverlay, pargL, orient,
990                 tmp_cropL, tmp_dstL, metadata, lDest) < 0) {
991             ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
992             return -1;
993         }
994     }
995 
996     //configure right mixer
997     if(rDest != OV_INVALID) {
998         PipeArgs pargR(mdpFlagsR, whf, z, isFg,
999                 static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
1000                 (ovutils::eBlending) getBlending(layer->blending));
1001 
1002         tmp_dstR.right = tmp_dstR.right - tmp_dstR.left;
1003         tmp_dstR.left = 0;
1004         if(configMdp(ctx->mOverlay, pargR, orient,
1005                 tmp_cropR, tmp_dstR, metadata, rDest) < 0) {
1006             ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
1007             return -1;
1008         }
1009     }
1010 
1011     return 0;
1012 }
1013 
add(hwc_layer_1_t * layer,Rotator * rot)1014 void LayerRotMap::add(hwc_layer_1_t* layer, Rotator *rot) {
1015     if(mCount >= MAX_SESS) return;
1016     mLayer[mCount] = layer;
1017     mRot[mCount] = rot;
1018     mCount++;
1019 }
1020 
reset()1021 void LayerRotMap::reset() {
1022     for (int i = 0; i < MAX_SESS; i++) {
1023         mLayer[i] = 0;
1024         mRot[i] = 0;
1025     }
1026     mCount = 0;
1027 }
1028 
setReleaseFd(const int & fence)1029 void LayerRotMap::setReleaseFd(const int& fence) {
1030     for(uint32_t i = 0; i < mCount; i++) {
1031         mRot[i]->setReleaseFd(dup(fence));
1032     }
1033 }
1034 
1035 };//namespace qhwc
1036