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 <PhysicalDevice.h> 22 #include <ips/common/OverlayPlaneBase.h> 23 #include <ips/common/TTMBufferMapper.h> 24 #include <ips/common/GrallocSubBuffer.h> 25 #include <DisplayQuery.h> 26 #include <khronos/openmax/OMX_IntelVideoExt.h> 27 #include <hal_public.h> 28 29 namespace android { 30 namespace intel { 31 32 OverlayPlaneBase::OverlayPlaneBase(int index, int disp) 33 : DisplayPlane(index, PLANE_OVERLAY, disp), 34 mTTMBuffers(), 35 mActiveTTMBuffers(), 36 mCurrent(0), 37 mWsbm(0), 38 mPipeConfig(0), 39 mBobDeinterlace(0) 40 { 41 CTRACE(); 42 for (int i = 0; i < OVERLAY_BACK_BUFFER_COUNT; i++) { 43 mBackBuffer[i] = 0; 44 } 45 } 46 47 OverlayPlaneBase::~OverlayPlaneBase() 48 { 49 CTRACE(); 50 } 51 52 bool OverlayPlaneBase::initialize(uint32_t bufferCount) 53 { 54 Drm *drm = Hwcomposer::getInstance().getDrm(); 55 CTRACE(); 56 57 // NOTE: use overlay's data buffer count for the overlay plane 58 if (bufferCount < OVERLAY_DATA_BUFFER_COUNT) { 59 ILOGTRACE("override overlay buffer count from %d to %d", 60 bufferCount, OVERLAY_DATA_BUFFER_COUNT); 61 bufferCount = OVERLAY_DATA_BUFFER_COUNT; 62 } 63 if (!DisplayPlane::initialize(bufferCount)) { 64 DEINIT_AND_RETURN_FALSE("failed to initialize display plane"); 65 } 66 67 mTTMBuffers.setCapacity(bufferCount); 68 mActiveTTMBuffers.setCapacity(MIN_DATA_BUFFER_COUNT); 69 70 // init wsbm 71 mWsbm = new Wsbm(drm->getDrmFd()); 72 if (!mWsbm || !mWsbm->initialize()) { 73 DEINIT_AND_RETURN_FALSE("failed to create wsbm"); 74 } 75 76 // create overlay back buffer 77 for (int i = 0; i < OVERLAY_BACK_BUFFER_COUNT; i++) { 78 mBackBuffer[i] = createBackBuffer(); 79 if (!mBackBuffer[i]) { 80 DEINIT_AND_RETURN_FALSE("failed to create overlay back buffer"); 81 } 82 // reset back buffer 83 resetBackBuffer(i); 84 } 85 86 // disable overlay when created 87 flush(PLANE_DISABLE); 88 89 return true; 90 } 91 92 bool OverlayPlaneBase::isDisabled() 93 { 94 RETURN_FALSE_IF_NOT_INIT(); 95 96 struct drm_psb_register_rw_arg arg; 97 memset(&arg, 0, sizeof(struct drm_psb_register_rw_arg)); 98 99 arg.get_plane_state_mask = 1; 100 arg.plane.type = DC_OVERLAY_PLANE; 101 arg.plane.index = mIndex; 102 // pass the pipe index to check its enabled status 103 // now we can pass the device id directly since 104 // their values are just equal 105 arg.plane.ctx = mDevice; // not used in kernel 106 107 Drm *drm = Hwcomposer::getInstance().getDrm(); 108 bool ret = drm->writeReadIoctl(DRM_PSB_REGISTER_RW, &arg, sizeof(arg)); 109 if (ret == false) { 110 WLOGTRACE("overlay plane query failed with error code %d", ret); 111 return false; 112 } 113 114 DLOGTRACE("overlay %d status %s on device %d, current device %d", 115 mIndex, arg.plane.ctx ? "DISABLED" : "ENABLED", mDevice, mDevice); 116 117 return arg.plane.ctx == PSB_DC_PLANE_DISABLED; 118 } 119 120 void OverlayPlaneBase::deinitialize() 121 { 122 if (mTTMBuffers.size()) { 123 invalidateBufferCache(); 124 } 125 126 if (mActiveTTMBuffers.size() > 0) { 127 invalidateActiveTTMBuffers(); 128 } 129 130 // delete back buffer 131 for (int i = 0; i < OVERLAY_BACK_BUFFER_COUNT; i++) { 132 if (mBackBuffer[i]) { 133 deleteBackBuffer(i); 134 mBackBuffer[i] = NULL; 135 } 136 } 137 DEINIT_AND_DELETE_OBJ(mWsbm); 138 139 DisplayPlane::deinitialize(); 140 } 141 142 void OverlayPlaneBase::invalidateBufferCache() 143 { 144 // clear plane buffer cache 145 DisplayPlane::invalidateBufferCache(); 146 invalidateTTMBuffers(); 147 } 148 149 bool OverlayPlaneBase::assignToDevice(int disp) 150 { 151 uint32_t pipeConfig = 0; 152 153 RETURN_FALSE_IF_NOT_INIT(); 154 VLOGTRACE("overlay %d assigned to disp %d", mIndex, disp); 155 156 switch (disp) { 157 case IDisplayDevice::DEVICE_EXTERNAL: 158 pipeConfig = (0x2 << 6); 159 break; 160 case IDisplayDevice::DEVICE_PRIMARY: 161 default: 162 pipeConfig = 0; 163 break; 164 } 165 166 // if pipe switching happened, then disable overlay first 167 if (mPipeConfig != pipeConfig) { 168 DLOGTRACE("overlay %d switched from %d to %d", mIndex, mDevice, disp); 169 disable(); 170 } 171 172 mPipeConfig = pipeConfig; 173 DisplayPlane::assignToDevice(disp); 174 175 enable(); 176 177 return true; 178 } 179 180 void OverlayPlaneBase::setZOrderConfig(ZOrderConfig& zorderConfig, 181 void * /*nativeConfig*/) 182 { 183 CTRACE(); 184 185 // setup overlay z order 186 int ovaZOrder = -1; 187 int ovcZOrder = -1; 188 for (size_t i = 0; i < zorderConfig.size(); i++) { 189 DisplayPlane *plane = zorderConfig[i]->plane; 190 if (plane->getType() == DisplayPlane::PLANE_OVERLAY) { 191 if (plane->getIndex() == 0) { 192 ovaZOrder = i; 193 } else if (plane->getIndex() == 1) { 194 ovcZOrder = i; 195 } 196 } 197 } 198 199 for (int i = 0; i < OVERLAY_BACK_BUFFER_COUNT; i++) { 200 OverlayBackBufferBlk *backBuffer = mBackBuffer[i]->buf; 201 if (!backBuffer) 202 return; 203 204 // force overlay c above overlay a 205 if ((ovaZOrder >= 0) && (ovaZOrder < ovcZOrder)) { 206 backBuffer->OCONFIG |= (1 << 15); 207 } else { 208 backBuffer->OCONFIG &= ~(1 << 15); 209 } 210 } 211 } 212 213 bool OverlayPlaneBase::reset() 214 { 215 RETURN_FALSE_IF_NOT_INIT(); 216 217 DisplayPlane::reset(); 218 219 // invalidate active TTM buffers 220 if (mActiveTTMBuffers.size() > 0) { 221 invalidateActiveTTMBuffers(); 222 } 223 224 // reset back buffers 225 for (int i = 0; i < OVERLAY_BACK_BUFFER_COUNT; i++) { 226 resetBackBuffer(i); 227 } 228 return true; 229 } 230 231 bool OverlayPlaneBase::enable() 232 { 233 RETURN_FALSE_IF_NOT_INIT(); 234 for (int i = 0; i < OVERLAY_BACK_BUFFER_COUNT; i++) { 235 OverlayBackBufferBlk *backBuffer = mBackBuffer[i]->buf; 236 if (!backBuffer) 237 return false; 238 239 if (backBuffer->OCMD & 0x1) 240 return true; 241 242 backBuffer->OCMD |= 0x1; 243 } 244 245 // flush 246 flush(PLANE_ENABLE); 247 return true; 248 } 249 250 bool OverlayPlaneBase::disable() 251 { 252 RETURN_FALSE_IF_NOT_INIT(); 253 for (int i = 0; i < OVERLAY_BACK_BUFFER_COUNT; i++) { 254 OverlayBackBufferBlk *backBuffer = mBackBuffer[i]->buf; 255 if (!backBuffer) 256 return false; 257 258 if (!(backBuffer->OCMD & 0x1)) 259 return true; 260 261 backBuffer->OCMD &= ~0x1; 262 } 263 264 // flush 265 flush(PLANE_DISABLE); 266 return true; 267 } 268 269 OverlayBackBuffer* OverlayPlaneBase::createBackBuffer() 270 { 271 CTRACE(); 272 273 // create back buffer 274 OverlayBackBuffer *backBuffer = (OverlayBackBuffer *)malloc(sizeof(OverlayBackBuffer)); 275 if (!backBuffer) { 276 ELOGTRACE("failed to allocate back buffer"); 277 return 0; 278 } 279 280 281 int size = sizeof(OverlayBackBufferBlk); 282 int alignment = 64 * 1024; 283 void *wsbmBufferObject = 0; 284 bool ret = mWsbm->allocateTTMBuffer(size, alignment, &wsbmBufferObject); 285 if (ret == false) { 286 ELOGTRACE("failed to allocate TTM buffer"); 287 return 0; 288 } 289 290 void *virtAddr = mWsbm->getCPUAddress(wsbmBufferObject); 291 uint32_t gttOffsetInPage = mWsbm->getGttOffset(wsbmBufferObject); 292 293 backBuffer->buf = (OverlayBackBufferBlk *)virtAddr; 294 backBuffer->gttOffsetInPage = gttOffsetInPage; 295 backBuffer->bufObject = (uint32_t)wsbmBufferObject; 296 297 VLOGTRACE("cpu %p, gtt %d", virtAddr, gttOffsetInPage); 298 299 return backBuffer; 300 } 301 302 void OverlayPlaneBase::deleteBackBuffer(int buf) 303 { 304 if (!mBackBuffer[buf]) 305 return; 306 307 void *wsbmBufferObject = (void *)mBackBuffer[buf]->bufObject; 308 bool ret = mWsbm->destroyTTMBuffer(wsbmBufferObject); 309 if (ret == false) { 310 WLOGTRACE("failed to destroy TTM buffer"); 311 } 312 // free back buffer 313 free(mBackBuffer[buf]); 314 mBackBuffer[buf] = 0; 315 } 316 317 void OverlayPlaneBase::resetBackBuffer(int buf) 318 { 319 CTRACE(); 320 321 if (!mBackBuffer[buf] || !mBackBuffer[buf]->buf) 322 return; 323 324 OverlayBackBufferBlk *backBuffer = mBackBuffer[buf]->buf; 325 326 memset(backBuffer, 0, sizeof(OverlayBackBufferBlk)); 327 328 // reset overlay 329 backBuffer->OCLRC0 = (OVERLAY_INIT_CONTRAST << 18) | 330 (OVERLAY_INIT_BRIGHTNESS & 0xff); 331 backBuffer->OCLRC1 = OVERLAY_INIT_SATURATION; 332 backBuffer->DCLRKV = OVERLAY_INIT_COLORKEY; 333 backBuffer->DCLRKM = OVERLAY_INIT_COLORKEYMASK; 334 backBuffer->OCONFIG = 0; 335 backBuffer->OCONFIG |= (0x1 << 3); 336 backBuffer->OCONFIG |= (0x1 << 27); 337 backBuffer->SCHRKEN &= ~(0x7 << 24); 338 backBuffer->SCHRKEN |= 0xff; 339 } 340 341 BufferMapper* OverlayPlaneBase::getTTMMapper(BufferMapper& grallocMapper, struct VideoPayloadBuffer *payload) 342 { 343 uint32_t khandle; 344 uint32_t w, h; 345 uint32_t yStride, uvStride; 346 stride_t stride; 347 int srcX, srcY, srcW, srcH; 348 349 ssize_t index; 350 TTMBufferMapper *mapper; 351 bool ret; 352 353 if (!payload) { 354 ELOGTRACE("invalid payload buffer"); 355 return 0; 356 } 357 358 srcX = grallocMapper.getCrop().x; 359 srcY = grallocMapper.getCrop().y; 360 srcW = grallocMapper.getCrop().w; 361 srcH = grallocMapper.getCrop().h; 362 363 // init ttm buffer 364 khandle = payload->rotated_buffer_handle; 365 index = mTTMBuffers.indexOfKey(khandle); 366 if (index < 0) { 367 VLOGTRACE("unmapped TTM buffer, will map it"); 368 369 w = payload->rotated_width; 370 h = payload->rotated_height; 371 checkCrop(srcX, srcY, srcW, srcH, payload->coded_width, payload->coded_height); 372 373 uint32_t format = grallocMapper.getFormat(); 374 // this is for sw decode with tiled buffer in landscape mode 375 if (payload->tiling) 376 format = OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled; 377 378 // calculate stride 379 switch (format) { 380 case HAL_PIXEL_FORMAT_YV12: 381 case HAL_PIXEL_FORMAT_I420: 382 uint32_t yStride_align; 383 yStride_align = DisplayQuery::getOverlayLumaStrideAlignment(grallocMapper.getFormat()); 384 if (yStride_align > 0) 385 { 386 yStride = align_to(align_to(w, 32), yStride_align); 387 } 388 else 389 { 390 yStride = align_to(align_to(w, 32), 64); 391 } 392 uvStride = align_to(yStride >> 1, 64); 393 stride.yuv.yStride = yStride; 394 stride.yuv.uvStride = uvStride; 395 break; 396 case HAL_PIXEL_FORMAT_NV12: 397 yStride = align_to(align_to(w, 32), 64); 398 uvStride = yStride; 399 stride.yuv.yStride = yStride; 400 stride.yuv.uvStride = uvStride; 401 break; 402 case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar: 403 case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled: 404 yStride = align_to(align_to(w, 32), 64); 405 uvStride = yStride; 406 stride.yuv.yStride = yStride; 407 stride.yuv.uvStride = uvStride; 408 break; 409 case HAL_PIXEL_FORMAT_YUY2: 410 case HAL_PIXEL_FORMAT_UYVY: 411 yStride = align_to((align_to(w, 32) << 1), 64); 412 uvStride = 0; 413 stride.yuv.yStride = yStride; 414 stride.yuv.uvStride = uvStride; 415 break; 416 } 417 418 DataBuffer buf(khandle); 419 // update buffer 420 buf.setStride(stride); 421 buf.setWidth(w); 422 buf.setHeight(h); 423 buf.setCrop(srcX, srcY, srcW, srcH); 424 buf.setFormat(format); 425 426 // create buffer mapper 427 bool res = false; 428 do { 429 mapper = new TTMBufferMapper(*mWsbm, buf); 430 if (!mapper) { 431 ELOGTRACE("failed to allocate mapper"); 432 break; 433 } 434 // map ttm buffer 435 ret = mapper->map(); 436 if (!ret) { 437 ELOGTRACE("failed to map"); 438 invalidateTTMBuffers(); 439 ret = mapper->map(); 440 if (!ret) { 441 ELOGTRACE("failed to remap"); 442 break; 443 } 444 } 445 446 if (mTTMBuffers.size() >= OVERLAY_DATA_BUFFER_COUNT) { 447 invalidateTTMBuffers(); 448 } 449 450 // add mapper 451 index = mTTMBuffers.add(khandle, mapper); 452 if (index < 0) { 453 ELOGTRACE("failed to add TTMMapper"); 454 break; 455 } 456 457 // increase mapper refCount since it is added to mTTMBuffers 458 mapper->incRef(); 459 res = true; 460 } while (0); 461 462 if (!res) { 463 // error handling 464 if (mapper) { 465 mapper->unmap(); 466 delete mapper; 467 mapper = NULL; 468 } 469 return 0; 470 } 471 } else { 472 VLOGTRACE("got mapper in saved ttm buffers"); 473 mapper = reinterpret_cast<TTMBufferMapper *>(mTTMBuffers.valueAt(index)); 474 if (mapper->getCrop().x != srcX || mapper->getCrop().y != srcY || 475 mapper->getCrop().w != srcW || mapper->getCrop().h != srcH) { 476 checkCrop(srcX, srcY, srcW, srcH, payload->coded_width, payload->coded_height); 477 mapper->setCrop(srcX, srcY, srcW, srcH); 478 } 479 } 480 481 XLOGTRACE(); 482 return mapper; 483 } 484 485 void OverlayPlaneBase::putTTMMapper(BufferMapper* mapper) 486 { 487 if (!mapper) 488 return; 489 490 if (!mapper->decRef()) { 491 // unmap it 492 mapper->unmap(); 493 494 // destroy this mapper 495 delete mapper; 496 } 497 } 498 499 bool OverlayPlaneBase::isActiveTTMBuffer(BufferMapper *mapper) 500 { 501 for (size_t i = 0; i < mActiveTTMBuffers.size(); i++) { 502 BufferMapper *activeMapper = mActiveTTMBuffers.itemAt(i); 503 if (!activeMapper) 504 continue; 505 if (activeMapper->getKey() == mapper->getKey()) 506 return true; 507 } 508 509 return false; 510 } 511 512 void OverlayPlaneBase::updateActiveTTMBuffers(BufferMapper *mapper) 513 { 514 // unmap the first entry (oldest buffer) 515 if (mActiveTTMBuffers.size() >= MAX_ACTIVE_TTM_BUFFERS) { 516 BufferMapper *oldest = mActiveTTMBuffers.itemAt(0); 517 putTTMMapper(oldest); 518 mActiveTTMBuffers.removeAt(0); 519 } 520 521 // queue it to cached buffers 522 if (!isActiveTTMBuffer(mapper)) { 523 mapper->incRef(); 524 mActiveTTMBuffers.push_back(mapper); 525 } 526 } 527 528 void OverlayPlaneBase::invalidateActiveTTMBuffers() 529 { 530 BufferMapper* mapper; 531 532 RETURN_VOID_IF_NOT_INIT(); 533 534 for (size_t i = 0; i < mActiveTTMBuffers.size(); i++) { 535 mapper = mActiveTTMBuffers.itemAt(i); 536 // unmap it 537 putTTMMapper(mapper); 538 } 539 540 // clear recorded data buffers 541 mActiveTTMBuffers.clear(); 542 } 543 544 void OverlayPlaneBase::invalidateTTMBuffers() 545 { 546 BufferMapper* mapper; 547 for (size_t i = 0; i < mTTMBuffers.size(); i++) { 548 mapper = mTTMBuffers.valueAt(i); 549 // putTTMMapper removes mapper from cache 550 putTTMMapper(mapper); 551 } 552 mTTMBuffers.clear(); 553 } 554 555 556 bool OverlayPlaneBase::rotatedBufferReady(BufferMapper& mapper, BufferMapper* &rotatedMapper) 557 { 558 struct VideoPayloadBuffer *payload; 559 uint32_t format; 560 561 // only NV12_VED has rotated buffer 562 format = mapper.getFormat(); 563 if (format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar && 564 format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled) 565 return false; 566 567 payload = (struct VideoPayloadBuffer *)mapper.getCpuAddress(SUB_BUFFER1); 568 // check payload 569 if (!payload) { 570 ELOGTRACE("no payload found"); 571 return false; 572 } 573 574 if (payload->force_output_method == FORCE_OUTPUT_GPU) 575 return false; 576 577 if (payload->client_transform != mTransform) { 578 if (payload->surface_protected) { 579 payload->hwc_timestamp = systemTime(); 580 payload->layer_transform = mTransform; 581 } 582 WLOGTRACE("client is not ready"); 583 return false; 584 } 585 586 rotatedMapper = getTTMMapper(mapper, payload); 587 return true; 588 } 589 590 591 bool OverlayPlaneBase::useOverlayRotation(BufferMapper& /* mapper */) 592 { 593 // by default overlay plane does not support rotation. 594 return false; 595 } 596 597 void OverlayPlaneBase::checkPosition(int& x, int& y, int& w, int& h) 598 { 599 drmModeModeInfoPtr mode = &mModeInfo; 600 601 if (mode->hdisplay == 0 || mode->vdisplay == 0) 602 return; 603 604 if (x < 0) 605 x = 0; 606 if (y < 0) 607 y = 0; 608 if ((x + w) > mode->hdisplay) 609 w = mode->hdisplay - x; 610 if ((y + h) > mode->vdisplay) 611 h = mode->vdisplay - y; 612 } 613 614 void OverlayPlaneBase::checkCrop(int& srcX, int& srcY, int& srcW, int& srcH, 615 int coded_width, int coded_height) 616 { 617 int tmp; 618 619 if (mTransform) 620 srcH >>= mBobDeinterlace; 621 622 if (mTransform == HWC_TRANSFORM_ROT_90 || mTransform == HWC_TRANSFORM_ROT_270) { 623 tmp = srcH; 624 srcH = srcW; 625 srcW = tmp; 626 627 tmp = srcX; 628 srcX = srcY; 629 srcY = tmp; 630 631 tmp = coded_width; 632 coded_width = coded_height; 633 coded_height = tmp; 634 } 635 636 // skip pading bytes in rotate buffer 637 switch(mTransform) { 638 case HWC_TRANSFORM_ROT_90: 639 srcX = (coded_width >> mBobDeinterlace) - srcW - srcX; 640 break; 641 case HWC_TRANSFORM_ROT_180: 642 srcX = coded_width - srcW - srcX; 643 srcY = (coded_height >> mBobDeinterlace) - srcH - srcY; 644 break; 645 case HWC_TRANSFORM_ROT_270: 646 srcY = coded_height - srcH - srcY; 647 break; 648 default: 649 break; 650 } 651 } 652 653 654 bool OverlayPlaneBase::bufferOffsetSetup(BufferMapper& mapper) 655 { 656 CTRACE(); 657 658 OverlayBackBufferBlk *backBuffer = mBackBuffer[mCurrent]->buf; 659 if (!backBuffer) { 660 ELOGTRACE("invalid back buffer"); 661 return false; 662 } 663 664 uint32_t format = mapper.getFormat(); 665 uint32_t gttOffsetInBytes = (mapper.getGttOffsetInPage(0) << 12); 666 uint32_t yStride = mapper.getStride().yuv.yStride; 667 uint32_t uvStride = mapper.getStride().yuv.uvStride; 668 uint32_t h = mapper.getHeight(); 669 uint32_t srcX= mapper.getCrop().x; 670 uint32_t srcY= mapper.getCrop().y; 671 672 // clear original format setting 673 backBuffer->OCMD &= ~(0xf << 10); 674 backBuffer->OCMD &= ~OVERLAY_MEMORY_LAYOUT_TILED; 675 676 // Y/U/V plane must be 4k bytes aligned. 677 backBuffer->OSTART_0Y = gttOffsetInBytes; 678 if (mIsProtectedBuffer) { 679 // temporary workaround until vsync event logic is corrected. 680 // it seems that overlay buffer update and renderring can be overlapped, 681 // as such encryption bit may be cleared during HW rendering 682 backBuffer->OSTART_0Y |= 0x01; 683 } 684 685 backBuffer->OSTART_0U = gttOffsetInBytes; 686 backBuffer->OSTART_0V = gttOffsetInBytes; 687 688 backBuffer->OSTART_1Y = backBuffer->OSTART_0Y; 689 backBuffer->OSTART_1U = backBuffer->OSTART_0U; 690 backBuffer->OSTART_1V = backBuffer->OSTART_0V; 691 692 switch(format) { 693 case HAL_PIXEL_FORMAT_YV12: // YV12 694 backBuffer->OBUF_0Y = 0; 695 backBuffer->OBUF_0V = yStride * h; 696 backBuffer->OBUF_0U = backBuffer->OBUF_0V + (uvStride * (h / 2)); 697 backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_YUV420; 698 break; 699 case HAL_PIXEL_FORMAT_I420: // I420 700 backBuffer->OBUF_0Y = 0; 701 backBuffer->OBUF_0U = yStride * h; 702 backBuffer->OBUF_0V = backBuffer->OBUF_0U + (uvStride * (h / 2)); 703 backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_YUV420; 704 break; 705 case HAL_PIXEL_FORMAT_NV12: // NV12 706 backBuffer->OBUF_0Y = 0; 707 backBuffer->OBUF_0U = yStride * h; 708 backBuffer->OBUF_0V = 0; 709 backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_NV12_2; 710 break; 711 // NOTE: this is the decoded video format, align the height to 32B 712 //as it's defined by video driver 713 case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar: // Intel codec NV12 714 backBuffer->OBUF_0Y = 0; 715 backBuffer->OBUF_0U = yStride * align_to(h, 32); 716 backBuffer->OBUF_0V = 0; 717 backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_NV12_2; 718 break; 719 case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled: //NV12_tiled 720 backBuffer->OBUF_0Y = 0; 721 backBuffer->OBUF_0U = yStride * align_to(h, 32); 722 backBuffer->OBUF_0V = 0; 723 backBuffer->OSTART_0U += yStride * align_to(h, 32); 724 backBuffer->OSTART_0V += yStride * align_to(h, 32); 725 backBuffer->OSTART_1U = backBuffer->OSTART_0U; 726 backBuffer->OSTART_1V = backBuffer->OSTART_0V; 727 backBuffer->OTILEOFF_0Y = srcX + (srcY << 16); 728 backBuffer->OTILEOFF_1Y = backBuffer->OTILEOFF_0Y; 729 backBuffer->OTILEOFF_0U = srcX + ((srcY / 2) << 16); 730 backBuffer->OTILEOFF_1U = backBuffer->OTILEOFF_0U; 731 backBuffer->OTILEOFF_0V = backBuffer->OTILEOFF_0U; 732 backBuffer->OTILEOFF_1V = backBuffer->OTILEOFF_0U; 733 backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_NV12_2; 734 backBuffer->OCMD |= OVERLAY_MEMORY_LAYOUT_TILED; 735 break; 736 case HAL_PIXEL_FORMAT_YUY2: // YUY2 737 backBuffer->OBUF_0Y = 0; 738 backBuffer->OBUF_0U = 0; 739 backBuffer->OBUF_0V = 0; 740 backBuffer->OCMD |= OVERLAY_FORMAT_PACKED_YUV422; 741 backBuffer->OCMD |= OVERLAY_PACKED_ORDER_YUY2; 742 break; 743 case HAL_PIXEL_FORMAT_UYVY: // UYVY 744 backBuffer->OBUF_0Y = 0; 745 backBuffer->OBUF_0U = 0; 746 backBuffer->OBUF_0V = 0; 747 backBuffer->OCMD |= OVERLAY_FORMAT_PACKED_YUV422; 748 backBuffer->OCMD |= OVERLAY_PACKED_ORDER_UYVY; 749 break; 750 default: 751 ELOGTRACE("unsupported format %d", format); 752 return false; 753 } 754 755 backBuffer->OBUF_0Y += srcY * yStride + srcX; 756 backBuffer->OBUF_0V += (srcY / 2) * uvStride + srcX; 757 backBuffer->OBUF_0U += (srcY / 2) * uvStride + srcX; 758 backBuffer->OBUF_1Y = backBuffer->OBUF_0Y; 759 backBuffer->OBUF_1U = backBuffer->OBUF_0U; 760 backBuffer->OBUF_1V = backBuffer->OBUF_0V; 761 762 VLOGTRACE("done. offset (%d, %d, %d)", 763 backBuffer->OBUF_0Y, 764 backBuffer->OBUF_0U, 765 backBuffer->OBUF_0V); 766 return true; 767 } 768 769 uint32_t OverlayPlaneBase::calculateSWidthSW(uint32_t offset, uint32_t width) 770 { 771 ALOGTRACE("offset = %d, width = %d", offset, width); 772 773 uint32_t swidth = ((offset + width + 0x3F) >> 6) - (offset >> 6); 774 775 swidth <<= 1; 776 swidth -= 1; 777 778 return swidth; 779 } 780 781 bool OverlayPlaneBase::coordinateSetup(BufferMapper& mapper) 782 { 783 CTRACE(); 784 785 OverlayBackBufferBlk *backBuffer = mBackBuffer[mCurrent]->buf; 786 if (!backBuffer) { 787 ELOGTRACE("invalid back buffer"); 788 return false; 789 } 790 791 uint32_t swidthy = 0; 792 uint32_t swidthuv = 0; 793 uint32_t format = mapper.getFormat(); 794 uint32_t width = mapper.getCrop().w; 795 uint32_t height = mapper.getCrop().h; 796 uint32_t yStride = mapper.getStride().yuv.yStride; 797 uint32_t uvStride = mapper.getStride().yuv.uvStride; 798 uint32_t offsety = backBuffer->OBUF_0Y; 799 uint32_t offsetu = backBuffer->OBUF_0U; 800 801 switch (format) { 802 case HAL_PIXEL_FORMAT_YV12: // YV12 803 case HAL_PIXEL_FORMAT_I420: // I420 804 case HAL_PIXEL_FORMAT_NV12: // NV12 805 case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar: // NV12 806 case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled: // NV12_tiled 807 break; 808 case HAL_PIXEL_FORMAT_YUY2: // YUY2 809 case HAL_PIXEL_FORMAT_UYVY: // UYVY 810 width <<= 1; 811 break; 812 default: 813 ELOGTRACE("unsupported format %d", format); 814 return false; 815 } 816 817 if (width <= 0 || height <= 0) { 818 ELOGTRACE("invalid src dim"); 819 return false; 820 } 821 822 if (yStride <=0 && uvStride <= 0) { 823 ELOGTRACE("invalid source stride"); 824 return false; 825 } 826 827 backBuffer->SWIDTH = width | ((width / 2) << 16); 828 swidthy = calculateSWidthSW(offsety, width); 829 swidthuv = calculateSWidthSW(offsetu, width / 2); 830 backBuffer->SWIDTHSW = (swidthy << 2) | (swidthuv << 18); 831 backBuffer->SHEIGHT = height | ((height / 2) << 16); 832 backBuffer->OSTRIDE = (yStride & (~0x3f)) | ((uvStride & (~0x3f)) << 16); 833 834 XLOGTRACE(); 835 836 return true; 837 } 838 839 bool OverlayPlaneBase::setCoeffRegs(double *coeff, int mantSize, 840 coeffPtr pCoeff, int pos) 841 { 842 int maxVal, icoeff, res; 843 int sign; 844 double c; 845 846 sign = 0; 847 maxVal = 1 << mantSize; 848 c = *coeff; 849 if (c < 0.0) { 850 sign = 1; 851 c = -c; 852 } 853 854 res = 12 - mantSize; 855 if ((icoeff = (int)(c * 4 * maxVal + 0.5)) < maxVal) { 856 pCoeff[pos].exponent = 3; 857 pCoeff[pos].mantissa = icoeff << res; 858 *coeff = (double)icoeff / (double)(4 * maxVal); 859 } else if ((icoeff = (int)(c * 2 * maxVal + 0.5)) < maxVal) { 860 pCoeff[pos].exponent = 2; 861 pCoeff[pos].mantissa = icoeff << res; 862 *coeff = (double)icoeff / (double)(2 * maxVal); 863 } else if ((icoeff = (int)(c * maxVal + 0.5)) < maxVal) { 864 pCoeff[pos].exponent = 1; 865 pCoeff[pos].mantissa = icoeff << res; 866 *coeff = (double)icoeff / (double)(maxVal); 867 } else if ((icoeff = (int)(c * maxVal * 0.5 + 0.5)) < maxVal) { 868 pCoeff[pos].exponent = 0; 869 pCoeff[pos].mantissa = icoeff << res; 870 *coeff = (double)icoeff / (double)(maxVal / 2); 871 } else { 872 // Coeff out of range 873 return false; 874 } 875 876 pCoeff[pos].sign = sign; 877 if (sign) 878 *coeff = -(*coeff); 879 return true; 880 } 881 882 void OverlayPlaneBase::updateCoeff(int taps, double fCutoff, 883 bool isHoriz, bool isY, 884 coeffPtr pCoeff) 885 { 886 int i, j, j1, num, pos, mantSize; 887 double pi = 3.1415926535, val, sinc, window, sum; 888 double rawCoeff[MAX_TAPS * 32], coeffs[N_PHASES][MAX_TAPS]; 889 double diff; 890 int tapAdjust[MAX_TAPS], tap2Fix; 891 bool isVertAndUV; 892 893 if (isHoriz) 894 mantSize = 7; 895 else 896 mantSize = 6; 897 898 isVertAndUV = !isHoriz && !isY; 899 num = taps * 16; 900 for (i = 0; i < num * 2; i++) { 901 val = (1.0 / fCutoff) * taps * pi * (i - num) / (2 * num); 902 if (val == 0.0) 903 sinc = 1.0; 904 else 905 sinc = sin(val) / val; 906 907 // Hamming window 908 window = (0.54 - 0.46 * cos(2 * i * pi / (2 * num - 1))); 909 rawCoeff[i] = sinc * window; 910 } 911 912 for (i = 0; i < N_PHASES; i++) { 913 // Normalise the coefficients 914 sum = 0.0; 915 for (j = 0; j < taps; j++) { 916 pos = i + j * 32; 917 sum += rawCoeff[pos]; 918 } 919 for (j = 0; j < taps; j++) { 920 pos = i + j * 32; 921 coeffs[i][j] = rawCoeff[pos] / sum; 922 } 923 924 // Set the register values 925 for (j = 0; j < taps; j++) { 926 pos = j + i * taps; 927 if ((j == (taps - 1) / 2) && !isVertAndUV) 928 setCoeffRegs(&coeffs[i][j], mantSize + 2, pCoeff, pos); 929 else 930 setCoeffRegs(&coeffs[i][j], mantSize, pCoeff, pos); 931 } 932 933 tapAdjust[0] = (taps - 1) / 2; 934 for (j = 1, j1 = 1; j <= tapAdjust[0]; j++, j1++) { 935 tapAdjust[j1] = tapAdjust[0] - j; 936 tapAdjust[++j1] = tapAdjust[0] + j; 937 } 938 939 // Adjust the coefficients 940 sum = 0.0; 941 for (j = 0; j < taps; j++) 942 sum += coeffs[i][j]; 943 if (sum != 1.0) { 944 for (j1 = 0; j1 < taps; j1++) { 945 tap2Fix = tapAdjust[j1]; 946 diff = 1.0 - sum; 947 coeffs[i][tap2Fix] += diff; 948 pos = tap2Fix + i * taps; 949 if ((tap2Fix == (taps - 1) / 2) && !isVertAndUV) 950 setCoeffRegs(&coeffs[i][tap2Fix], mantSize + 2, pCoeff, pos); 951 else 952 setCoeffRegs(&coeffs[i][tap2Fix], mantSize, pCoeff, pos); 953 954 sum = 0.0; 955 for (j = 0; j < taps; j++) 956 sum += coeffs[i][j]; 957 if (sum == 1.0) 958 break; 959 } 960 } 961 } 962 } 963 964 bool OverlayPlaneBase::scalingSetup(BufferMapper& mapper) 965 { 966 int xscaleInt, xscaleFract, yscaleInt, yscaleFract; 967 int xscaleIntUV, xscaleFractUV; 968 int yscaleIntUV, yscaleFractUV; 969 int deinterlace_factor = 1; 970 // UV is half the size of Y -- YUV420 971 int uvratio = 2; 972 uint32_t newval; 973 coeffRec xcoeffY[N_HORIZ_Y_TAPS * N_PHASES]; 974 coeffRec xcoeffUV[N_HORIZ_UV_TAPS * N_PHASES]; 975 int i, j, pos; 976 bool scaleChanged = false; 977 int x, y, w, h; 978 979 OverlayBackBufferBlk *backBuffer = mBackBuffer[mCurrent]->buf; 980 if (!backBuffer) { 981 ELOGTRACE("invalid back buffer"); 982 return false; 983 } 984 985 x = mPosition.x; 986 y = mPosition.y; 987 w = mPosition.w; 988 h = mPosition.h; 989 990 // check position 991 checkPosition(x, y, w, h); 992 VLOGTRACE("final position (%d, %d, %d, %d)", x, y, w, h); 993 994 if ((w <= 0) || (h <= 0)) { 995 ELOGTRACE("invalid dst width/height"); 996 return false; 997 } 998 999 // setup dst position 1000 backBuffer->DWINPOS = (y << 16) | x; 1001 backBuffer->DWINSZ = (h << 16) | w; 1002 1003 uint32_t srcWidth = mapper.getCrop().w; 1004 uint32_t srcHeight = mapper.getCrop().h; 1005 uint32_t dstWidth = w; 1006 uint32_t dstHeight = h; 1007 1008 VLOGTRACE("src (%dx%d), dst (%dx%d)", 1009 srcWidth, srcHeight, 1010 dstWidth, dstHeight); 1011 1012 // Y down-scale factor as a multiple of 4096 1013 if (srcWidth == dstWidth && srcHeight == dstHeight) { 1014 xscaleFract = (1 << 12); 1015 yscaleFract = (1 << 12)/deinterlace_factor; 1016 } else { 1017 xscaleFract = ((srcWidth - 1) << 12) / dstWidth; 1018 yscaleFract = ((srcHeight - 1) << 12) / (dstHeight * deinterlace_factor); 1019 } 1020 1021 // Calculate the UV scaling factor 1022 xscaleFractUV = xscaleFract / uvratio; 1023 yscaleFractUV = yscaleFract / uvratio; 1024 1025 // To keep the relative Y and UV ratios exact, round the Y scales 1026 // to a multiple of the Y/UV ratio. 1027 xscaleFract = xscaleFractUV * uvratio; 1028 yscaleFract = yscaleFractUV * uvratio; 1029 1030 // Integer (un-multiplied) values 1031 xscaleInt = xscaleFract >> 12; 1032 yscaleInt = yscaleFract >> 12; 1033 1034 xscaleIntUV = xscaleFractUV >> 12; 1035 yscaleIntUV = yscaleFractUV >> 12; 1036 1037 // Check scaling ratio 1038 if (xscaleInt > INTEL_OVERLAY_MAX_SCALING_RATIO) { 1039 ELOGTRACE("xscaleInt > %d", INTEL_OVERLAY_MAX_SCALING_RATIO); 1040 return false; 1041 } 1042 1043 // shouldn't get here 1044 if (xscaleIntUV > INTEL_OVERLAY_MAX_SCALING_RATIO) { 1045 ELOGTRACE("xscaleIntUV > %d", INTEL_OVERLAY_MAX_SCALING_RATIO); 1046 return false; 1047 } 1048 1049 newval = (xscaleInt << 15) | 1050 ((xscaleFract & 0xFFF) << 3) | ((yscaleFract & 0xFFF) << 20); 1051 if (newval != backBuffer->YRGBSCALE) { 1052 scaleChanged = true; 1053 backBuffer->YRGBSCALE = newval; 1054 } 1055 1056 newval = (xscaleIntUV << 15) | ((xscaleFractUV & 0xFFF) << 3) | 1057 ((yscaleFractUV & 0xFFF) << 20); 1058 if (newval != backBuffer->UVSCALE) { 1059 scaleChanged = true; 1060 backBuffer->UVSCALE = newval; 1061 } 1062 1063 newval = yscaleInt << 16 | yscaleIntUV; 1064 if (newval != backBuffer->UVSCALEV) { 1065 scaleChanged = true; 1066 backBuffer->UVSCALEV = newval; 1067 } 1068 1069 // Recalculate coefficients if the scaling changed 1070 // Only Horizontal coefficients so far. 1071 if (scaleChanged) { 1072 double fCutoffY; 1073 double fCutoffUV; 1074 1075 fCutoffY = xscaleFract / 4096.0; 1076 fCutoffUV = xscaleFractUV / 4096.0; 1077 1078 // Limit to between 1.0 and 3.0 1079 if (fCutoffY < MIN_CUTOFF_FREQ) 1080 fCutoffY = MIN_CUTOFF_FREQ; 1081 if (fCutoffY > MAX_CUTOFF_FREQ) 1082 fCutoffY = MAX_CUTOFF_FREQ; 1083 if (fCutoffUV < MIN_CUTOFF_FREQ) 1084 fCutoffUV = MIN_CUTOFF_FREQ; 1085 if (fCutoffUV > MAX_CUTOFF_FREQ) 1086 fCutoffUV = MAX_CUTOFF_FREQ; 1087 1088 updateCoeff(N_HORIZ_Y_TAPS, fCutoffY, true, true, xcoeffY); 1089 updateCoeff(N_HORIZ_UV_TAPS, fCutoffUV, true, false, xcoeffUV); 1090 1091 for (i = 0; i < N_PHASES; i++) { 1092 for (j = 0; j < N_HORIZ_Y_TAPS; j++) { 1093 pos = i * N_HORIZ_Y_TAPS + j; 1094 backBuffer->Y_HCOEFS[pos] = 1095 (xcoeffY[pos].sign << 15 | 1096 xcoeffY[pos].exponent << 12 | 1097 xcoeffY[pos].mantissa); 1098 } 1099 } 1100 for (i = 0; i < N_PHASES; i++) { 1101 for (j = 0; j < N_HORIZ_UV_TAPS; j++) { 1102 pos = i * N_HORIZ_UV_TAPS + j; 1103 backBuffer->UV_HCOEFS[pos] = 1104 (xcoeffUV[pos].sign << 15 | 1105 xcoeffUV[pos].exponent << 12 | 1106 xcoeffUV[pos].mantissa); 1107 } 1108 } 1109 } 1110 1111 XLOGTRACE(); 1112 return true; 1113 } 1114 1115 bool OverlayPlaneBase::colorSetup(BufferMapper& mapper) 1116 { 1117 CTRACE(); 1118 1119 OverlayBackBufferBlk *backBuffer = mBackBuffer[mCurrent]->buf; 1120 if (!backBuffer) { 1121 ELOGTRACE("invalid back buffer"); 1122 return false; 1123 } 1124 1125 uint32_t format = mapper.getFormat(); 1126 if (format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar && 1127 format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled) { 1128 1129 VLOGTRACE("Not video layer, use default color setting"); 1130 backBuffer->OCLRC0 = (OVERLAY_INIT_CONTRAST << 18) | 1131 (OVERLAY_INIT_BRIGHTNESS & 0xff); 1132 backBuffer->OCLRC1 = OVERLAY_INIT_SATURATION; 1133 backBuffer->OCONFIG &= ~(1 << 5); 1134 1135 return true; 1136 } 1137 1138 struct VideoPayloadBuffer *payload; 1139 payload = (struct VideoPayloadBuffer *)mapper.getCpuAddress(SUB_BUFFER1); 1140 // check payload 1141 if (!payload) { 1142 ELOGTRACE("no payload found"); 1143 return false; 1144 } 1145 1146 // BT.601 or BT.709 1147 backBuffer->OCONFIG &= ~(1 << 5); 1148 backBuffer->OCONFIG |= (payload->csc_mode << 5); 1149 1150 // no level expansion for video on HDMI 1151 if (payload->video_range || mPipeConfig == (0x2 << 6)) { 1152 // full range, no need to do level expansion 1153 backBuffer->OCLRC0 = 0x1000000; 1154 backBuffer->OCLRC1 = 0x80; 1155 } else { 1156 // level expansion for limited range 1157 backBuffer->OCLRC0 = (OVERLAY_INIT_CONTRAST << 18) | 1158 (OVERLAY_INIT_BRIGHTNESS & 0xff); 1159 backBuffer->OCLRC1 = OVERLAY_INIT_SATURATION; 1160 } 1161 1162 return true; 1163 } 1164 1165 bool OverlayPlaneBase::setDataBuffer(BufferMapper& grallocMapper) 1166 { 1167 BufferMapper *mapper; 1168 BufferMapper *rotatedMapper = 0; 1169 bool ret; 1170 uint32_t format; 1171 1172 RETURN_FALSE_IF_NOT_INIT(); 1173 1174 // get gralloc mapper 1175 mapper = &grallocMapper; 1176 format = grallocMapper.getFormat(); 1177 if (format == OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar || 1178 format == OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled) { 1179 struct VideoPayloadBuffer *payload; 1180 payload = (struct VideoPayloadBuffer *)grallocMapper.getCpuAddress(SUB_BUFFER1); 1181 if (!payload) { 1182 ELOGTRACE("invalid payload buffer"); 1183 return 0; 1184 } 1185 1186 mBobDeinterlace = payload->bob_deinterlace; 1187 } 1188 1189 if (mTransform && !useOverlayRotation(grallocMapper)) { 1190 if (!rotatedBufferReady(grallocMapper, rotatedMapper)) { 1191 DLOGTRACE("rotated buffer is not ready"); 1192 return false; 1193 } 1194 1195 if (!rotatedMapper) { 1196 ELOGTRACE("failed to get rotated buffer"); 1197 return false; 1198 } 1199 mapper = rotatedMapper; 1200 } 1201 1202 OverlayBackBufferBlk *backBuffer = mBackBuffer[mCurrent]->buf; 1203 if (!backBuffer) { 1204 ELOGTRACE("invalid back buffer"); 1205 return false; 1206 } 1207 1208 ret = bufferOffsetSetup(*mapper); 1209 if (ret == false) { 1210 ELOGTRACE("failed to set up buffer offsets"); 1211 return false; 1212 } 1213 1214 ret = coordinateSetup(*mapper); 1215 if (ret == false) { 1216 ELOGTRACE("failed to set up overlay coordinates"); 1217 return false; 1218 } 1219 1220 ret = scalingSetup(*mapper); 1221 if (ret == false) { 1222 ELOGTRACE("failed to set up scaling parameters"); 1223 return false; 1224 } 1225 1226 backBuffer->OCMD |= 0x1; 1227 1228 if (mBobDeinterlace && !mTransform) { 1229 backBuffer->OCMD |= BUF_TYPE_FIELD; 1230 backBuffer->OCMD &= ~FIELD_SELECT; 1231 backBuffer->OCMD |= FIELD0; 1232 backBuffer->OCMD &= ~(BUFFER_SELECT); 1233 backBuffer->OCMD |= BUFFER0; 1234 } else { 1235 backBuffer->OCMD &= ~BUF_TYPE; 1236 backBuffer->OCMD &= ~FIELD_SELECT; 1237 backBuffer->OCMD &= ~(BUFFER_SELECT); 1238 } 1239 1240 ret = colorSetup(*mapper); 1241 if (ret == false) { 1242 ELOGTRACE("failed to set up color parameters"); 1243 return false; 1244 } 1245 1246 // add to active ttm buffers if it's a rotated buffer 1247 if (rotatedMapper) { 1248 updateActiveTTMBuffers(mapper); 1249 } 1250 1251 return true; 1252 } 1253 1254 } // namespace intel 1255 } // namespace android 1256 1257