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