Home | History | Annotate | Download | only in libhwcomposer
      1 /*
      2 * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved.
      3 *
      4 * Redistribution and use in source and binary forms, with or without
      5 * modification, are permitted provided that the following conditions are
      6 * met:
      7 *    * Redistributions of source code must retain the above copyright
      8 *      notice, this list of conditions and the following disclaimer.
      9 *    * Redistributions in binary form must reproduce the above
     10 *      copyright notice, this list of conditions and the following
     11 *      disclaimer in the documentation and/or other materials provided
     12 *      with the distribution.
     13 *    * Neither the name of The Linux Foundation. nor the names of its
     14 *      contributors may be used to endorse or promote products derived
     15 *      from this software without specific prior written permission.
     16 *
     17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
     18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
     20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
     21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28 */
     29 
     30 #include <unistd.h>
     31 #include <overlay.h>
     32 #include <overlayUtils.h>
     33 #include <overlayWriteback.h>
     34 #include <mdp_version.h>
     35 #include "hwc_ad.h"
     36 #include "hwc_utils.h"
     37 #include "external.h"
     38 
     39 #define DEBUG 0
     40 using namespace overlay;
     41 using namespace overlay::utils;
     42 namespace qhwc {
     43 
     44 //Opens writeback framebuffer and returns fd.
     45 static int openWbFb() {
     46     int wbFd = -1;
     47     //Check opening which FB would connect LM to WB
     48     const int wbFbNum = Overlay::getFbForDpy(Overlay::DPY_WRITEBACK);
     49     if(wbFbNum >= 0) {
     50         char wbFbPath[256];
     51         snprintf (wbFbPath, sizeof(wbFbPath),
     52                 "/sys/class/graphics/fb%d", wbFbNum);
     53         //Opening writeback fb first time would create ad node if the device
     54         //supports adaptive display
     55         wbFd = open(wbFbPath, O_RDONLY);
     56         if(wbFd < 0) {
     57             ALOGE("%s: Failed to open /sys/class/graphics/fb%d with error %s",
     58                     __func__, wbFbNum, strerror(errno));
     59         }
     60     } else {
     61         ALOGD_IF(DEBUG, "%s: No writeback available", __func__);
     62     }
     63     return wbFd;
     64 }
     65 
     66 static inline void closeWbFb(int& fd) {
     67     if(fd >= 0) {
     68         close(fd);
     69         fd = -1;
     70     } else {
     71         ALOGE("%s: Invalid fd %d", __func__, fd);
     72     }
     73 }
     74 
     75 //Helper to write data to ad node
     76 static void adWrite(const int& value) {
     77     const int wbFbNum = Overlay::getFbForDpy(Overlay::DPY_WRITEBACK);
     78     char wbFbPath[256];
     79     snprintf (wbFbPath, sizeof(wbFbPath),
     80             "/sys/class/graphics/fb%d/ad", wbFbNum);
     81     int adFd = open(wbFbPath, O_WRONLY);
     82     if(adFd >= 0) {
     83         char opStr[4] = "";
     84         snprintf(opStr, sizeof(opStr), "%d", value);
     85         ssize_t ret = write(adFd, opStr, strlen(opStr));
     86         if(ret < 0) {
     87             ALOGE("%s: Failed to write %d with error %s",
     88                     __func__, value, strerror(errno));
     89         } else if (ret == 0){
     90             ALOGE("%s Nothing written to ad", __func__);
     91         } else {
     92             ALOGD_IF(DEBUG, "%s: Wrote %d to ad", __func__, value);
     93         }
     94         close(adFd);
     95     } else {
     96         ALOGE("%s: Failed to open /sys/class/graphics/fb%d/ad with error %s",
     97                 __func__, wbFbNum, strerror(errno));
     98     }
     99 }
    100 
    101 //Helper to read data from ad node
    102 static int adRead() {
    103     const int wbFbNum = Overlay::getFbForDpy(Overlay::DPY_WRITEBACK);
    104     int ret = -1;
    105     char wbFbPath[256];
    106     snprintf (wbFbPath, sizeof(wbFbPath),
    107             "/sys/class/graphics/fb%d/ad", wbFbNum);
    108     int adFd = open(wbFbPath, O_RDONLY);
    109     if(adFd >= 0) {
    110         char opStr[4] = {'\0'};
    111         if(read(adFd, opStr, strlen(opStr)) >= 0) {
    112             //Should return -1, 0 or 1
    113             ret = atoi(opStr);
    114             ALOGD_IF(DEBUG, "%s: Read %d from ad", __func__, ret);
    115         } else {
    116             ALOGE("%s: Read from ad node failed with error %s", __func__,
    117                     strerror(errno));
    118         }
    119         close(adFd);
    120     } else {
    121         ALOGD("%s: /sys/class/graphics/fb%d/ad could not be opened : %s",
    122                 __func__, wbFbNum, strerror(errno));
    123     }
    124     return ret;
    125 }
    126 
    127 AssertiveDisplay::AssertiveDisplay(hwc_context_t *ctx) : mWbFd(-1),
    128         mDoable(false), mFeatureEnabled(false),
    129         mDest(overlay::utils::OV_INVALID) {
    130     int fd = openWbFb();
    131     if(fd >= 0) {
    132         //Values in ad node:
    133         //-1 means feature is disabled on device
    134         // 0 means feature exists but turned off, will be turned on by hwc
    135         // 1 means feature is turned on by hwc
    136         // Plus, we do this feature only on split primary displays.
    137         // Plus, we do this feature only if ro.qcom.ad=2
    138 
    139         char property[PROPERTY_VALUE_MAX];
    140         const int ENABLED = 2;
    141         int val = 0;
    142 
    143         if(property_get("ro.qcom.ad", property, "0") > 0) {
    144             val = atoi(property);
    145         }
    146 
    147         if(adRead() >= 0 && isDisplaySplit(ctx, HWC_DISPLAY_PRIMARY) &&
    148                 val == ENABLED) {
    149             ALOGD_IF(DEBUG, "Assertive display feature supported");
    150             mFeatureEnabled = true;
    151         }
    152         closeWbFb(fd);
    153     }
    154 }
    155 
    156 void AssertiveDisplay::markDoable(hwc_context_t *ctx,
    157         const hwc_display_contents_1_t* list) {
    158     mDoable = false;
    159     if(mFeatureEnabled &&
    160         !isSecondaryConnected(ctx) &&
    161         ctx->listStats[HWC_DISPLAY_PRIMARY].yuvCount == 1) {
    162         int nYuvIndex = ctx->listStats[HWC_DISPLAY_PRIMARY].yuvIndices[0];
    163         const hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
    164         private_handle_t *hnd = (private_handle_t *)layer->handle;
    165         if(hnd && hnd->width <= qdutils::MAX_DISPLAY_DIM) {
    166             mDoable = true;
    167         }
    168     }
    169 }
    170 
    171 bool AssertiveDisplay::prepare(hwc_context_t *ctx,
    172         const hwc_rect_t& crop,
    173         const Whf& whf,
    174         const private_handle_t *hnd) {
    175     if(!isDoable()) {
    176         if(isModeOn()) {
    177             //Cleanup one time during this switch
    178             const int off = 0;
    179             adWrite(off);
    180             closeWbFb(mWbFd);
    181         }
    182         return false;
    183     }
    184 
    185     Overlay::PipeSpecs pipeSpecs;
    186     pipeSpecs.formatClass = Overlay::FORMAT_YUV;
    187     pipeSpecs.dpy = overlay::Overlay::DPY_WRITEBACK;
    188     pipeSpecs.fb = false;
    189 
    190     ovutils::eDest dest = ctx->mOverlay->getPipe(pipeSpecs);
    191     if(dest == OV_INVALID) {
    192         ALOGE("%s failed: No VG pipe available", __func__);
    193         mDoable = false;
    194         return false;
    195     }
    196 
    197     overlay::Writeback *wb = overlay::Writeback::getInstance();
    198 
    199     //Set Security flag on writeback
    200     if(isSecureBuffer(hnd)) {
    201         if(!wb->setSecure(isSecureBuffer(hnd))) {
    202             ALOGE("Failure in setting WB secure flag for ad");
    203             return false;
    204         }
    205     }
    206 
    207     if(!wb->configureDpyInfo(hnd->width, hnd->height)) {
    208         ALOGE("%s: config display failed", __func__);
    209         mDoable = false;
    210         return false;
    211     }
    212 
    213     int tmpW, tmpH;
    214     size_t size;
    215     int format = ovutils::getHALFormat(wb->getOutputFormat());
    216     if(format < 0) {
    217         ALOGE("%s invalid format %d", __func__, format);
    218         mDoable = false;
    219         return false;
    220     }
    221 
    222     size = getBufferSizeAndDimensions(hnd->width, hnd->height,
    223                 format, tmpW, tmpH);
    224 
    225     if(!wb->configureMemory((uint32_t)size)) {
    226         ALOGE("%s: config memory failed", __func__);
    227         mDoable = false;
    228         return false;
    229     }
    230 
    231     eMdpFlags mdpFlags = OV_MDP_FLAGS_NONE;
    232     if(isSecureBuffer(hnd)) {
    233         ovutils::setMdpFlags(mdpFlags,
    234                 ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
    235     }
    236 
    237     PipeArgs parg(mdpFlags, whf, ZORDER_0, IS_FG_OFF,
    238             ROT_FLAGS_NONE);
    239     hwc_rect_t dst = crop; //input same as output
    240 
    241     if(configMdp(ctx->mOverlay, parg, OVERLAY_TRANSFORM_0, crop, dst, NULL,
    242                 dest) < 0) {
    243         ALOGE("%s: configMdp failed", __func__);
    244         mDoable = false;
    245         return false;
    246     }
    247 
    248     mDest = dest;
    249     if(!isModeOn()) {
    250         mWbFd = openWbFb();
    251         if(mWbFd >= 0) {
    252             //write to sysfs, one time during this switch
    253             const int on = 1;
    254             adWrite(on);
    255         }
    256     }
    257 
    258     if(!ctx->mOverlay->validateAndSet(overlay::Overlay::DPY_WRITEBACK,
    259             mWbFd)) {
    260         ALOGE("%s: Failed to validate and set overlay for dpy %d"
    261                 ,__FUNCTION__, overlay::Overlay::DPY_WRITEBACK);
    262         return false;
    263     }
    264 
    265     return true;
    266 }
    267 
    268 bool AssertiveDisplay::draw(hwc_context_t *ctx, int fd, uint32_t offset) {
    269     if(!isDoable() || !isModeOn()) {
    270         return false;
    271     }
    272 
    273     if (!ctx->mOverlay->queueBuffer(fd, offset, mDest)) {
    274         ALOGE("%s: queueBuffer failed", __func__);
    275         return false;
    276     }
    277 
    278     overlay::Writeback *wb = overlay::Writeback::getInstance();
    279     if(!wb->writeSync()) {
    280         return false;
    281     }
    282 
    283     return true;
    284 }
    285 
    286 int AssertiveDisplay::getDstFd() const {
    287     overlay::Writeback *wb = overlay::Writeback::getInstance();
    288     return wb->getDstFd();
    289 }
    290 
    291 uint32_t AssertiveDisplay::getDstOffset() const {
    292     overlay::Writeback *wb = overlay::Writeback::getInstance();
    293     return wb->getOffset();
    294 }
    295 
    296 }
    297