Home | History | Annotate | Download | only in anniedale
      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 
     17 #include <math.h>
     18 #include <HwcTrace.h>
     19 #include <Drm.h>
     20 #include <Hwcomposer.h>
     21 #include <anniedale/AnnOverlayPlane.h>
     22 #include <tangier/TngGrallocBuffer.h>
     23 
     24 // FIXME: remove it
     25 #include <OMX_IVCommon.h>
     26 #include <OMX_IntelVideoExt.h>
     27 
     28 namespace android {
     29 namespace intel {
     30 
     31 AnnOverlayPlane::AnnOverlayPlane(int index, int disp)
     32     : OverlayPlaneBase(index, disp),
     33       mRotationBufProvider(NULL),
     34       mRotationConfig(0),
     35       mZOrderConfig(0),
     36       mUseOverlayRotation(true)
     37 {
     38     CTRACE();
     39 
     40     memset(&mContext, 0, sizeof(mContext));
     41 }
     42 
     43 AnnOverlayPlane::~AnnOverlayPlane()
     44 {
     45     CTRACE();
     46 }
     47 
     48 void AnnOverlayPlane::setZOrderConfig(ZOrderConfig& zorderConfig,
     49                                             void *nativeConfig)
     50 {
     51     long slot = (long)nativeConfig;
     52 
     53     CTRACE();
     54 
     55     switch (slot) {
     56     case 0:
     57         mZOrderConfig = 0;
     58         break;
     59     case 1:
     60         mZOrderConfig = (1 << 8);
     61         break;
     62     case 2:
     63         mZOrderConfig = (2 << 8);
     64         break;
     65     case 3:
     66         mZOrderConfig = (3 << 8);
     67         break;
     68     default:
     69         ETRACE("Invalid overlay plane zorder %ld", slot);
     70         return;
     71     }
     72 }
     73 
     74 bool AnnOverlayPlane::reset()
     75 {
     76     OverlayPlaneBase::reset();
     77     if (mRotationBufProvider) {
     78         mRotationBufProvider->reset();
     79     }
     80     return true;
     81 }
     82 
     83 bool AnnOverlayPlane::enable()
     84 {
     85     RETURN_FALSE_IF_NOT_INIT();
     86 
     87     // by default always use overlay rotation
     88     mUseOverlayRotation = true;
     89 
     90     if (mContext.ctx.ov_ctx.ovadd & (0x1 << 15))
     91         return true;
     92 
     93     mContext.ctx.ov_ctx.ovadd |= (0x1 << 15);
     94 
     95     // flush
     96     flush(PLANE_ENABLE);
     97 
     98     return true;
     99 }
    100 
    101 bool AnnOverlayPlane::disable()
    102 {
    103     RETURN_FALSE_IF_NOT_INIT();
    104 
    105     if (!(mContext.ctx.ov_ctx.ovadd & (0x1 << 15)))
    106         return true;
    107 
    108     mContext.ctx.ov_ctx.ovadd &= ~(0x1 << 15);
    109 
    110     mContext.ctx.ov_ctx.ovadd &= ~(0x300);
    111 
    112     mContext.ctx.ov_ctx.ovadd |= mPipeConfig;
    113 
    114     // flush
    115     flush(PLANE_DISABLE);
    116 
    117     return true;
    118 }
    119 
    120 void AnnOverlayPlane::postFlip()
    121 {
    122     // when using AnnOverlayPlane through AnnDisplayPlane as proxy, postFlip is never
    123     // called so mUpdateMasks is never reset.
    124     // When using AnnOverlayPlane directly, postFlip is invoked and mUpdateMasks is reset
    125     // post-flip.
    126 
    127     // need to check why mUpdateMasks = 0 causes video freeze.
    128 
    129     //DisplayPlane::postFlip();
    130 }
    131 
    132 
    133 void AnnOverlayPlane::resetBackBuffer(int buf)
    134 {
    135     CTRACE();
    136 
    137     if (!mBackBuffer[buf] || !mBackBuffer[buf]->buf)
    138         return;
    139 
    140     OverlayBackBufferBlk *backBuffer = mBackBuffer[buf]->buf;
    141 
    142     memset(backBuffer, 0, sizeof(OverlayBackBufferBlk));
    143 
    144     // reset overlay
    145     backBuffer->OCLRC0 = (OVERLAY_INIT_CONTRAST << 18) |
    146                          (OVERLAY_INIT_BRIGHTNESS & 0xff);
    147     backBuffer->OCLRC1 = OVERLAY_INIT_SATURATION;
    148     backBuffer->DCLRKV = OVERLAY_INIT_COLORKEY;
    149     backBuffer->DCLRKM = OVERLAY_INIT_COLORKEYMASK;
    150     backBuffer->OCONFIG = 0;
    151     backBuffer->OCONFIG |= (0x1 << 27);
    152     // use 3 line buffers
    153     backBuffer->OCONFIG |= 0x1;
    154     backBuffer->SCHRKEN &= ~(0x7 << 24);
    155     backBuffer->SCHRKEN |= 0xff;
    156 }
    157 
    158 bool AnnOverlayPlane::bufferOffsetSetup(BufferMapper& mapper)
    159 {
    160     CTRACE();
    161 
    162     OverlayBackBufferBlk *backBuffer = mBackBuffer[mCurrent]->buf;
    163     if (!backBuffer) {
    164         ETRACE("invalid back buffer");
    165         return false;
    166     }
    167 
    168     uint32_t format = mapper.getFormat();
    169     uint32_t gttOffsetInBytes = (mapper.getGttOffsetInPage(0) << 12);
    170     uint32_t yStride = mapper.getStride().yuv.yStride;
    171     uint32_t uvStride = mapper.getStride().yuv.uvStride;
    172     uint32_t w = mapper.getWidth();
    173     uint32_t h = mapper.getHeight();
    174     uint32_t srcX= mapper.getCrop().x;
    175     uint32_t srcY= mapper.getCrop().y;
    176     uint32_t ySurface, uSurface, vSurface;
    177     uint32_t yTileOffsetX, yTileOffsetY;
    178     uint32_t uTileOffsetX, uTileOffsetY;
    179     uint32_t vTileOffsetX, vTileOffsetY;
    180 
    181     // clear original format setting
    182     backBuffer->OCMD &= ~(0xf << 10);
    183     backBuffer->OCMD &= ~OVERLAY_MEMORY_LAYOUT_TILED;
    184 
    185     backBuffer->OBUF_0Y = 0;
    186     backBuffer->OBUF_0V = 0;
    187     backBuffer->OBUF_0U = 0;
    188     // Y/U/V plane must be 4k bytes aligned.
    189     ySurface = gttOffsetInBytes;
    190     if (mIsProtectedBuffer) {
    191         // temporary workaround until vsync event logic is corrected.
    192         // it seems that overlay buffer update and renderring can be overlapped,
    193         // as such encryption bit may be cleared during HW rendering
    194         ySurface |= 0x01;
    195     }
    196 
    197     switch(format) {
    198     case HAL_PIXEL_FORMAT_YV12:    // YV12
    199         vSurface = ySurface + yStride * h;
    200         uSurface = vSurface + uvStride * (h / 2);
    201         yTileOffsetX = srcX;
    202         yTileOffsetY = srcY;
    203         uTileOffsetX = srcX / 2;
    204         uTileOffsetY = srcY / 2;
    205         vTileOffsetX = uTileOffsetX;
    206         vTileOffsetY = uTileOffsetY;
    207         backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_YUV420;
    208         break;
    209     case HAL_PIXEL_FORMAT_I420:    // I420
    210         uSurface = ySurface + yStride * h;
    211         vSurface = uSurface + uvStride * (h / 2);
    212         yTileOffsetX = srcX;
    213         yTileOffsetY = srcY;
    214         uTileOffsetX = srcX / 2;
    215         uTileOffsetY = srcY / 2;
    216         vTileOffsetX = uTileOffsetX;
    217         vTileOffsetY = uTileOffsetY;
    218         backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_YUV420;
    219         break;
    220     case HAL_PIXEL_FORMAT_NV12:    // NV12
    221         uSurface = ySurface;
    222         vSurface = ySurface;
    223         backBuffer->OBUF_0U = yStride * h;
    224         yTileOffsetX = srcX;
    225         yTileOffsetY = srcY;
    226         uTileOffsetX = srcX / 2;
    227         uTileOffsetY = srcY / 2 + h;
    228         vTileOffsetX = uTileOffsetX;
    229         vTileOffsetY = uTileOffsetY;
    230         backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_NV12_2;
    231         break;
    232     // NOTE: this is the decoded video format, align the height to 32B
    233     //as it's defined by video driver
    234     case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar:    // NV12
    235         uSurface = ySurface + yStride * align_to(h, 32);
    236         vSurface = ySurface + yStride * align_to(h, 32);
    237         yTileOffsetX = srcX;
    238         yTileOffsetY = srcY;
    239         uTileOffsetX = srcX;
    240         uTileOffsetY = srcY / 2;
    241         vTileOffsetX = uTileOffsetX;
    242         vTileOffsetY = uTileOffsetY;
    243         backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_NV12_2;
    244         break;
    245     case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled:  //NV12_tiled
    246         uSurface = ySurface + yStride * align_to(h, 32);
    247         vSurface = ySurface + yStride * align_to(h, 32);
    248         yTileOffsetX = srcX;
    249         yTileOffsetY = srcY;
    250         uTileOffsetX = srcX;
    251         uTileOffsetY = srcY / 2;
    252         vTileOffsetX = uTileOffsetX;
    253         vTileOffsetY = uTileOffsetY;
    254         backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_NV12_2;
    255         backBuffer->OCMD |= OVERLAY_MEMORY_LAYOUT_TILED;
    256         break;
    257     case HAL_PIXEL_FORMAT_YUY2:    // YUY2
    258         uSurface = ySurface;
    259         vSurface = ySurface;
    260         yTileOffsetX = srcX;
    261         yTileOffsetY = srcY;
    262         uTileOffsetX = yTileOffsetX;
    263         uTileOffsetY = yTileOffsetY;
    264         vTileOffsetX = yTileOffsetX;
    265         vTileOffsetY = yTileOffsetY;
    266         backBuffer->OCMD |= OVERLAY_FORMAT_PACKED_YUV422;
    267         backBuffer->OCMD |= OVERLAY_PACKED_ORDER_YUY2;
    268         break;
    269     case HAL_PIXEL_FORMAT_UYVY:    // UYVY
    270         uSurface = ySurface;
    271         vSurface = ySurface;
    272         yTileOffsetX = srcX;
    273         yTileOffsetY = srcY;
    274         uTileOffsetX = yTileOffsetX;
    275         uTileOffsetY = yTileOffsetY;
    276         vTileOffsetX = yTileOffsetX;
    277         vTileOffsetY = yTileOffsetY;
    278         backBuffer->OCMD |= OVERLAY_FORMAT_PACKED_YUV422;
    279         backBuffer->OCMD |= OVERLAY_PACKED_ORDER_UYVY;
    280         break;
    281     default:
    282         ETRACE("unsupported format %d", format);
    283         return false;
    284     }
    285 
    286     backBuffer->OSTART_0Y = ySurface;
    287     backBuffer->OSTART_0U = uSurface;
    288     backBuffer->OSTART_0V = vSurface;
    289     backBuffer->OBUF_0Y += srcY * yStride + srcX;
    290     backBuffer->OBUF_0V += (srcY / 2) * uvStride + srcX;
    291     backBuffer->OBUF_0U += (srcY / 2) * uvStride + srcX;
    292     backBuffer->OTILEOFF_0Y = yTileOffsetY << 16 | yTileOffsetX;
    293     backBuffer->OTILEOFF_0U = uTileOffsetY << 16 | uTileOffsetX;
    294     backBuffer->OTILEOFF_0V = vTileOffsetY << 16 | vTileOffsetX;
    295 
    296     VTRACE("done. offset (%d, %d, %d)",
    297           backBuffer->OBUF_0Y,
    298           backBuffer->OBUF_0U,
    299           backBuffer->OBUF_0V);
    300 
    301     return true;
    302 }
    303 
    304 bool AnnOverlayPlane::scalingSetup(BufferMapper& mapper)
    305 {
    306     int xscaleInt, xscaleFract, yscaleInt, yscaleFract;
    307     int xscaleIntUV, xscaleFractUV;
    308     int yscaleIntUV, yscaleFractUV;
    309     // UV is half the size of Y -- YUV420
    310     int uvratio = 2;
    311     uint32_t newval;
    312     coeffRec xcoeffY[N_HORIZ_Y_TAPS * N_PHASES];
    313     coeffRec xcoeffUV[N_HORIZ_UV_TAPS * N_PHASES];
    314     coeffRec ycoeffY[N_VERT_Y_TAPS * N_PHASES];
    315     coeffRec ycoeffUV[N_VERT_UV_TAPS * N_PHASES];
    316     int i, j, pos;
    317     bool scaleChanged = false;
    318     int x, y, w, h;
    319     int deinterlace_factor = 1;
    320     drmModeModeInfoPtr mode = &mModeInfo;
    321 
    322     OverlayBackBufferBlk *backBuffer = mBackBuffer[mCurrent]->buf;
    323     if (!backBuffer) {
    324         ETRACE("invalid back buffer");
    325         return false;
    326     }
    327 
    328     if (mPanelOrientation == PANEL_ORIENTATION_180) {
    329         if (mode->hdisplay)
    330             x = mode->hdisplay - mPosition.x - mPosition.w;
    331         else
    332             x = mPosition.x;
    333         if (mode->vdisplay)
    334             y = mode->vdisplay - mPosition.y - mPosition.h;
    335         else
    336             y = mPosition.y;
    337     } else {
    338         x = mPosition.x;
    339         y = mPosition.y;
    340     }
    341 
    342     w = mPosition.w;
    343     h = mPosition.h;
    344 
    345     // check position
    346     checkPosition(x, y, w, h);
    347     VTRACE("final position (%d, %d, %d, %d)", x, y, w, h);
    348 
    349     if ((w <= 0) || (h <= 0)) {
    350          ETRACE("invalid dst width/height");
    351          return false;
    352     }
    353 
    354     // setup dst position
    355     backBuffer->DWINPOS = (y << 16) | x;
    356     backBuffer->DWINSZ = (h << 16) | w;
    357 
    358     uint32_t srcWidth = mapper.getCrop().w;
    359     uint32_t srcHeight = mapper.getCrop().h;
    360     uint32_t dstWidth = w;
    361     uint32_t dstHeight = h;
    362 
    363     if (mBobDeinterlace && !mTransform)
    364         deinterlace_factor = 2;
    365 
    366     VTRACE("src (%dx%d), dst (%dx%d), transform %d",
    367           srcWidth, srcHeight,
    368           dstWidth, dstHeight,
    369           mTransform);
    370 
    371     // switch destination width/height for scale factor calculation
    372     // for 90/270 transformation
    373     if (mUseOverlayRotation && ((mTransform == HWC_TRANSFORM_ROT_90) ||
    374         (mTransform == HWC_TRANSFORM_ROT_270))) {
    375         uint32_t tmp = srcHeight;
    376         srcHeight = srcWidth;
    377         srcWidth = tmp;
    378     }
    379 
    380      // Y down-scale factor as a multiple of 4096
    381     if (srcWidth == dstWidth && srcHeight == dstHeight) {
    382         xscaleFract = (1 << 12);
    383         yscaleFract = (1 << 12) / deinterlace_factor;
    384     } else {
    385         xscaleFract = ((srcWidth - 1) << 12) / dstWidth;
    386         yscaleFract = ((srcHeight - 1) << 12) / (dstHeight * deinterlace_factor);
    387     }
    388 
    389     // Calculate the UV scaling factor
    390     xscaleFractUV = xscaleFract / uvratio;
    391     yscaleFractUV = yscaleFract / uvratio;
    392 
    393 
    394     // To keep the relative Y and UV ratios exact, round the Y scales
    395     // to a multiple of the Y/UV ratio.
    396     xscaleFract = xscaleFractUV * uvratio;
    397     yscaleFract = yscaleFractUV * uvratio;
    398 
    399     // Integer (un-multiplied) values
    400     xscaleInt = xscaleFract >> 12;
    401     yscaleInt = yscaleFract >> 12;
    402 
    403     xscaleIntUV = xscaleFractUV >> 12;
    404     yscaleIntUV = yscaleFractUV >> 12;
    405 
    406     // Check scaling ratio
    407     if (xscaleInt > INTEL_OVERLAY_MAX_SCALING_RATIO) {
    408         ETRACE("xscaleInt > %d", INTEL_OVERLAY_MAX_SCALING_RATIO);
    409         return false;
    410     }
    411 
    412     // shouldn't get here
    413     if (xscaleIntUV > INTEL_OVERLAY_MAX_SCALING_RATIO) {
    414         ETRACE("xscaleIntUV > %d", INTEL_OVERLAY_MAX_SCALING_RATIO);
    415         return false;
    416     }
    417 
    418     newval = (xscaleInt << 15) |
    419     ((xscaleFract & 0xFFF) << 3) | ((yscaleFract & 0xFFF) << 20);
    420     if (newval != backBuffer->YRGBSCALE) {
    421         scaleChanged = true;
    422         backBuffer->YRGBSCALE = newval;
    423     }
    424 
    425     newval = (xscaleIntUV << 15) | ((xscaleFractUV & 0xFFF) << 3) |
    426     ((yscaleFractUV & 0xFFF) << 20);
    427     if (newval != backBuffer->UVSCALE) {
    428         scaleChanged = true;
    429         backBuffer->UVSCALE = newval;
    430     }
    431 
    432     newval = yscaleInt << 16 | yscaleIntUV;
    433     if (newval != backBuffer->UVSCALEV) {
    434         scaleChanged = true;
    435         backBuffer->UVSCALEV = newval;
    436     }
    437 
    438     // Recalculate coefficients if the scaling changed
    439     // Only Horizontal coefficients so far.
    440     if (scaleChanged) {
    441         double fHCutoffY;
    442         double fHCutoffUV;
    443         double fVCutoffY;
    444         double fVCutoffUV;
    445 
    446         fHCutoffY = xscaleFract / 4096.0;
    447         fHCutoffUV = xscaleFractUV / 4096.0;
    448         fVCutoffY = yscaleFract / 4096.0;
    449         fVCutoffUV = yscaleFractUV / 4096.0;
    450 
    451         // Limit to between 1.0 and 3.0
    452         if (fHCutoffY < MIN_CUTOFF_FREQ)
    453             fHCutoffY = MIN_CUTOFF_FREQ;
    454         if (fHCutoffY > MAX_CUTOFF_FREQ)
    455             fHCutoffY = MAX_CUTOFF_FREQ;
    456         if (fHCutoffUV < MIN_CUTOFF_FREQ)
    457             fHCutoffUV = MIN_CUTOFF_FREQ;
    458         if (fHCutoffUV > MAX_CUTOFF_FREQ)
    459             fHCutoffUV = MAX_CUTOFF_FREQ;
    460 
    461         if (fVCutoffY < MIN_CUTOFF_FREQ)
    462             fVCutoffY = MIN_CUTOFF_FREQ;
    463         if (fVCutoffY > MAX_CUTOFF_FREQ)
    464             fVCutoffY = MAX_CUTOFF_FREQ;
    465         if (fVCutoffUV < MIN_CUTOFF_FREQ)
    466             fVCutoffUV = MIN_CUTOFF_FREQ;
    467         if (fVCutoffUV > MAX_CUTOFF_FREQ)
    468             fVCutoffUV = MAX_CUTOFF_FREQ;
    469 
    470         updateCoeff(N_HORIZ_Y_TAPS, fHCutoffY, true, true, xcoeffY);
    471         updateCoeff(N_HORIZ_UV_TAPS, fHCutoffUV, true, false, xcoeffUV);
    472         updateCoeff(N_VERT_Y_TAPS, fVCutoffY, false, true, ycoeffY);
    473         updateCoeff(N_VERT_UV_TAPS, fVCutoffUV, false, false, ycoeffUV);
    474 
    475         for (i = 0; i < N_PHASES; i++) {
    476             for (j = 0; j < N_HORIZ_Y_TAPS; j++) {
    477                 pos = i * N_HORIZ_Y_TAPS + j;
    478                 backBuffer->Y_HCOEFS[pos] =
    479                         (xcoeffY[pos].sign << 15 |
    480                          xcoeffY[pos].exponent << 12 |
    481                          xcoeffY[pos].mantissa);
    482             }
    483         }
    484         for (i = 0; i < N_PHASES; i++) {
    485             for (j = 0; j < N_HORIZ_UV_TAPS; j++) {
    486                 pos = i * N_HORIZ_UV_TAPS + j;
    487                 backBuffer->UV_HCOEFS[pos] =
    488                          (xcoeffUV[pos].sign << 15 |
    489                           xcoeffUV[pos].exponent << 12 |
    490                           xcoeffUV[pos].mantissa);
    491             }
    492         }
    493 
    494         for (i = 0; i < N_PHASES; i++) {
    495             for (j = 0; j < N_VERT_Y_TAPS; j++) {
    496                 pos = i * N_VERT_Y_TAPS + j;
    497                 backBuffer->Y_VCOEFS[pos] =
    498                         (ycoeffY[pos].sign << 15 |
    499                          ycoeffY[pos].exponent << 12 |
    500                          ycoeffY[pos].mantissa);
    501             }
    502         }
    503         for (i = 0; i < N_PHASES; i++) {
    504             for (j = 0; j < N_VERT_UV_TAPS; j++) {
    505                 pos = i * N_VERT_UV_TAPS + j;
    506                 backBuffer->UV_VCOEFS[pos] =
    507                          (ycoeffUV[pos].sign << 15 |
    508                           ycoeffUV[pos].exponent << 12 |
    509                           ycoeffUV[pos].mantissa);
    510             }
    511         }
    512     }
    513 
    514     XTRACE();
    515     return true;
    516 }
    517 
    518 void AnnOverlayPlane::setTransform(int transform)
    519 {
    520     RETURN_VOID_IF_NOT_INIT();
    521 
    522     if (mPanelOrientation == PANEL_ORIENTATION_180)
    523        transform ^=  HWC_TRANSFORM_ROT_180;
    524 
    525     DisplayPlane::setTransform(transform);
    526 
    527     // setup transform config
    528     switch (mTransform) {
    529     case HWC_TRANSFORM_ROT_90:
    530         mRotationConfig = (0x1 << 10);
    531         break;
    532     case HWC_TRANSFORM_ROT_180:
    533         mRotationConfig = (0x2 << 10);
    534         break;
    535     case HWC_TRANSFORM_ROT_270:
    536         mRotationConfig = (0x3 << 10);
    537         break;
    538     case 0:
    539         mRotationConfig = 0;
    540         break;
    541     default:
    542         ETRACE("Invalid transform %d", mTransform);
    543         mRotationConfig = 0;
    544         break;
    545     }
    546 }
    547 
    548 // HSD 4645510:
    549 // This is a SOC limition, that when source buffer width range is
    550 // in (960, 1024] - one cache line length, and rotation bit is set
    551 // in portrait mode, video will show distortion.
    552 bool AnnOverlayPlane::isSettingRotBitAllowed()
    553 {
    554     uint32_t width = mSrcCrop.w;
    555 
    556     if ((width > 960 && width <= 1024) &&
    557             (mTransform == 0 || mTransform == HAL_TRANSFORM_ROT_180))
    558         return false;
    559     return true;
    560 }
    561 
    562 bool AnnOverlayPlane::flip(void *ctx)
    563 {
    564     uint32_t ovadd = 0;
    565 
    566     RETURN_FALSE_IF_NOT_INIT();
    567 
    568     if (!DisplayPlane::flip(ctx)) {
    569         ETRACE("failed to flip display plane.");
    570         return false;
    571     }
    572 
    573     // update back buffer address
    574     ovadd = (mBackBuffer[mCurrent]->gttOffsetInPage << 12);
    575 
    576     // enable rotation mode and setup rotation config
    577     // if video is interlaced, cannot use overlay rotation
    578     if (mIndex == 0 && !mBobDeinterlace) {
    579         if (isSettingRotBitAllowed())
    580             ovadd |= (1 << 12);
    581         ovadd |= mRotationConfig;
    582     }
    583 
    584     // setup z-order config
    585     ovadd |= mZOrderConfig;
    586 
    587     // load coefficients
    588     ovadd |= 0x1;
    589 
    590     // enable overlay
    591     ovadd |= (1 << 15);
    592 
    593     mContext.type = DC_OVERLAY_PLANE;
    594     mContext.ctx.ov_ctx.ovadd = ovadd;
    595     mContext.ctx.ov_ctx.index = mIndex;
    596     mContext.ctx.ov_ctx.pipe = mDevice;
    597     mContext.ctx.ov_ctx.ovadd |= mPipeConfig;
    598 
    599     // move to next back buffer
    600     mCurrent = (mCurrent + 1) % OVERLAY_BACK_BUFFER_COUNT;
    601 
    602     VTRACE("ovadd = %#x, index = %d, device = %d",
    603           mContext.ctx.ov_ctx.ovadd,
    604           mIndex,
    605           mDevice);
    606 
    607     return true;
    608 }
    609 
    610 void* AnnOverlayPlane::getContext() const
    611 {
    612     CTRACE();
    613     return (void *)&mContext;
    614 }
    615 
    616 bool AnnOverlayPlane::setDataBuffer(BufferMapper& mapper)
    617 {
    618     if (OverlayPlaneBase::setDataBuffer(mapper) == false) {
    619         return false;
    620     }
    621 
    622     signalVideoRotation(mapper);
    623 
    624     if (mIsProtectedBuffer) {
    625         // Bit 0: Decryption request, only allowed to change on a synchronous flip
    626         // This request will be qualified with the separate decryption enable bit for OV
    627         mBackBuffer[mCurrent]->buf->OSTART_0Y |= 0x1;
    628         mBackBuffer[mCurrent]->buf->OSTART_1Y |= 0x1;
    629     }
    630 
    631     mContext.gtt_key = (unsigned long)mapper.getCpuAddress(0);
    632 
    633     return true;
    634 }
    635 
    636 bool AnnOverlayPlane::initialize(uint32_t bufferCount)
    637 {
    638     if (!OverlayPlaneBase::initialize(bufferCount)) {
    639         ETRACE("failed to initialize OverlayPlaneBase");
    640         return false;
    641     }
    642 
    643     // setup rotation buffer
    644     mRotationBufProvider = new RotationBufferProvider(mWsbm);
    645     if (!mRotationBufProvider || !mRotationBufProvider->initialize()) {
    646         DEINIT_AND_RETURN_FALSE("failed to initialize RotationBufferProvider");
    647     }
    648     return true;
    649 }
    650 
    651 void AnnOverlayPlane::deinitialize()
    652 {
    653     DEINIT_AND_DELETE_OBJ(mRotationBufProvider);
    654     OverlayPlaneBase::deinitialize();
    655 }
    656 
    657 bool AnnOverlayPlane::rotatedBufferReady(BufferMapper& mapper, BufferMapper* &rotatedMapper)
    658 {
    659     struct VideoPayloadBuffer *payload;
    660     uint32_t format;
    661     // only NV12_VED has rotated buffer
    662     format = mapper.getFormat();
    663     if (format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar &&
    664         format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled) {
    665         ETRACE("invalid video format %#x", format);
    666         return false;
    667     }
    668 
    669     payload = (struct VideoPayloadBuffer *)mapper.getCpuAddress(SUB_BUFFER1);
    670     // check payload
    671     if (!payload) {
    672         ETRACE("no payload found");
    673         return false;
    674     }
    675 
    676     if (payload->force_output_method == FORCE_OUTPUT_GPU) {
    677         ETRACE("Output method is not supported!");
    678         return false;
    679     }
    680 
    681     if (payload->client_transform != mTransform ||
    682         mBobDeinterlace) {
    683         if (!mRotationBufProvider->setupRotationBuffer(payload, mTransform)) {
    684             DTRACE("failed to setup rotation buffer");
    685             return false;
    686         }
    687     }
    688 
    689     rotatedMapper = getTTMMapper(mapper, payload);
    690     return true;
    691 }
    692 
    693 void AnnOverlayPlane::signalVideoRotation(BufferMapper& mapper)
    694 {
    695     struct VideoPayloadBuffer *payload;
    696     uint32_t format;
    697 
    698     // check if it's video layer
    699     format = mapper.getFormat();
    700     if (format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar &&
    701         format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled) {
    702         return;
    703     }
    704 
    705     payload = (struct VideoPayloadBuffer *)mapper.getCpuAddress(SUB_BUFFER1);
    706     if (!payload) {
    707         ETRACE("no payload found");
    708         return;
    709     }
    710 
    711     /* if use overlay rotation, signal decoder to stop rotation */
    712     if (mUseOverlayRotation) {
    713         if (payload->client_transform) {
    714             WTRACE("signal decoder to stop generate rotation buffer");
    715             payload->hwc_timestamp = systemTime();
    716             payload->layer_transform = 0;
    717         }
    718     } else {
    719         /* if overlay rotation cannot be used, signal decoder to start rotation */
    720         if (payload->client_transform != mTransform) {
    721             WTRACE("signal decoder to generate rotation buffer with transform %d", mTransform);
    722             payload->hwc_timestamp = systemTime();
    723             payload->layer_transform = mTransform;
    724         }
    725     }
    726 }
    727 
    728 bool AnnOverlayPlane::useOverlayRotation(BufferMapper& mapper)
    729 {
    730     if (mTransform == 0)
    731         return true;
    732 
    733     if (!isSettingRotBitAllowed()) {
    734         mUseOverlayRotation = false;
    735         mRotationConfig = 0;
    736         return false;
    737     }
    738 
    739     // workaround limitation of overlay rotation by falling back to use VA rotated buffer
    740     bool fallback = false;
    741     float scaleX = (float)mSrcCrop.w / mPosition.w;
    742     float scaleY = (float)mSrcCrop.h / mPosition.h;
    743     if (mTransform == HAL_TRANSFORM_ROT_270 || mTransform == HAL_TRANSFORM_ROT_90) {
    744         scaleX = (float)mSrcCrop.w / mPosition.h;
    745         scaleY = (float)mSrcCrop.h / mPosition.w;
    746     }
    747     if (scaleX >= 3 || scaleY >= 3) {
    748         if (mUseOverlayRotation) {
    749             DTRACE("overlay rotation with scaling >= 3, use VA rotated buffer");
    750         }
    751         fallback = true;
    752     } else if ((int)mSrcCrop.x & 63) {
    753         if (mUseOverlayRotation) {
    754             DTRACE("offset is not 64 bytes aligned, use VA rotated buffer");
    755         }
    756         fallback = true;
    757     }
    758 #if 0
    759     else if (mTransform != HAL_TRANSFORM_ROT_180 && scaleX != scaleY) {
    760         if (mUseOverlayRotation) {
    761             DTRACE("overlay rotation with uneven scaling, use VA rotated buffer");
    762         }
    763         fallback = true;
    764     }
    765 #endif
    766 
    767     // per DC spec, if video is 1080(H)x1920(V), the buffer
    768     // need 1920 of 64-pixel strip if using hw rotation.
    769     // fallback to video ration buffer in such case.
    770     if (mSrcCrop.w == 1080 && mSrcCrop.h == 1920 && mTransform != 0) {
    771         DTRACE("1080(H)x1920(V) cannot use hw rotation, use VA rotated buffer");
    772         fallback = true;
    773     }
    774 
    775     if (fallback || mBobDeinterlace) {
    776         mUseOverlayRotation = false;
    777         mRotationConfig = 0;
    778     } else {
    779         mUseOverlayRotation = true;
    780     }
    781     return mUseOverlayRotation;
    782 }
    783 
    784 bool AnnOverlayPlane::scaledBufferReady(BufferMapper& mapper, BufferMapper* &scaledMapper, VideoPayloadBuffer *payload)
    785 {
    786     mUseScaledBuffer = (payload->scaling_khandle != 0);
    787 
    788     if (mUseScaledBuffer) {
    789         mapper.setCrop(mapper.getCrop().x, mapper.getCrop().y, payload->scaling_width, payload->scaling_height);
    790         scaledMapper = getTTMMapper(mapper, payload);
    791         return (scaledMapper != 0);
    792     }
    793 
    794     return mUseScaledBuffer;
    795 }
    796 
    797 bool AnnOverlayPlane::flush(uint32_t flags)
    798 {
    799     RETURN_FALSE_IF_NOT_INIT();
    800     ATRACE("flags = %#x, type = %d, index = %d", flags, mType, mIndex);
    801 
    802     if (!(flags & PLANE_ENABLE) && !(flags & PLANE_DISABLE)) {
    803         ETRACE("invalid flush flags.");
    804         return false;
    805     }
    806 
    807     struct drm_psb_register_rw_arg arg;
    808     memset(&arg, 0, sizeof(struct drm_psb_register_rw_arg));
    809 
    810     if (flags & PLANE_DISABLE)
    811         arg.plane_disable_mask = 1;
    812     else if (flags & PLANE_ENABLE)
    813         arg.plane_enable_mask = 1;
    814 
    815     arg.plane.type = DC_OVERLAY_PLANE;
    816     arg.plane.index = mIndex;
    817     arg.plane.ctx = mContext.ctx.ov_ctx.ovadd;
    818     if (flags & PLANE_DISABLE) {
    819         DTRACE("disabling overlay %d on device %d", mIndex, mDevice);
    820     }
    821 
    822     // issue ioctl
    823     Drm *drm = Hwcomposer::getInstance().getDrm();
    824     bool ret = drm->writeReadIoctl(DRM_PSB_REGISTER_RW, &arg, sizeof(arg));
    825     if (ret == false) {
    826         WTRACE("overlay update failed with error code %d", ret);
    827         return false;
    828     }
    829 
    830     return true;
    831 }
    832 
    833 } // namespace intel
    834 } // namespace android
    835