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