Home | History | Annotate | Download | only in tangier
      1 /*
      2 // Copyright(c)2014 IntelCorporation
      3 //
      4 // LicensedundertheApacheLicense,Version2.0(the"License");
      5 // youmaynotusethisfileexceptincompliancewiththeLicense.
      6 // YoumayobtainacopyoftheLicenseat
      7 //
      8 // http://www.apache.org/licenses/LICENSE-2.0
      9 //
     10 // Unlessrequiredbyapplicablelaworagreedtoinwriting,software
     11 // distributedundertheLicenseisdistributedonan"ASIS"BASIS,
     12 // WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.
     13 // SeetheLicenseforthespecificlanguagegoverningpermissionsand
     14 // limitationsundertheLicense.
     15 */
     16 #include <math.h>
     17 #include <HwcTrace.h>
     18 #include <Drm.h>
     19 #include <Hwcomposer.h>
     20 #include <tangier/TngOverlayPlane.h>
     21 #include <tangier/TngGrallocBuffer.h>
     22 
     23 namespace android {
     24 namespace intel {
     25 
     26 TngOverlayPlane::TngOverlayPlane(int index, int disp)
     27     : OverlayPlaneBase(index, disp),
     28       mRotationBufProvider(NULL)
     29 {
     30     CTRACE();
     31 
     32     memset(&mContext, 0, sizeof(mContext));
     33 }
     34 
     35 TngOverlayPlane::~TngOverlayPlane()
     36 {
     37     CTRACE();
     38 }
     39 
     40 bool TngOverlayPlane::flip(void *ctx)
     41 {
     42     RETURN_FALSE_IF_NOT_INIT();
     43 
     44     if (!DisplayPlane::flip(ctx))
     45         return false;
     46 
     47     mContext.type = DC_OVERLAY_PLANE;
     48     mContext.ctx.ov_ctx.ovadd = 0x0;
     49     mContext.ctx.ov_ctx.ovadd = (mBackBuffer[mCurrent]->gttOffsetInPage << 12);
     50     mContext.ctx.ov_ctx.index = mIndex;
     51     mContext.ctx.ov_ctx.pipe = mDevice;
     52     mContext.ctx.ov_ctx.ovadd |= mPipeConfig;
     53     mContext.ctx.ov_ctx.ovadd |= 0x1;
     54 
     55     // move to next back buffer
     56     //mCurrent = (mCurrent + 1) % OVERLAY_BACK_BUFFER_COUNT;
     57 
     58     VTRACE("ovadd = %#x, index = %d, device = %d",
     59           mContext.ctx.ov_ctx.ovadd,
     60           mIndex,
     61           mDevice);
     62 
     63     return true;
     64 }
     65 
     66 bool TngOverlayPlane::reset()
     67 {
     68     OverlayPlaneBase::reset();
     69     if (mRotationBufProvider)
     70         mRotationBufProvider->reset();
     71     return true;
     72 }
     73 
     74 void* TngOverlayPlane::getContext() const
     75 {
     76     CTRACE();
     77     return (void *)&mContext;
     78 }
     79 
     80 bool TngOverlayPlane::setDataBuffer(BufferMapper& mapper)
     81 {
     82     if (OverlayPlaneBase::setDataBuffer(mapper) == false) {
     83         return false;
     84     }
     85 
     86     if (mIsProtectedBuffer) {
     87         // Bit 0: Decryption request, only allowed to change on a synchronous flip
     88         // This request will be qualified with the separate decryption enable bit for OV
     89         mBackBuffer[mCurrent]->buf->OSTART_0Y |= 0x1;
     90         mBackBuffer[mCurrent]->buf->OSTART_1Y |= 0x1;
     91     }
     92 
     93     mContext.gtt_key = (uint64_t)mapper.getCpuAddress(0);
     94     return true;
     95 }
     96 
     97 bool TngOverlayPlane::initialize(uint32_t bufferCount)
     98 {
     99     if (!OverlayPlaneBase::initialize(bufferCount)) {
    100         ETRACE("failed to initialize OverlayPlaneBase");
    101         return false;
    102     }
    103 
    104     // setup rotation buffer
    105     mRotationBufProvider = new RotationBufferProvider(mWsbm);
    106     if (!mRotationBufProvider || !mRotationBufProvider->initialize()) {
    107         DEINIT_AND_RETURN_FALSE("failed to initialize RotationBufferProvider");
    108     }
    109     return true;
    110 }
    111 
    112 void TngOverlayPlane::deinitialize()
    113 {
    114     DEINIT_AND_DELETE_OBJ(mRotationBufProvider);
    115     OverlayPlaneBase::deinitialize();
    116 }
    117 
    118 bool TngOverlayPlane::rotatedBufferReady(BufferMapper& mapper, BufferMapper* &rotatedMapper)
    119 {
    120     struct VideoPayloadBuffer *payload;
    121     VideoPayloadBuffer buffer_info;
    122     uint32_t format;
    123     // only NV12_VED has rotated buffer
    124     format = mapper.getFormat();
    125 
    126     if (format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar &&
    127         format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled &&
    128         format != HAL_PIXEL_FORMAT_NV12) {
    129         ETRACE("Invalid video format %#x", format);
    130         return false;
    131     }
    132 
    133     payload = (struct VideoPayloadBuffer *)mapper.getCpuAddress(SUB_BUFFER1);
    134 
    135     if (payload == NULL && format == HAL_PIXEL_FORMAT_NV12) {
    136          // need to populate buffer_info
    137         void *p = mapper.getCpuAddress(SUB_BUFFER0);
    138         if (!p) {
    139             ETRACE("failed to get buffer user pointer");
    140             return false;
    141         }
    142 
    143         bool ret = mRotationBufProvider->prepareBufferInfo(mapper.getWidth(),
    144                                                 mapper.getHeight(),
    145                                                 mapper.getStride().yuv.yStride,
    146                                                 &buffer_info, p);
    147         if (ret == false) {
    148             ETRACE("failed to prepare buffer info");
    149             return false;
    150         }
    151         payload = &buffer_info;
    152     }
    153 
    154     // check payload
    155     if (!payload) {
    156         ETRACE("no payload found");
    157         return false;
    158     }
    159 
    160     if (payload->force_output_method == FORCE_OUTPUT_GPU) {
    161         ETRACE("Output method is not supported!");
    162         return false;
    163     }
    164 
    165     if (payload->client_transform != mTransform ||
    166         mBobDeinterlace) {
    167         payload->hwc_timestamp = systemTime();
    168         payload->layer_transform = mTransform;
    169         if (!mRotationBufProvider->setupRotationBuffer(payload, mTransform)) {
    170             ETRACE("failed to setup rotation buffer");
    171             return false;
    172         }
    173     }
    174 
    175     rotatedMapper = getTTMMapper(mapper, payload);
    176 
    177     return true;
    178 }
    179 
    180 bool TngOverlayPlane::flush(uint32_t flags)
    181 {
    182     RETURN_FALSE_IF_NOT_INIT();
    183     ATRACE("flags = %#x, type = %d, index = %d", flags, mType, mIndex);
    184 
    185     if (!(flags & PLANE_ENABLE) && !(flags & PLANE_DISABLE))
    186         return false;
    187 
    188     struct drm_psb_register_rw_arg arg;
    189     memset(&arg, 0, sizeof(struct drm_psb_register_rw_arg));
    190 
    191     if (flags & PLANE_DISABLE)
    192         arg.plane_disable_mask = 1;
    193     else if (flags & PLANE_ENABLE)
    194         arg.plane_enable_mask = 1;
    195 
    196     arg.plane.type = DC_OVERLAY_PLANE;
    197     arg.plane.index = mIndex;
    198     arg.plane.ctx = (mBackBuffer[mCurrent]->gttOffsetInPage << 12);
    199     // pipe select
    200     arg.plane.ctx |= mPipeConfig;
    201 
    202     if (flags & PLANE_DISABLE) {
    203         DTRACE("disabling overlay %d on device %d", mIndex, mDevice);
    204     }
    205 
    206     // issue ioctl
    207     Drm *drm = Hwcomposer::getInstance().getDrm();
    208     bool ret = drm->writeReadIoctl(DRM_PSB_REGISTER_RW, &arg, sizeof(arg));
    209     if (ret == false) {
    210         WTRACE("overlay update failed with error code %d", ret);
    211         return false;
    212     }
    213 
    214     return true;
    215 }
    216 
    217 } // namespace intel
    218 } // namespace android
    219