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 #include <fcntl.h>
     21 #include <errno.h>
     22 
     23 #include <cutils/log.h>
     24 #include <utils/Trace.h>
     25 #include <overlayWriteback.h>
     26 #include "hwc_utils.h"
     27 #include "hwc_fbupdate.h"
     28 #include "hwc_mdpcomp.h"
     29 #include "hwc_dump_layers.h"
     30 #include "hwc_copybit.h"
     31 #include "hwc_virtual.h"
     32 
     33 #define HWCVIRTUAL_LOG 0
     34 
     35 using namespace qhwc;
     36 using namespace overlay;
     37 
     38 HWCVirtualBase* HWCVirtualBase::getObject(bool isVDSEnabled) {
     39 
     40     if(isVDSEnabled) {
     41         ALOGD_IF(HWCVIRTUAL_LOG, "%s: VDS is enabled for Virtual display",
     42                  __FUNCTION__);
     43         return new HWCVirtualVDS();
     44     } else {
     45         ALOGD_IF(HWCVIRTUAL_LOG, "%s: V4L2 is enabled for Virtual display",
     46                  __FUNCTION__);
     47         return new HWCVirtualV4L2();
     48     }
     49 }
     50 
     51 void HWCVirtualVDS::init(hwc_context_t *ctx) {
     52     const int dpy = HWC_DISPLAY_VIRTUAL;
     53     ctx->mFBUpdate[dpy] =
     54             IFBUpdate::getObject(ctx, dpy);
     55     ctx->mMDPComp[dpy] =  MDPComp::getObject(ctx, dpy);
     56 
     57     if(ctx->mFBUpdate[dpy])
     58         ctx->mFBUpdate[dpy]->reset();
     59     if(ctx->mMDPComp[dpy])
     60         ctx->mMDPComp[dpy]->reset();
     61 }
     62 
     63 void HWCVirtualVDS::destroy(hwc_context_t *ctx, size_t /*numDisplays*/,
     64                        hwc_display_contents_1_t** displays) {
     65     int dpy = HWC_DISPLAY_VIRTUAL;
     66 
     67     //Cleanup virtual display objs, since there is no explicit disconnect
     68     if(ctx->dpyAttr[dpy].connected && (displays[dpy] == NULL)) {
     69         ctx->dpyAttr[dpy].connected = false;
     70         ctx->dpyAttr[dpy].isPause = false;
     71 
     72         if(ctx->mFBUpdate[dpy]) {
     73             delete ctx->mFBUpdate[dpy];
     74             ctx->mFBUpdate[dpy] = NULL;
     75         }
     76         if(ctx->mMDPComp[dpy]) {
     77             delete ctx->mMDPComp[dpy];
     78             ctx->mMDPComp[dpy] = NULL;
     79         }
     80         // We reset the WB session to non-secure when the virtual display
     81         // has been disconnected.
     82         if(!Writeback::getInstance()->setSecure(false)) {
     83             ALOGE("Failure while attempting to reset WB session.");
     84         }
     85         ctx->mWfdSyncLock.lock();
     86         ctx->mWfdSyncLock.signal();
     87         ctx->mWfdSyncLock.unlock();
     88     }
     89 }
     90 
     91 int HWCVirtualVDS::prepare(hwc_composer_device_1 *dev,
     92         hwc_display_contents_1_t *list) {
     93     ATRACE_CALL();
     94     //XXX: Fix when framework support is added
     95     hwc_context_t* ctx = (hwc_context_t*)(dev);
     96     const int dpy = HWC_DISPLAY_VIRTUAL;
     97 
     98     if (list && list->outbuf && list->numHwLayers > 0) {
     99         reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1);
    100         uint32_t last = (uint32_t)list->numHwLayers - 1;
    101         hwc_layer_1_t *fbLayer = &list->hwLayers[last];
    102         int fbWidth = 0, fbHeight = 0;
    103         getLayerResolution(fbLayer, fbWidth, fbHeight);
    104         ctx->dpyAttr[dpy].xres = fbWidth;
    105         ctx->dpyAttr[dpy].yres = fbHeight;
    106 
    107         if(ctx->dpyAttr[dpy].connected == false) {
    108             ctx->dpyAttr[dpy].connected = true;
    109             ctx->dpyAttr[dpy].isPause = false;
    110             // We set the vsync period to the primary refresh rate, leaving
    111             // it up to the consumer to decide how fast to consume frames.
    112             ctx->dpyAttr[dpy].vsync_period
    113                               = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period;
    114             init(ctx);
    115             // Do a padding round so that primary can free up a pipe for virtual
    116             // The virtual composition falls back to GPU for this frame
    117             ctx->isPaddingRound = true;
    118         }
    119         if(!ctx->dpyAttr[dpy].isPause) {
    120             ctx->dpyAttr[dpy].isConfiguring = false;
    121             ctx->dpyAttr[dpy].fd = Writeback::getInstance()->getFbFd();
    122             private_handle_t *ohnd = (private_handle_t *)list->outbuf;
    123             Writeback::getInstance()->configureDpyInfo(ohnd->width,
    124                                                           ohnd->height);
    125             setListStats(ctx, list, dpy);
    126 
    127             if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
    128                 const int fbZ = 0;
    129                 if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ))
    130                 {
    131                     ctx->mOverlay->clear(dpy);
    132                     ctx->mLayerRotMap[dpy]->clear();
    133                 }
    134             }
    135         } else {
    136             /* Virtual Display is in Pause state.
    137              * Mark all application layers as OVERLAY so that
    138              * GPU will not compose.
    139              */
    140             for(size_t i = 0 ;i < (size_t)(list->numHwLayers - 1); i++) {
    141                 hwc_layer_1_t *layer = &list->hwLayers[i];
    142                 layer->compositionType = HWC_OVERLAY;
    143             }
    144         }
    145     }
    146     return 0;
    147 }
    148 
    149 int HWCVirtualVDS::set(hwc_context_t *ctx, hwc_display_contents_1_t *list) {
    150     ATRACE_CALL();
    151     int ret = 0;
    152     const int dpy = HWC_DISPLAY_VIRTUAL;
    153 
    154     if (list && list->outbuf && list->numHwLayers > 0) {
    155         uint32_t last = (uint32_t)list->numHwLayers - 1;
    156         hwc_layer_1_t *fbLayer = &list->hwLayers[last];
    157 
    158         if(ctx->dpyAttr[dpy].connected
    159                 && (!ctx->dpyAttr[dpy].isPause))
    160         {
    161             private_handle_t *ohnd = (private_handle_t *)list->outbuf;
    162             int format = ohnd->format;
    163             if (format == HAL_PIXEL_FORMAT_RGBA_8888)
    164                 format = HAL_PIXEL_FORMAT_RGBX_8888;
    165             Writeback::getInstance()->setOutputFormat(
    166                                     utils::getMdpFormat(format));
    167 
    168             // Configure WB as secure if the output buffer handle is secure.
    169             if(isSecureBuffer(ohnd)){
    170                 if(! Writeback::getInstance()->setSecure(true))
    171                 {
    172                     ALOGE("Failed to set WB as secure for virtual display");
    173                     return false;
    174                 }
    175             }
    176 
    177             int fd = -1; //FenceFD from the Copybit
    178             hwc_sync(ctx, list, dpy, fd);
    179 
    180             if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
    181                 ALOGE("%s: MDPComp draw failed", __FUNCTION__);
    182                 ret = -1;
    183             }
    184             // We need an FB layer handle check to cater for this usecase:
    185             // Video is playing in landscape on primary, then launch
    186             // ScreenRecord app.
    187             // In this scenario, the first VDS draw call will have HWC
    188             // composition and VDS does nit involve GPU to get eglSwapBuffer
    189             // to get valid fb handle.
    190             if (fbLayer->handle && !ctx->mFBUpdate[dpy]->draw(ctx,
    191                         (private_handle_t *)fbLayer->handle)) {
    192                 ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
    193                 ret = -1;
    194             }
    195 
    196             Writeback::getInstance()->queueBuffer(ohnd->fd,
    197                                         (uint32_t)ohnd->offset);
    198             if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
    199                 ALOGE("%s: display commit fail!", __FUNCTION__);
    200                 ret = -1;
    201             }
    202 
    203         } else if(list->outbufAcquireFenceFd >= 0) {
    204             //If we dont handle the frame, set retireFenceFd to outbufFenceFd,
    205             //which will make sure, the framework waits on it and closes it.
    206             //The other way is to wait on outbufFenceFd ourselves, close it and
    207             //set retireFenceFd to -1. Since we want hwc to be async, choosing
    208             //the former.
    209             //Also dup because, the closeAcquireFds() will close the outbufFence
    210             list->retireFenceFd = dup(list->outbufAcquireFenceFd);
    211         }
    212     }
    213 
    214     closeAcquireFds(list);
    215     return ret;
    216 }
    217 
    218 void HWCVirtualVDS::pause(hwc_context_t* ctx, int dpy) {
    219     {
    220         Locker::Autolock _l(ctx->mDrawLock);
    221         ctx->dpyAttr[dpy].isActive = true;
    222         ctx->dpyAttr[dpy].isPause = true;
    223         ctx->proc->invalidate(ctx->proc);
    224     }
    225     usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
    226             * 2 / 1000);
    227     return;
    228 }
    229 
    230 void HWCVirtualVDS::resume(hwc_context_t* ctx, int dpy) {
    231     {
    232         Locker::Autolock _l(ctx->mDrawLock);
    233         ctx->dpyAttr[dpy].isConfiguring = true;
    234         ctx->dpyAttr[dpy].isActive = true;
    235         ctx->proc->invalidate(ctx->proc);
    236     }
    237     usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
    238             * 2 / 1000);
    239     //At this point external has all the pipes it would need.
    240     {
    241         Locker::Autolock _l(ctx->mDrawLock);
    242         ctx->dpyAttr[dpy].isPause = false;
    243         ctx->proc->invalidate(ctx->proc);
    244     }
    245     return;
    246 }
    247 
    248 /* Implementation for HWCVirtualV4L2 class */
    249 
    250 int HWCVirtualV4L2::prepare(hwc_composer_device_1 *dev,
    251         hwc_display_contents_1_t *list) {
    252     ATRACE_CALL();
    253 
    254     hwc_context_t* ctx = (hwc_context_t*)(dev);
    255     const int dpy = HWC_DISPLAY_VIRTUAL;
    256 
    257     if (LIKELY(list && list->numHwLayers > 1) &&
    258             ctx->dpyAttr[dpy].isActive &&
    259             ctx->dpyAttr[dpy].connected &&
    260             canUseMDPforVirtualDisplay(ctx,list)) {
    261         reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1);
    262         if(!ctx->dpyAttr[dpy].isPause) {
    263             ctx->dpyAttr[dpy].isConfiguring = false;
    264             setListStats(ctx, list, dpy);
    265             if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
    266                 const int fbZ = 0;
    267                 if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ))
    268                 {
    269                     ctx->mOverlay->clear(dpy);
    270                     ctx->mLayerRotMap[dpy]->clear();
    271                 }
    272             }
    273         } else {
    274             /* Virtual Display is in Pause state.
    275              * Mark all application layers as OVERLAY so that
    276              * GPU will not compose.
    277              */
    278             for(size_t i = 0 ;i < (size_t)(list->numHwLayers - 1); i++) {
    279                 hwc_layer_1_t *layer = &list->hwLayers[i];
    280                 layer->compositionType = HWC_OVERLAY;
    281             }
    282         }
    283     }
    284     return 0;
    285 }
    286 
    287 int HWCVirtualV4L2::set(hwc_context_t *ctx, hwc_display_contents_1_t *list) {
    288     ATRACE_CALL();
    289     int ret = 0;
    290 
    291     const int dpy = HWC_DISPLAY_VIRTUAL;
    292 
    293     if (LIKELY(list) && ctx->dpyAttr[dpy].isActive &&
    294             ctx->dpyAttr[dpy].connected &&
    295             (!ctx->dpyAttr[dpy].isPause) &&
    296             canUseMDPforVirtualDisplay(ctx,list)) {
    297         uint32_t last = (uint32_t)list->numHwLayers - 1;
    298         hwc_layer_1_t *fbLayer = &list->hwLayers[last];
    299         int fd = -1; //FenceFD from the Copybit(valid in async mode)
    300         bool copybitDone = false;
    301         if(ctx->mCopyBit[dpy])
    302             copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
    303 
    304         if(list->numHwLayers > 1)
    305             hwc_sync(ctx, list, dpy, fd);
    306 
    307             // Dump the layers for virtual
    308             if(ctx->mHwcDebug[dpy])
    309                 ctx->mHwcDebug[dpy]->dumpLayers(list);
    310 
    311         if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
    312             ALOGE("%s: MDPComp draw failed", __FUNCTION__);
    313             ret = -1;
    314         }
    315 
    316         int extOnlyLayerIndex =
    317             ctx->listStats[dpy].extOnlyLayerIndex;
    318 
    319         private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
    320         if(extOnlyLayerIndex!= -1) {
    321             hwc_layer_1_t *extLayer = &list->hwLayers[extOnlyLayerIndex];
    322             hnd = (private_handle_t *)extLayer->handle;
    323         } else if(copybitDone) {
    324             hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
    325         }
    326 
    327         if(hnd && !isYuvBuffer(hnd)) {
    328             if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
    329                 ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
    330                 ret = -1;
    331             }
    332         }
    333 
    334         if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
    335             ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy);
    336             ret = -1;
    337         }
    338     }
    339 
    340     closeAcquireFds(list);
    341 
    342     if (list && list->outbuf && (list->retireFenceFd < 0) ) {
    343         // SF assumes HWC waits for the acquire fence and returns a new fence
    344         // that signals when we're done. Since we don't wait, and also don't
    345         // touch the buffer, we can just handle the acquire fence back to SF
    346         // as the retire fence.
    347         list->retireFenceFd = list->outbufAcquireFenceFd;
    348     }
    349 
    350     return ret;
    351 }
    352 
    353 void HWCVirtualV4L2::pause(hwc_context_t* ctx, int dpy) {
    354     {
    355         Locker::Autolock _l(ctx->mDrawLock);
    356         ctx->dpyAttr[dpy].isActive = true;
    357         ctx->dpyAttr[dpy].isPause = true;
    358         ctx->proc->invalidate(ctx->proc);
    359     }
    360     usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
    361             * 2 / 1000);
    362     // At this point all the pipes used by External have been
    363     // marked as UNSET.
    364     {
    365         Locker::Autolock _l(ctx->mDrawLock);
    366         // Perform commit to unstage the pipes.
    367         if (!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
    368             ALOGE("%s: display commit fail! for %d dpy",
    369                     __FUNCTION__, dpy);
    370         }
    371     }
    372     return;
    373 }
    374 
    375 void HWCVirtualV4L2::resume(hwc_context_t* ctx, int dpy){
    376     //Treat Resume as Online event
    377     //Since external didnt have any pipes, force primary to give up
    378     //its pipes; we don't allow inter-mixer pipe transfers.
    379     {
    380         Locker::Autolock _l(ctx->mDrawLock);
    381 
    382         // A dynamic resolution change (DRC) can be made for a WiFi
    383         // display. In order to support the resolution change, we
    384         // need to reconfigure the corresponding display attributes.
    385         // Since DRC is only on WiFi display, we only need to call
    386         // configure() on the VirtualDisplay device.
    387         //TODO: clean up
    388         if(dpy == HWC_DISPLAY_VIRTUAL)
    389             ctx->mVirtualDisplay->configure();
    390 
    391         ctx->dpyAttr[dpy].isConfiguring = true;
    392         ctx->dpyAttr[dpy].isActive = true;
    393         ctx->proc->invalidate(ctx->proc);
    394     }
    395     usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
    396             * 2 / 1000);
    397     //At this point external has all the pipes it would need.
    398     {
    399         Locker::Autolock _l(ctx->mDrawLock);
    400         ctx->dpyAttr[dpy].isPause = false;
    401         ctx->proc->invalidate(ctx->proc);
    402     }
    403     return;
    404 }
    405