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