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