Home | History | Annotate | Download | only in libhwcomposer
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  * Copyright (C) 2012-2014, 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 ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
     21 #include <fcntl.h>
     22 #include <errno.h>
     23 
     24 #include <cutils/log.h>
     25 #include <cutils/atomic.h>
     26 #include <EGL/egl.h>
     27 #include <utils/Trace.h>
     28 #include <sys/ioctl.h>
     29 #include <overlay.h>
     30 #include <overlayRotator.h>
     31 #include <overlayWriteback.h>
     32 #include <mdp_version.h>
     33 #include "hwc_utils.h"
     34 #include "hwc_fbupdate.h"
     35 #include "hwc_mdpcomp.h"
     36 #include "hwc_dump_layers.h"
     37 #include "external.h"
     38 #include "hwc_copybit.h"
     39 #include "hwc_ad.h"
     40 #include "profiler.h"
     41 #include "hwc_virtual.h"
     42 
     43 using namespace qhwc;
     44 using namespace overlay;
     45 
     46 #define VSYNC_DEBUG 0
     47 #define BLANK_DEBUG 1
     48 
     49 static int hwc_device_open(const struct hw_module_t* module,
     50                            const char* name,
     51                            struct hw_device_t** device);
     52 
     53 static struct hw_module_methods_t hwc_module_methods = {
     54     open: hwc_device_open
     55 };
     56 
     57 static void reset_panel(struct hwc_composer_device_1* dev);
     58 
     59 hwc_module_t HAL_MODULE_INFO_SYM = {
     60     common: {
     61         tag: HARDWARE_MODULE_TAG,
     62         version_major: 2,
     63         version_minor: 0,
     64         id: HWC_HARDWARE_MODULE_ID,
     65         name: "Qualcomm Hardware Composer Module",
     66         author: "CodeAurora Forum",
     67         methods: &hwc_module_methods,
     68         dso: 0,
     69         reserved: {0},
     70     }
     71 };
     72 
     73 /* In case of non-hybrid WFD session, we are fooling SF by piggybacking on
     74  * HDMI display ID for virtual. This helper is needed to differentiate their
     75  * paths in HAL.
     76  * TODO: Not needed once we have WFD client working on top of Google API's */
     77 
     78 static int getDpyforExternalDisplay(hwc_context_t *ctx, int dpy) {
     79     if(dpy == HWC_DISPLAY_EXTERNAL && ctx->mVirtualonExtActive)
     80         return HWC_DISPLAY_VIRTUAL;
     81     return dpy;
     82 }
     83 
     84 /*
     85  * Save callback functions registered to HWC
     86  */
     87 static void hwc_registerProcs(struct hwc_composer_device_1* dev,
     88                               hwc_procs_t const* procs)
     89 {
     90     ALOGI("%s", __FUNCTION__);
     91     hwc_context_t* ctx = (hwc_context_t*)(dev);
     92     if(!ctx) {
     93         ALOGE("%s: Invalid context", __FUNCTION__);
     94         return;
     95     }
     96     ctx->proc = procs;
     97 
     98     // Now that we have the functions needed, kick off
     99     // the uevent & vsync threads
    100     init_uevent_thread(ctx);
    101     init_vsync_thread(ctx);
    102 }
    103 
    104 //Helper
    105 static void reset(hwc_context_t *ctx, int numDisplays,
    106                   hwc_display_contents_1_t** displays) {
    107 
    108     ctx->numActiveDisplays = 0;
    109     ctx->isPaddingRound = false;
    110 
    111     for(int i = 0; i < numDisplays; i++) {
    112         hwc_display_contents_1_t *list = displays[i];
    113         // XXX:SurfaceFlinger no longer guarantees that this
    114         // value is reset on every prepare. However, for the layer
    115         // cache we need to reset it.
    116         // We can probably rethink that later on
    117         if (LIKELY(list && list->numHwLayers > 0)) {
    118             for(uint32_t j = 0; j < list->numHwLayers; j++) {
    119                 if(list->hwLayers[j].compositionType != HWC_FRAMEBUFFER_TARGET)
    120                     list->hwLayers[j].compositionType = HWC_FRAMEBUFFER;
    121             }
    122 
    123             /* For display devices like SSD and screenrecord, we cannot
    124              * rely on isActive and connected attributes of dpyAttr to
    125              * determine if the displaydevice is active. Hence in case if
    126              * the layer-list is non-null and numHwLayers > 0, we assume
    127              * the display device to be active.
    128              */
    129             ctx->numActiveDisplays += 1;
    130 
    131             if((ctx->mPrevHwLayerCount[i] == 1) and (list->numHwLayers > 1)) {
    132                 /* If the previous cycle for dpy 'i' has 0 AppLayers and the
    133                  * current cycle has atleast 1 AppLayer, padding round needs
    134                  * to be invoked on current cycle to free up the resources.
    135                  */
    136                 ctx->isPaddingRound = true;
    137             }
    138             ctx->mPrevHwLayerCount[i] = list->numHwLayers;
    139         } else {
    140             ctx->mPrevHwLayerCount[i] = 0;
    141         }
    142 
    143         if(ctx->mFBUpdate[i])
    144             ctx->mFBUpdate[i]->reset();
    145         if(ctx->mCopyBit[i])
    146             ctx->mCopyBit[i]->reset();
    147         if(ctx->mLayerRotMap[i])
    148             ctx->mLayerRotMap[i]->reset();
    149     }
    150 
    151     ctx->mAD->reset();
    152     MDPComp::reset();
    153     if(ctx->mHWCVirtual)
    154         ctx->mHWCVirtual->destroy(ctx, numDisplays, displays);
    155 }
    156 
    157 bool isEqual(float f1, float f2) {
    158         return ((int)(f1*100) == (int)(f2*100)) ? true : false;
    159 }
    160 
    161 static void scaleDisplayFrame(hwc_context_t *ctx, int dpy,
    162                             hwc_display_contents_1_t *list) {
    163     float origXres = ctx->dpyAttr[dpy].xres_orig;
    164     float origYres = ctx->dpyAttr[dpy].yres_orig;
    165     float fakeXres = ctx->dpyAttr[dpy].xres;
    166     float fakeYres = ctx->dpyAttr[dpy].yres;
    167     float xresRatio = origXres / fakeXres;
    168     float yresRatio = origYres / fakeYres;
    169     for (size_t i = 0; i < list->numHwLayers; i++) {
    170         hwc_layer_1_t *layer = &list->hwLayers[i];
    171         hwc_rect_t& displayFrame = layer->displayFrame;
    172         hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
    173         float layerWidth = displayFrame.right - displayFrame.left;
    174         float layerHeight = displayFrame.bottom - displayFrame.top;
    175         float sourceWidth = sourceCrop.right - sourceCrop.left;
    176         float sourceHeight = sourceCrop.bottom - sourceCrop.top;
    177 
    178         if (isEqual(layerWidth / sourceWidth, xresRatio) &&
    179                 isEqual(layerHeight / sourceHeight, yresRatio))
    180             break;
    181 
    182         displayFrame.left = xresRatio * displayFrame.left;
    183         displayFrame.top = yresRatio * displayFrame.top;
    184         displayFrame.right = displayFrame.left + layerWidth * xresRatio;
    185         displayFrame.bottom = displayFrame.top + layerHeight * yresRatio;
    186     }
    187 }
    188 
    189 static int hwc_prepare_primary(hwc_composer_device_1 *dev,
    190         hwc_display_contents_1_t *list) {
    191     ATRACE_CALL();
    192     hwc_context_t* ctx = (hwc_context_t*)(dev);
    193     const int dpy = HWC_DISPLAY_PRIMARY;
    194     bool fbComp = false;
    195     if (LIKELY(list && list->numHwLayers > 1) &&
    196             ctx->dpyAttr[dpy].isActive) {
    197 
    198         if (ctx->dpyAttr[dpy].customFBSize)
    199             scaleDisplayFrame(ctx, dpy, list);
    200 
    201         reset_layer_prop(ctx, dpy, list->numHwLayers - 1);
    202         setListStats(ctx, list, dpy);
    203 
    204         fbComp = (ctx->mMDPComp[dpy]->prepare(ctx, list) < 0);
    205 
    206         if (fbComp) {
    207             const int fbZ = 0;
    208             ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ);
    209         }
    210 
    211         if (ctx->mMDP.version < qdutils::MDP_V4_0) {
    212             if(ctx->mCopyBit[dpy])
    213                 ctx->mCopyBit[dpy]->prepare(ctx, list, dpy);
    214         }
    215         setGPUHint(ctx, list);
    216     }
    217     return 0;
    218 }
    219 
    220 static int hwc_prepare_external(hwc_composer_device_1 *dev,
    221         hwc_display_contents_1_t *list) {
    222     ATRACE_CALL();
    223     hwc_context_t* ctx = (hwc_context_t*)(dev);
    224     const int dpy = HWC_DISPLAY_EXTERNAL;
    225 
    226     if (LIKELY(list && list->numHwLayers > 1) &&
    227             ctx->dpyAttr[dpy].isActive &&
    228             ctx->dpyAttr[dpy].connected) {
    229         reset_layer_prop(ctx, dpy, list->numHwLayers - 1);
    230         if(!ctx->dpyAttr[dpy].isPause) {
    231             ctx->dpyAttr[dpy].isConfiguring = false;
    232             setListStats(ctx, list, dpy);
    233             if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
    234                 const int fbZ = 0;
    235                 ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ);
    236             }
    237         } else {
    238             /* External Display is in Pause state.
    239              * Mark all application layers as OVERLAY so that
    240              * GPU will not compose.
    241              */
    242             for(size_t i = 0 ;i < (size_t)(list->numHwLayers - 1); i++) {
    243                 hwc_layer_1_t *layer = &list->hwLayers[i];
    244                 layer->compositionType = HWC_OVERLAY;
    245             }
    246         }
    247     }
    248     return 0;
    249 }
    250 
    251 static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays,
    252                        hwc_display_contents_1_t** displays)
    253 {
    254     int ret = 0;
    255     hwc_context_t* ctx = (hwc_context_t*)(dev);
    256 
    257     if (ctx->mPanelResetStatus) {
    258         ALOGW("%s: panel is in bad state. reset the panel", __FUNCTION__);
    259         reset_panel(dev);
    260     }
    261 
    262     //Will be unlocked at the end of set
    263     ctx->mDrawLock.lock();
    264     reset(ctx, numDisplays, displays);
    265 
    266     ctx->mOverlay->configBegin();
    267     ctx->mRotMgr->configBegin();
    268     overlay::Writeback::configBegin();
    269 
    270     for (int32_t i = (numDisplays-1); i >= 0; i--) {
    271         hwc_display_contents_1_t *list = displays[i];
    272         int dpy = getDpyforExternalDisplay(ctx, i);
    273         switch(dpy) {
    274             case HWC_DISPLAY_PRIMARY:
    275                 ret = hwc_prepare_primary(dev, list);
    276                 break;
    277             case HWC_DISPLAY_EXTERNAL:
    278                 ret = hwc_prepare_external(dev, list);
    279                 break;
    280             case HWC_DISPLAY_VIRTUAL:
    281                 if(ctx->mHWCVirtual)
    282                     ret = ctx->mHWCVirtual->prepare(dev, list);
    283                 break;
    284             default:
    285                 ret = -EINVAL;
    286         }
    287     }
    288 
    289     ctx->mOverlay->configDone();
    290     ctx->mRotMgr->configDone();
    291     overlay::Writeback::configDone();
    292 
    293     return ret;
    294 }
    295 
    296 static int hwc_eventControl(struct hwc_composer_device_1* dev, int dpy,
    297                              int event, int enable)
    298 {
    299     ATRACE_CALL();
    300     int ret = 0;
    301     hwc_context_t* ctx = (hwc_context_t*)(dev);
    302     switch(event) {
    303         case HWC_EVENT_VSYNC:
    304             if (ctx->vstate.enable == enable)
    305                 break;
    306             ret = hwc_vsync_control(ctx, dpy, enable);
    307             if(ret == 0)
    308                 ctx->vstate.enable = !!enable;
    309             ALOGD_IF (VSYNC_DEBUG, "VSYNC state changed to %s",
    310                       (enable)?"ENABLED":"DISABLED");
    311             break;
    312 #ifdef QCOM_BSP
    313         case  HWC_EVENT_ORIENTATION:
    314             if(dpy == HWC_DISPLAY_PRIMARY) {
    315                 Locker::Autolock _l(ctx->mDrawLock);
    316                 // store the primary display orientation
    317                 ctx->deviceOrientation = enable;
    318             }
    319             break;
    320 #endif
    321         default:
    322             ret = -EINVAL;
    323     }
    324     return ret;
    325 }
    326 
    327 static int hwc_blank(struct hwc_composer_device_1* dev, int dpy, int blank)
    328 {
    329     ATRACE_CALL();
    330     hwc_context_t* ctx = (hwc_context_t*)(dev);
    331 
    332     Locker::Autolock _l(ctx->mDrawLock);
    333     int ret = 0, value = 0;
    334 
    335     /* In case of non-hybrid WFD session, we are fooling SF by
    336      * piggybacking on HDMI display ID for virtual.
    337      * TODO: Not needed once we have WFD client working on top
    338      * of Google API's.
    339      */
    340     dpy = getDpyforExternalDisplay(ctx,dpy);
    341 
    342     ALOGD_IF(BLANK_DEBUG, "%s: %s display: %d", __FUNCTION__,
    343           blank==1 ? "Blanking":"Unblanking", dpy);
    344     if(blank) {
    345         // free up all the overlay pipes in use
    346         // when we get a blank for either display
    347         // makes sure that all pipes are freed
    348         ctx->mOverlay->configBegin();
    349         ctx->mOverlay->configDone();
    350         ctx->mRotMgr->clear();
    351         // If VDS is connected, do not clear WB object as it
    352         // will end up detaching IOMMU. This is required
    353         // to send black frame to WFD sink on power suspend.
    354         // Note: With this change, we keep the WriteBack object
    355         // alive on power suspend for AD use case.
    356     }
    357     switch(dpy) {
    358     case HWC_DISPLAY_PRIMARY:
    359         value = blank ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK;
    360         if(ioctl(ctx->dpyAttr[dpy].fd, FBIOBLANK, value) < 0 ) {
    361             ALOGE("%s: Failed to handle blank event(%d) for Primary!!",
    362                   __FUNCTION__, blank );
    363             return -1;
    364         }
    365 
    366         if(!blank) {
    367             // Enable HPD here, as during bootup unblank is called
    368             // when SF is completely initialized
    369             ctx->mExtDisplay->setHPD(1);
    370         }
    371 
    372         ctx->dpyAttr[dpy].isActive = !blank;
    373 
    374         if(ctx->mVirtualonExtActive) {
    375             /* if mVirtualonExtActive is true, display hal will
    376              * receive unblank calls for non-hybrid WFD solution
    377              * since we piggyback on HDMI.
    378              * TODO: Not needed once we have WFD client working on top
    379              of Google API's */
    380             break;
    381         }
    382     case HWC_DISPLAY_VIRTUAL:
    383         /* There are two ways to reach this block of code.
    384 
    385          * Display hal has received unblank call on HWC_DISPLAY_EXTERNAL
    386          and ctx->mVirtualonExtActive is true. In this case, non-hybrid
    387          WFD is active. If so, getDpyforExternalDisplay will return dpy
    388          as HWC_DISPLAY_VIRTUAL.
    389 
    390          * Display hal has received unblank call on HWC_DISPLAY_PRIMARY
    391          and since SF is not aware of VIRTUAL DISPLAY being handle by HWC,
    392          it wont send blank / unblank events for it. We piggyback on
    393          PRIMARY DISPLAY events to release mdp pipes and
    394          activate/deactivate VIRTUAL DISPLAY.
    395 
    396          * TODO: This separate case statement is not needed once we have
    397          WFD client working on top of Google API's.
    398 
    399          */
    400 
    401         if(ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected) {
    402             if(blank and (!ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isPause)) {
    403                 int dpy = HWC_DISPLAY_VIRTUAL;
    404                 if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
    405                     ALOGE("%s: display commit fail for virtual!", __FUNCTION__);
    406                     ret = -1;
    407                 }
    408             }
    409             ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isActive = !blank;
    410         }
    411         break;
    412     case HWC_DISPLAY_EXTERNAL:
    413         if(blank) {
    414             if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
    415                 ALOGE("%s: display commit fail for external!", __FUNCTION__);
    416                 ret = -1;
    417             }
    418         }
    419         ctx->dpyAttr[dpy].isActive = !blank;
    420         break;
    421     default:
    422         return -EINVAL;
    423     }
    424 
    425     ALOGD_IF(BLANK_DEBUG, "%s: Done %s display: %d", __FUNCTION__,
    426           blank ? "blanking":"unblanking", dpy);
    427     return ret;
    428 }
    429 
    430 static void reset_panel(struct hwc_composer_device_1* dev)
    431 {
    432     int ret = 0;
    433     hwc_context_t* ctx = (hwc_context_t*)(dev);
    434 
    435     if (!ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isActive) {
    436         ALOGD ("%s : Display OFF - Skip BLANK & UNBLANK", __FUNCTION__);
    437         ctx->mPanelResetStatus = false;
    438         return;
    439     }
    440 
    441     ALOGD("%s: calling BLANK DISPLAY", __FUNCTION__);
    442     ret = hwc_blank(dev, HWC_DISPLAY_PRIMARY, 1);
    443     if (ret < 0) {
    444         ALOGE("%s: FBIOBLANK failed to BLANK:  %s", __FUNCTION__,
    445                                                             strerror(errno));
    446     }
    447 
    448     ALOGD("%s: calling UNBLANK DISPLAY and enabling vsync", __FUNCTION__);
    449     ret = hwc_blank(dev, HWC_DISPLAY_PRIMARY, 0);
    450     if (ret < 0) {
    451         ALOGE("%s: FBIOBLANK failed to UNBLANK : %s", __FUNCTION__,
    452                                                             strerror(errno));
    453     }
    454     hwc_vsync_control(ctx, HWC_DISPLAY_PRIMARY, 1);
    455 
    456     ctx->mPanelResetStatus = false;
    457 }
    458 
    459 
    460 static int hwc_query(struct hwc_composer_device_1* dev,
    461                      int param, int* value)
    462 {
    463     hwc_context_t* ctx = (hwc_context_t*)(dev);
    464     int supported = HWC_DISPLAY_PRIMARY_BIT;
    465 
    466     switch (param) {
    467     case HWC_BACKGROUND_LAYER_SUPPORTED:
    468         // Not supported for now
    469         value[0] = 0;
    470         break;
    471     case HWC_DISPLAY_TYPES_SUPPORTED:
    472         if(ctx->mMDP.hasOverlay) {
    473             supported |= HWC_DISPLAY_VIRTUAL_BIT;
    474             if(!(qdutils::MDPVersion::getInstance().is8x26() ||
    475                         qdutils::MDPVersion::getInstance().is8x16()))
    476                 supported |= HWC_DISPLAY_EXTERNAL_BIT;
    477         }
    478         value[0] = supported;
    479         break;
    480     case HWC_FORMAT_RB_SWAP:
    481         value[0] = 1;
    482         break;
    483     case HWC_COLOR_FILL:
    484         value[0] = 1;
    485         break;
    486     default:
    487         return -EINVAL;
    488     }
    489     return 0;
    490 
    491 }
    492 
    493 
    494 static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
    495     ATRACE_CALL();
    496     int ret = 0;
    497     const int dpy = HWC_DISPLAY_PRIMARY;
    498     if (LIKELY(list) && ctx->dpyAttr[dpy].isActive) {
    499         uint32_t last = list->numHwLayers - 1;
    500         hwc_layer_1_t *fbLayer = &list->hwLayers[last];
    501         int fd = -1; //FenceFD from the Copybit(valid in async mode)
    502         bool copybitDone = false;
    503         if(ctx->mCopyBit[dpy])
    504             copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
    505         if(list->numHwLayers > 1)
    506             hwc_sync(ctx, list, dpy, fd);
    507 
    508         // Dump the layers for primary
    509         if(ctx->mHwcDebug[dpy])
    510             ctx->mHwcDebug[dpy]->dumpLayers(list);
    511 
    512         if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
    513             ALOGE("%s: MDPComp draw failed", __FUNCTION__);
    514             ret = -1;
    515         }
    516 
    517         //TODO We dont check for SKIP flag on this layer because we need PAN
    518         //always. Last layer is always FB
    519         private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
    520         if(copybitDone && ctx->mMDP.version >= qdutils::MDP_V4_0) {
    521             hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
    522         }
    523 
    524         if(hnd) {
    525             if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
    526                 ALOGE("%s: FBUpdate draw failed", __FUNCTION__);
    527                 ret = -1;
    528             }
    529         }
    530 
    531         if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd,
    532                                             ctx->listStats[dpy].roi)) {
    533             ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy);
    534             ret = -1;
    535         }
    536 
    537     }
    538 
    539     closeAcquireFds(list);
    540     return ret;
    541 }
    542 
    543 static int hwc_set_external(hwc_context_t *ctx,
    544                             hwc_display_contents_1_t* list)
    545 {
    546     ATRACE_CALL();
    547     int ret = 0;
    548 
    549     const int dpy = HWC_DISPLAY_EXTERNAL;
    550 
    551 
    552     if (LIKELY(list) && ctx->dpyAttr[dpy].isActive &&
    553         ctx->dpyAttr[dpy].connected &&
    554         !ctx->dpyAttr[dpy].isPause) {
    555         uint32_t last = list->numHwLayers - 1;
    556         hwc_layer_1_t *fbLayer = &list->hwLayers[last];
    557         int fd = -1; //FenceFD from the Copybit(valid in async mode)
    558         bool copybitDone = false;
    559         if(ctx->mCopyBit[dpy])
    560             copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
    561 
    562         if(list->numHwLayers > 1)
    563             hwc_sync(ctx, list, dpy, fd);
    564 
    565         // Dump the layers for external
    566         if(ctx->mHwcDebug[dpy])
    567             ctx->mHwcDebug[dpy]->dumpLayers(list);
    568 
    569         if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
    570             ALOGE("%s: MDPComp draw failed", __FUNCTION__);
    571             ret = -1;
    572         }
    573 
    574         int extOnlyLayerIndex =
    575                 ctx->listStats[dpy].extOnlyLayerIndex;
    576 
    577         private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
    578         if(extOnlyLayerIndex!= -1) {
    579             hwc_layer_1_t *extLayer = &list->hwLayers[extOnlyLayerIndex];
    580             hnd = (private_handle_t *)extLayer->handle;
    581         } else if(copybitDone) {
    582             hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
    583         }
    584 
    585         if(hnd && !isYuvBuffer(hnd)) {
    586             if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
    587                 ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
    588                 ret = -1;
    589             }
    590         }
    591 
    592         if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
    593             ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy);
    594             ret = -1;
    595         }
    596     }
    597 
    598     closeAcquireFds(list);
    599     return ret;
    600 }
    601 
    602 static int hwc_set(hwc_composer_device_1 *dev,
    603                    size_t numDisplays,
    604                    hwc_display_contents_1_t** displays)
    605 {
    606     int ret = 0;
    607     hwc_context_t* ctx = (hwc_context_t*)(dev);
    608     for (uint32_t i = 0; i < numDisplays; i++) {
    609         hwc_display_contents_1_t* list = displays[i];
    610         int dpy = getDpyforExternalDisplay(ctx, i);
    611         switch(dpy) {
    612             case HWC_DISPLAY_PRIMARY:
    613                 ret = hwc_set_primary(ctx, list);
    614                 break;
    615             case HWC_DISPLAY_EXTERNAL:
    616                 ret = hwc_set_external(ctx, list);
    617                 break;
    618             case HWC_DISPLAY_VIRTUAL:
    619                 if(ctx->mHWCVirtual)
    620                     ret = ctx->mHWCVirtual->set(ctx, list);
    621                 break;
    622             default:
    623                 ret = -EINVAL;
    624         }
    625     }
    626     // This is only indicative of how many times SurfaceFlinger posts
    627     // frames to the display.
    628     CALC_FPS();
    629     MDPComp::resetIdleFallBack();
    630     ctx->mVideoTransFlag = false;
    631     if(ctx->mRotMgr->getNumActiveSessions() == 0)
    632         Overlay::setDMAMode(Overlay::DMA_LINE_MODE);
    633     //Was locked at the beginning of prepare
    634     ctx->mDrawLock.unlock();
    635     return ret;
    636 }
    637 
    638 int hwc_getDisplayConfigs(struct hwc_composer_device_1* dev, int disp,
    639         uint32_t* configs, size_t* numConfigs) {
    640     int ret = 0;
    641     hwc_context_t* ctx = (hwc_context_t*)(dev);
    642     disp = getDpyforExternalDisplay(ctx, disp);
    643     //in 1.1 there is no way to choose a config, report as config id # 0
    644     //This config is passed to getDisplayAttributes. Ignore for now.
    645     switch(disp) {
    646         case HWC_DISPLAY_PRIMARY:
    647             if(*numConfigs > 0) {
    648                 configs[0] = 0;
    649                 *numConfigs = 1;
    650             }
    651             ret = 0; //NO_ERROR
    652             break;
    653         case HWC_DISPLAY_EXTERNAL:
    654         case HWC_DISPLAY_VIRTUAL:
    655             ret = -1; //Not connected
    656             if(ctx->dpyAttr[disp].connected) {
    657                 ret = 0; //NO_ERROR
    658                 if(*numConfigs > 0) {
    659                     configs[0] = 0;
    660                     *numConfigs = 1;
    661                 }
    662             }
    663             break;
    664     }
    665     return ret;
    666 }
    667 
    668 int hwc_getDisplayAttributes(struct hwc_composer_device_1* dev, int disp,
    669         uint32_t /*config*/, const uint32_t* attributes, int32_t* values) {
    670 
    671     hwc_context_t* ctx = (hwc_context_t*)(dev);
    672     disp = getDpyforExternalDisplay(ctx, disp);
    673     //If hotpluggable displays(i.e, HDMI, WFD) are inactive return error
    674     if( (disp != HWC_DISPLAY_PRIMARY) && !ctx->dpyAttr[disp].connected) {
    675         return -1;
    676     }
    677 
    678     //From HWComposer
    679     static const uint32_t DISPLAY_ATTRIBUTES[] = {
    680         HWC_DISPLAY_VSYNC_PERIOD,
    681         HWC_DISPLAY_WIDTH,
    682         HWC_DISPLAY_HEIGHT,
    683         HWC_DISPLAY_DPI_X,
    684         HWC_DISPLAY_DPI_Y,
    685         HWC_DISPLAY_NO_ATTRIBUTE,
    686     };
    687 
    688     const int NUM_DISPLAY_ATTRIBUTES = (sizeof(DISPLAY_ATTRIBUTES) /
    689             sizeof(DISPLAY_ATTRIBUTES)[0]);
    690 
    691     for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) {
    692         switch (attributes[i]) {
    693         case HWC_DISPLAY_VSYNC_PERIOD:
    694             values[i] = ctx->dpyAttr[disp].vsync_period;
    695             break;
    696         case HWC_DISPLAY_WIDTH:
    697             values[i] = ctx->dpyAttr[disp].xres;
    698             ALOGD("%s disp = %d, width = %d",__FUNCTION__, disp,
    699                     ctx->dpyAttr[disp].xres);
    700             break;
    701         case HWC_DISPLAY_HEIGHT:
    702             values[i] = ctx->dpyAttr[disp].yres;
    703             ALOGD("%s disp = %d, height = %d",__FUNCTION__, disp,
    704                     ctx->dpyAttr[disp].yres);
    705             break;
    706         case HWC_DISPLAY_DPI_X:
    707             values[i] = (int32_t) (ctx->dpyAttr[disp].xdpi*1000.0);
    708             break;
    709         case HWC_DISPLAY_DPI_Y:
    710             values[i] = (int32_t) (ctx->dpyAttr[disp].ydpi*1000.0);
    711             break;
    712         default:
    713             ALOGE("Unknown display attribute %d",
    714                     attributes[i]);
    715             return -EINVAL;
    716         }
    717     }
    718     return 0;
    719 }
    720 
    721 void hwc_dump(struct hwc_composer_device_1* dev, char *buff, int buff_len)
    722 {
    723     hwc_context_t* ctx = (hwc_context_t*)(dev);
    724     Locker::Autolock _l(ctx->mDrawLock);
    725     android::String8 aBuf("");
    726     dumpsys_log(aBuf, "Qualcomm HWC state:\n");
    727     dumpsys_log(aBuf, "  MDPVersion=%d\n", ctx->mMDP.version);
    728     dumpsys_log(aBuf, "  DisplayPanel=%c\n", ctx->mMDP.panel);
    729     if(ctx->vstate.fakevsync)
    730         dumpsys_log(aBuf, "  Vsync is being faked!!\n");
    731     for(int dpy = 0; dpy < HWC_NUM_DISPLAY_TYPES; dpy++) {
    732         if(ctx->mMDPComp[dpy])
    733             ctx->mMDPComp[dpy]->dump(aBuf);
    734     }
    735     char ovDump[2048] = {'\0'};
    736     ctx->mOverlay->getDump(ovDump, 2048);
    737     dumpsys_log(aBuf, ovDump);
    738     ovDump[0] = '\0';
    739     ctx->mRotMgr->getDump(ovDump, 1024);
    740     dumpsys_log(aBuf, ovDump);
    741     ovDump[0] = '\0';
    742     if(Writeback::getDump(ovDump, 1024)) {
    743         dumpsys_log(aBuf, ovDump);
    744         ovDump[0] = '\0';
    745     }
    746     strlcpy(buff, aBuf.string(), buff_len);
    747 }
    748 
    749 static int hwc_device_close(struct hw_device_t *dev)
    750 {
    751     if(!dev) {
    752         ALOGE("%s: NULL device pointer", __FUNCTION__);
    753         return -1;
    754     }
    755     closeContext((hwc_context_t*)dev);
    756     free(dev);
    757 
    758     return 0;
    759 }
    760 
    761 static int hwc_device_open(const struct hw_module_t* module, const char* name,
    762                            struct hw_device_t** device)
    763 {
    764     int status = -EINVAL;
    765 
    766     if (!strcmp(name, HWC_HARDWARE_COMPOSER)) {
    767         struct hwc_context_t *dev;
    768         dev = (hwc_context_t*)malloc(sizeof(*dev));
    769         if(dev == NULL)
    770             return status;
    771         memset(dev, 0, sizeof(*dev));
    772 
    773         //Initialize hwc context
    774         initContext(dev);
    775 
    776         //Setup HWC methods
    777         dev->device.common.tag          = HARDWARE_DEVICE_TAG;
    778         dev->device.common.version      = HWC_DEVICE_API_VERSION_1_3;
    779         dev->device.common.module       = const_cast<hw_module_t*>(module);
    780         dev->device.common.close        = hwc_device_close;
    781         dev->device.prepare             = hwc_prepare;
    782         dev->device.set                 = hwc_set;
    783         dev->device.eventControl        = hwc_eventControl;
    784         dev->device.blank               = hwc_blank;
    785         dev->device.query               = hwc_query;
    786         dev->device.registerProcs       = hwc_registerProcs;
    787         dev->device.dump                = hwc_dump;
    788         dev->device.getDisplayConfigs   = hwc_getDisplayConfigs;
    789         dev->device.getDisplayAttributes = hwc_getDisplayAttributes;
    790         *device = &dev->device.common;
    791         status = 0;
    792     }
    793     return status;
    794 }
    795