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