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 
     38 #define DEBUG 0
     39 using namespace overlay;
     40 using namespace overlay::utils;
     41 namespace qhwc {
     42 
     43 //Helper to write data to ad node
     44 static void adWrite(const int& value) {
     45     const int wbFbNum = Overlay::getFbForDpy(Overlay::DPY_WRITEBACK);
     46     char wbFbPath[256];
     47     snprintf (wbFbPath, sizeof(wbFbPath),
     48             "/sys/class/graphics/fb%d/ad", wbFbNum);
     49     int adFd = open(wbFbPath, O_WRONLY);
     50     if(adFd >= 0) {
     51         char opStr[4] = "";
     52         snprintf(opStr, sizeof(opStr), "%d", value);
     53         ssize_t ret = write(adFd, opStr, strlen(opStr));
     54         if(ret < 0) {
     55             ALOGE("%s: Failed to write %d with error %s",
     56                     __func__, value, strerror(errno));
     57         } else if (ret == 0){
     58             ALOGE("%s Nothing written to ad", __func__);
     59         } else {
     60             ALOGD_IF(DEBUG, "%s: Wrote %d to ad", __func__, value);
     61         }
     62         close(adFd);
     63     } else {
     64         ALOGE("%s: Failed to open /sys/class/graphics/fb%d/ad with error %s",
     65                 __func__, wbFbNum, strerror(errno));
     66     }
     67 }
     68 
     69 //Helper to read data from ad node
     70 static int adRead() {
     71     const int wbFbNum = Overlay::getFbForDpy(Overlay::DPY_WRITEBACK);
     72     int ret = -1;
     73     char wbFbPath[256];
     74     snprintf (wbFbPath, sizeof(wbFbPath),
     75             "/sys/class/graphics/fb%d/ad", wbFbNum);
     76     int adFd = open(wbFbPath, O_RDONLY);
     77     if(adFd >= 0) {
     78         char opStr[4];
     79         ssize_t bytesRead = read(adFd, opStr, sizeof(opStr) - 1);
     80         if(bytesRead > 0) {
     81             opStr[bytesRead] = '\0';
     82             //Should return -1, 0 or 1
     83             ret = atoi(opStr);
     84             ALOGD_IF(DEBUG, "%s: Read %d from ad", __func__, ret);
     85         } else if(bytesRead == 0) {
     86             ALOGE("%s: ad node empty", __func__);
     87         } else {
     88             ALOGE("%s: Read from ad node failed with error %s", __func__,
     89                     strerror(errno));
     90         }
     91         close(adFd);
     92     } else {
     93         ALOGD("%s: /sys/class/graphics/fb%d/ad could not be opened : %s",
     94                 __func__, wbFbNum, strerror(errno));
     95     }
     96     return ret;
     97 }
     98 
     99 AssertiveDisplay::AssertiveDisplay(hwc_context_t *ctx) :
    100      mTurnedOff(true), mFeatureEnabled(false),
    101      mDest(overlay::utils::OV_INVALID)
    102 {
    103     //Values in ad node:
    104     //-1 means feature is disabled on device
    105     // 0 means feature exists but turned off, will be turned on by hwc
    106     // 1 means feature is turned on by hwc
    107     // Plus, we do this feature only on split primary displays.
    108     // Plus, we do this feature only if ro.qcom.ad=2
    109 
    110     char property[PROPERTY_VALUE_MAX];
    111     const int ENABLED = 2;
    112     int val = 0;
    113 
    114     if(property_get("ro.qcom.ad", property, "0") > 0) {
    115         val = atoi(property);
    116     }
    117 
    118     if(adRead() >= 0 && isDisplaySplit(ctx, HWC_DISPLAY_PRIMARY) &&
    119             val == ENABLED) {
    120         ALOGD_IF(DEBUG, "Assertive display feature supported");
    121         mFeatureEnabled = true;
    122         // If feature exists but is turned off, set mTurnedOff to true
    123         mTurnedOff = adRead() > 0 ? false : true;
    124     }
    125 }
    126 
    127 void AssertiveDisplay::markDoable(hwc_context_t *ctx,
    128         const hwc_display_contents_1_t* list) {
    129     mDoable = false;
    130     if(mFeatureEnabled &&
    131         !isSecondaryConnected(ctx) &&
    132         ctx->listStats[HWC_DISPLAY_PRIMARY].yuvCount == 1) {
    133         int nYuvIndex = ctx->listStats[HWC_DISPLAY_PRIMARY].yuvIndices[0];
    134         const hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
    135         private_handle_t *hnd = (private_handle_t *)layer->handle;
    136         qdutils::MDPVersion& mdpHw =  qdutils::MDPVersion::getInstance();
    137         if(hnd && hnd->width <= (int) mdpHw.getMaxMixerWidth()) {
    138             mDoable = true;
    139         }
    140     }
    141 }
    142 
    143 void AssertiveDisplay::turnOffAD() {
    144     if(mFeatureEnabled) {
    145         if(!mTurnedOff) {
    146             const int off = 0;
    147             adWrite(off);
    148             mTurnedOff = true;
    149         }
    150     }
    151     mDoable = false;
    152 }
    153 
    154 bool AssertiveDisplay::prepare(hwc_context_t *ctx,
    155         const hwc_rect_t& crop,
    156         const Whf& whf,
    157         const private_handle_t *hnd) {
    158     if(!isDoable()) {
    159         //Cleanup one time during this switch
    160         turnOffAD();
    161         return false;
    162     }
    163 
    164     Overlay::PipeSpecs pipeSpecs;
    165     pipeSpecs.formatClass = Overlay::FORMAT_YUV;
    166     pipeSpecs.dpy = overlay::Overlay::DPY_WRITEBACK;
    167     pipeSpecs.fb = false;
    168 
    169     ovutils::eDest dest = ctx->mOverlay->getPipe(pipeSpecs);
    170     if(dest == OV_INVALID) {
    171         ALOGE("%s failed: No VG pipe available", __func__);
    172         mDoable = false;
    173         return false;
    174     }
    175 
    176     overlay::Writeback *wb = overlay::Writeback::getInstance();
    177 
    178     //Set Security flag on writeback
    179     if(isSecureBuffer(hnd)) {
    180         if(!wb->setSecure(isSecureBuffer(hnd))) {
    181             ALOGE("Failure in setting WB secure flag for ad");
    182             return false;
    183         }
    184     }
    185 
    186     if(!wb->configureDpyInfo(hnd->width, hnd->height)) {
    187         ALOGE("%s: config display failed", __func__);
    188         mDoable = false;
    189         return false;
    190     }
    191 
    192     int tmpW, tmpH;
    193     size_t size;
    194     int format = ovutils::getHALFormat(wb->getOutputFormat());
    195     if(format < 0) {
    196         ALOGE("%s invalid format %d", __func__, format);
    197         mDoable = false;
    198         return false;
    199     }
    200 
    201     size = getBufferSizeAndDimensions(hnd->width, hnd->height,
    202                 format, tmpW, tmpH);
    203 
    204     if(!wb->configureMemory((uint32_t)size)) {
    205         ALOGE("%s: config memory failed", __func__);
    206         mDoable = false;
    207         return false;
    208     }
    209 
    210     eMdpFlags mdpFlags = OV_MDP_FLAGS_NONE;
    211     if(isSecureBuffer(hnd)) {
    212         ovutils::setMdpFlags(mdpFlags,
    213                 ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
    214     }
    215 
    216     PipeArgs parg(mdpFlags, whf, ZORDER_0,
    217             ROT_FLAGS_NONE);
    218     hwc_rect_t dst = crop; //input same as output
    219 
    220     if(configMdp(ctx->mOverlay, parg, OVERLAY_TRANSFORM_0, crop, dst, NULL,
    221                 dest) < 0) {
    222         ALOGE("%s: configMdp failed", __func__);
    223         mDoable = false;
    224         return false;
    225     }
    226 
    227     mDest = dest;
    228     int wbFd = wb->getFbFd();
    229     if(mFeatureEnabled && wbFd >= 0 &&
    230         !ctx->mOverlay->validateAndSet(overlay::Overlay::DPY_WRITEBACK, wbFd))
    231     {
    232         ALOGE("%s: Failed to validate and set overlay for dpy %d"
    233                 ,__FUNCTION__, overlay::Overlay::DPY_WRITEBACK);
    234         turnOffAD();
    235         return false;
    236     }
    237 
    238     // Only turn on AD if there are no errors during configuration stage
    239     // and if it was previously in OFF state.
    240     if(mFeatureEnabled && mTurnedOff) {
    241         //write to sysfs, one time during this switch
    242         const int on = 1;
    243         adWrite(on);
    244         mTurnedOff = false;
    245     }
    246 
    247     return true;
    248 }
    249 
    250 bool AssertiveDisplay::draw(hwc_context_t *ctx, int fd, uint32_t offset) {
    251     if(!isDoable()) {
    252         return false;
    253     }
    254 
    255     if (!ctx->mOverlay->queueBuffer(fd, offset, mDest)) {
    256         ALOGE("%s: queueBuffer failed", __func__);
    257         return false;
    258     }
    259 
    260     overlay::Writeback *wb = overlay::Writeback::getInstance();
    261     if(!wb->writeSync()) {
    262         return false;
    263     }
    264 
    265     return true;
    266 }
    267 
    268 int AssertiveDisplay::getDstFd() const {
    269     overlay::Writeback *wb = overlay::Writeback::getInstance();
    270     return wb->getDstFd();
    271 }
    272 
    273 uint32_t AssertiveDisplay::getDstOffset() const {
    274     overlay::Writeback *wb = overlay::Writeback::getInstance();
    275     return wb->getOffset();
    276 }
    277 
    278 }
    279