1/* 2// Copyright (c) 2014 Intel Corporation 3// 4// Licensed under the Apache License, Version 2.0 (the "License"); 5// you may not use this file except in compliance with the License. 6// You may obtain a copy of the License at 7// 8// http://www.apache.org/licenses/LICENSE-2.0 9// 10// Unless required by applicable law or agreed to in writing, software 11// distributed under the License is distributed on an "AS IS" BASIS, 12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13// See the License for the specific language governing permissions and 14// limitations under the License. 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 28namespace android { 29namespace intel { 30 31AnnOverlayPlane::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 43AnnOverlayPlane::~AnnOverlayPlane() 44{ 45 CTRACE(); 46} 47 48void 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 74bool AnnOverlayPlane::reset() 75{ 76 OverlayPlaneBase::reset(); 77 if (mRotationBufProvider) { 78 mRotationBufProvider->reset(); 79 } 80 return true; 81} 82 83bool 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 101bool 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 120void 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 133void 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 158bool 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 304bool 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 518void 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. 552bool 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 562bool 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 610void* AnnOverlayPlane::getContext() const 611{ 612 CTRACE(); 613 return (void *)&mContext; 614} 615 616bool 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 636bool 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 651void AnnOverlayPlane::deinitialize() 652{ 653 DEINIT_AND_DELETE_OBJ(mRotationBufProvider); 654 OverlayPlaneBase::deinitialize(); 655} 656 657bool 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 693void 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 728bool 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 784bool 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 797bool 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