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_INTEL_YV12: 382 case HAL_PIXEL_FORMAT_I420: 383 uint32_t yStride_align; 384 yStride_align = DisplayQuery::getOverlayLumaStrideAlignment(grallocMapper.getFormat()); 385 if (yStride_align > 0) 386 { 387 yStride = align_to(align_to(w, 32), yStride_align); 388 } 389 else 390 { 391 yStride = align_to(align_to(w, 32), 64); 392 } 393 uvStride = align_to(yStride >> 1, 64); 394 stride.yuv.yStride = yStride; 395 stride.yuv.uvStride = uvStride; 396 break; 397 case HAL_PIXEL_FORMAT_NV12: 398 yStride = align_to(align_to(w, 32), 64); 399 uvStride = yStride; 400 stride.yuv.yStride = yStride; 401 stride.yuv.uvStride = uvStride; 402 break; 403 case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar: 404 case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled: 405 yStride = align_to(align_to(w, 32), 64); 406 uvStride = yStride; 407 stride.yuv.yStride = yStride; 408 stride.yuv.uvStride = uvStride; 409 break; 410 case HAL_PIXEL_FORMAT_YUY2: 411 case HAL_PIXEL_FORMAT_UYVY: 412 yStride = align_to((align_to(w, 32) << 1), 64); 413 uvStride = 0; 414 stride.yuv.yStride = yStride; 415 stride.yuv.uvStride = uvStride; 416 break; 417 } 418 419 DataBuffer buf(khandle); 420 // update buffer 421 buf.setStride(stride); 422 buf.setWidth(w); 423 buf.setHeight(h); 424 buf.setCrop(srcX, srcY, srcW, srcH); 425 buf.setFormat(format); 426 427 // create buffer mapper 428 bool res = false; 429 do { 430 mapper = new TTMBufferMapper(*mWsbm, buf); 431 if (!mapper) { 432 ELOGTRACE("failed to allocate mapper"); 433 break; 434 } 435 // map ttm buffer 436 ret = mapper->map(); 437 if (!ret) { 438 ELOGTRACE("failed to map"); 439 invalidateTTMBuffers(); 440 ret = mapper->map(); 441 if (!ret) { 442 ELOGTRACE("failed to remap"); 443 break; 444 } 445 } 446 447 if (mTTMBuffers.size() >= OVERLAY_DATA_BUFFER_COUNT) { 448 invalidateTTMBuffers(); 449 } 450 451 // add mapper 452 index = mTTMBuffers.add(khandle, mapper); 453 if (index < 0) { 454 ELOGTRACE("failed to add TTMMapper"); 455 break; 456 } 457 458 // increase mapper refCount since it is added to mTTMBuffers 459 mapper->incRef(); 460 res = true; 461 } while (0); 462 463 if (!res) { 464 // error handling 465 if (mapper) { 466 mapper->unmap(); 467 delete mapper; 468 mapper = NULL; 469 } 470 return 0; 471 } 472 } else { 473 VLOGTRACE("got mapper in saved ttm buffers"); 474 mapper = reinterpret_cast<TTMBufferMapper *>(mTTMBuffers.valueAt(index)); 475 if (mapper->getCrop().x != srcX || mapper->getCrop().y != srcY || 476 mapper->getCrop().w != srcW || mapper->getCrop().h != srcH) { 477 checkCrop(srcX, srcY, srcW, srcH, payload->coded_width, payload->coded_height); 478 mapper->setCrop(srcX, srcY, srcW, srcH); 479 } 480 } 481 482 XLOGTRACE(); 483 return mapper; 484 } 485 486 void OverlayPlaneBase::putTTMMapper(BufferMapper* mapper) 487 { 488 if (!mapper) 489 return; 490 491 if (!mapper->decRef()) { 492 // unmap it 493 mapper->unmap(); 494 495 // destroy this mapper 496 delete mapper; 497 } 498 } 499 500 bool OverlayPlaneBase::isActiveTTMBuffer(BufferMapper *mapper) 501 { 502 for (size_t i = 0; i < mActiveTTMBuffers.size(); i++) { 503 BufferMapper *activeMapper = mActiveTTMBuffers.itemAt(i); 504 if (!activeMapper) 505 continue; 506 if (activeMapper->getKey() == mapper->getKey()) 507 return true; 508 } 509 510 return false; 511 } 512 513 void OverlayPlaneBase::updateActiveTTMBuffers(BufferMapper *mapper) 514 { 515 // unmap the first entry (oldest buffer) 516 if (mActiveTTMBuffers.size() >= MAX_ACTIVE_TTM_BUFFERS) { 517 BufferMapper *oldest = mActiveTTMBuffers.itemAt(0); 518 putTTMMapper(oldest); 519 mActiveTTMBuffers.removeAt(0); 520 } 521 522 // queue it to cached buffers 523 if (!isActiveTTMBuffer(mapper)) { 524 mapper->incRef(); 525 mActiveTTMBuffers.push_back(mapper); 526 } 527 } 528 529 void OverlayPlaneBase::invalidateActiveTTMBuffers() 530 { 531 BufferMapper* mapper; 532 533 RETURN_VOID_IF_NOT_INIT(); 534 535 for (size_t i = 0; i < mActiveTTMBuffers.size(); i++) { 536 mapper = mActiveTTMBuffers.itemAt(i); 537 // unmap it 538 putTTMMapper(mapper); 539 } 540 541 // clear recorded data buffers 542 mActiveTTMBuffers.clear(); 543 } 544 545 void OverlayPlaneBase::invalidateTTMBuffers() 546 { 547 BufferMapper* mapper; 548 for (size_t i = 0; i < mTTMBuffers.size(); i++) { 549 mapper = mTTMBuffers.valueAt(i); 550 // putTTMMapper removes mapper from cache 551 putTTMMapper(mapper); 552 } 553 mTTMBuffers.clear(); 554 } 555 556 557 bool OverlayPlaneBase::rotatedBufferReady(BufferMapper& mapper, BufferMapper* &rotatedMapper) 558 { 559 struct VideoPayloadBuffer *payload; 560 uint32_t format; 561 562 // only NV12_VED has rotated buffer 563 format = mapper.getFormat(); 564 if (format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar && 565 format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled) 566 return false; 567 568 payload = (struct VideoPayloadBuffer *)mapper.getCpuAddress(SUB_BUFFER1); 569 // check payload 570 if (!payload) { 571 ELOGTRACE("no payload found"); 572 return false; 573 } 574 575 if (payload->force_output_method == FORCE_OUTPUT_GPU) 576 return false; 577 578 if (payload->client_transform != mTransform) { 579 if (payload->surface_protected) { 580 payload->hwc_timestamp = systemTime(); 581 payload->layer_transform = mTransform; 582 } 583 WLOGTRACE("client is not ready"); 584 return false; 585 } 586 587 rotatedMapper = getTTMMapper(mapper, payload); 588 return true; 589 } 590 591 592 bool OverlayPlaneBase::useOverlayRotation(BufferMapper& /* mapper */) 593 { 594 // by default overlay plane does not support rotation. 595 return false; 596 } 597 598 void OverlayPlaneBase::checkPosition(int& x, int& y, int& w, int& h) 599 { 600 drmModeModeInfoPtr mode = &mModeInfo; 601 602 if (mode->hdisplay == 0 || mode->vdisplay == 0) 603 return; 604 605 if (x < 0) 606 x = 0; 607 if (y < 0) 608 y = 0; 609 if ((x + w) > mode->hdisplay) 610 w = mode->hdisplay - x; 611 if ((y + h) > mode->vdisplay) 612 h = mode->vdisplay - y; 613 } 614 615 void OverlayPlaneBase::checkCrop(int& srcX, int& srcY, int& srcW, int& srcH, 616 int coded_width, int coded_height) 617 { 618 int tmp; 619 620 if (mTransform) 621 srcH >>= mBobDeinterlace; 622 623 if (mTransform == HWC_TRANSFORM_ROT_90 || mTransform == HWC_TRANSFORM_ROT_270) { 624 tmp = srcH; 625 srcH = srcW; 626 srcW = tmp; 627 628 tmp = srcX; 629 srcX = srcY; 630 srcY = tmp; 631 632 tmp = coded_width; 633 coded_width = coded_height; 634 coded_height = tmp; 635 } 636 637 // skip pading bytes in rotate buffer 638 switch(mTransform) { 639 case HWC_TRANSFORM_ROT_90: 640 srcX = (coded_width >> mBobDeinterlace) - srcW - srcX; 641 break; 642 case HWC_TRANSFORM_ROT_180: 643 srcX = coded_width - srcW - srcX; 644 srcY = (coded_height >> mBobDeinterlace) - srcH - srcY; 645 break; 646 case HWC_TRANSFORM_ROT_270: 647 srcY = coded_height - srcH - srcY; 648 break; 649 default: 650 break; 651 } 652 } 653 654 655 bool OverlayPlaneBase::bufferOffsetSetup(BufferMapper& mapper) 656 { 657 CTRACE(); 658 659 OverlayBackBufferBlk *backBuffer = mBackBuffer[mCurrent]->buf; 660 if (!backBuffer) { 661 ELOGTRACE("invalid back buffer"); 662 return false; 663 } 664 665 uint32_t format = mapper.getFormat(); 666 uint32_t gttOffsetInBytes = (mapper.getGttOffsetInPage(0) << 12); 667 uint32_t yStride = mapper.getStride().yuv.yStride; 668 uint32_t uvStride = mapper.getStride().yuv.uvStride; 669 uint32_t h = mapper.getHeight(); 670 uint32_t srcX= mapper.getCrop().x; 671 uint32_t srcY= mapper.getCrop().y; 672 673 // clear original format setting 674 backBuffer->OCMD &= ~(0xf << 10); 675 backBuffer->OCMD &= ~OVERLAY_MEMORY_LAYOUT_TILED; 676 677 // Y/U/V plane must be 4k bytes aligned. 678 backBuffer->OSTART_0Y = gttOffsetInBytes; 679 if (mIsProtectedBuffer) { 680 // temporary workaround until vsync event logic is corrected. 681 // it seems that overlay buffer update and renderring can be overlapped, 682 // as such encryption bit may be cleared during HW rendering 683 backBuffer->OSTART_0Y |= 0x01; 684 } 685 686 backBuffer->OSTART_0U = gttOffsetInBytes; 687 backBuffer->OSTART_0V = gttOffsetInBytes; 688 689 backBuffer->OSTART_1Y = backBuffer->OSTART_0Y; 690 backBuffer->OSTART_1U = backBuffer->OSTART_0U; 691 backBuffer->OSTART_1V = backBuffer->OSTART_0V; 692 693 switch(format) { 694 case HAL_PIXEL_FORMAT_YV12: // YV12 695 backBuffer->OBUF_0Y = 0; 696 backBuffer->OBUF_0V = yStride * h; 697 backBuffer->OBUF_0U = backBuffer->OBUF_0V + (uvStride * (h / 2)); 698 backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_YUV420; 699 break; 700 case HAL_PIXEL_FORMAT_INTEL_YV12: // INTEL_YV12 701 backBuffer->OBUF_0Y = 0; 702 backBuffer->OBUF_0V = yStride * align_to(h, 32); 703 backBuffer->OBUF_0U = backBuffer->OBUF_0V + (uvStride * (align_to(h, 32) / 2)); 704 backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_YUV420; 705 break; 706 case HAL_PIXEL_FORMAT_I420: // I420 707 backBuffer->OBUF_0Y = 0; 708 backBuffer->OBUF_0U = yStride * h; 709 backBuffer->OBUF_0V = backBuffer->OBUF_0U + (uvStride * (h / 2)); 710 backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_YUV420; 711 break; 712 case HAL_PIXEL_FORMAT_NV12: // NV12 713 backBuffer->OBUF_0Y = 0; 714 backBuffer->OBUF_0U = yStride * h; 715 backBuffer->OBUF_0V = 0; 716 backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_NV12_2; 717 break; 718 // NOTE: this is the decoded video format, align the height to 32B 719 //as it's defined by video driver 720 case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar: // Intel codec NV12 721 backBuffer->OBUF_0Y = 0; 722 backBuffer->OBUF_0U = yStride * align_to(h, 32); 723 backBuffer->OBUF_0V = 0; 724 backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_NV12_2; 725 break; 726 case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled: //NV12_tiled 727 backBuffer->OBUF_0Y = 0; 728 backBuffer->OBUF_0U = yStride * align_to(h, 32); 729 backBuffer->OBUF_0V = 0; 730 backBuffer->OSTART_0U += yStride * align_to(h, 32); 731 backBuffer->OSTART_0V += yStride * align_to(h, 32); 732 backBuffer->OSTART_1U = backBuffer->OSTART_0U; 733 backBuffer->OSTART_1V = backBuffer->OSTART_0V; 734 backBuffer->OTILEOFF_0Y = srcX + (srcY << 16); 735 backBuffer->OTILEOFF_1Y = backBuffer->OTILEOFF_0Y; 736 backBuffer->OTILEOFF_0U = srcX + ((srcY / 2) << 16); 737 backBuffer->OTILEOFF_1U = backBuffer->OTILEOFF_0U; 738 backBuffer->OTILEOFF_0V = backBuffer->OTILEOFF_0U; 739 backBuffer->OTILEOFF_1V = backBuffer->OTILEOFF_0U; 740 backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_NV12_2; 741 backBuffer->OCMD |= OVERLAY_MEMORY_LAYOUT_TILED; 742 break; 743 case HAL_PIXEL_FORMAT_YUY2: // YUY2 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_YUY2; 749 break; 750 case HAL_PIXEL_FORMAT_UYVY: // UYVY 751 backBuffer->OBUF_0Y = 0; 752 backBuffer->OBUF_0U = 0; 753 backBuffer->OBUF_0V = 0; 754 backBuffer->OCMD |= OVERLAY_FORMAT_PACKED_YUV422; 755 backBuffer->OCMD |= OVERLAY_PACKED_ORDER_UYVY; 756 break; 757 default: 758 ELOGTRACE("unsupported format %d", format); 759 return false; 760 } 761 762 backBuffer->OBUF_0Y += srcY * yStride + srcX; 763 backBuffer->OBUF_0V += (srcY / 2) * uvStride + srcX; 764 backBuffer->OBUF_0U += (srcY / 2) * uvStride + srcX; 765 backBuffer->OBUF_1Y = backBuffer->OBUF_0Y; 766 backBuffer->OBUF_1U = backBuffer->OBUF_0U; 767 backBuffer->OBUF_1V = backBuffer->OBUF_0V; 768 769 VLOGTRACE("done. offset (%d, %d, %d)", 770 backBuffer->OBUF_0Y, 771 backBuffer->OBUF_0U, 772 backBuffer->OBUF_0V); 773 return true; 774 } 775 776 uint32_t OverlayPlaneBase::calculateSWidthSW(uint32_t offset, uint32_t width) 777 { 778 ALOGTRACE("offset = %d, width = %d", offset, width); 779 780 uint32_t swidth = ((offset + width + 0x3F) >> 6) - (offset >> 6); 781 782 swidth <<= 1; 783 swidth -= 1; 784 785 return swidth; 786 } 787 788 bool OverlayPlaneBase::coordinateSetup(BufferMapper& mapper) 789 { 790 CTRACE(); 791 792 OverlayBackBufferBlk *backBuffer = mBackBuffer[mCurrent]->buf; 793 if (!backBuffer) { 794 ELOGTRACE("invalid back buffer"); 795 return false; 796 } 797 798 uint32_t swidthy = 0; 799 uint32_t swidthuv = 0; 800 uint32_t format = mapper.getFormat(); 801 uint32_t width = mapper.getCrop().w; 802 uint32_t height = mapper.getCrop().h; 803 uint32_t yStride = mapper.getStride().yuv.yStride; 804 uint32_t uvStride = mapper.getStride().yuv.uvStride; 805 uint32_t offsety = backBuffer->OBUF_0Y; 806 uint32_t offsetu = backBuffer->OBUF_0U; 807 808 switch (format) { 809 case HAL_PIXEL_FORMAT_YV12: // YV12 810 case HAL_PIXEL_FORMAT_INTEL_YV12: // INTEL_YV12 811 case HAL_PIXEL_FORMAT_I420: // I420 812 case HAL_PIXEL_FORMAT_NV12: // NV12 813 case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar: // NV12 814 case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled: // NV12_tiled 815 break; 816 case HAL_PIXEL_FORMAT_YUY2: // YUY2 817 case HAL_PIXEL_FORMAT_UYVY: // UYVY 818 width <<= 1; 819 break; 820 default: 821 ELOGTRACE("unsupported format %d", format); 822 return false; 823 } 824 825 if (width <= 0 || height <= 0) { 826 ELOGTRACE("invalid src dim"); 827 return false; 828 } 829 830 if (yStride <=0 && uvStride <= 0) { 831 ELOGTRACE("invalid source stride"); 832 return false; 833 } 834 835 backBuffer->SWIDTH = width | ((width / 2) << 16); 836 swidthy = calculateSWidthSW(offsety, width); 837 swidthuv = calculateSWidthSW(offsetu, width / 2); 838 backBuffer->SWIDTHSW = (swidthy << 2) | (swidthuv << 18); 839 backBuffer->SHEIGHT = height | ((height / 2) << 16); 840 backBuffer->OSTRIDE = (yStride & (~0x3f)) | ((uvStride & (~0x3f)) << 16); 841 842 XLOGTRACE(); 843 844 return true; 845 } 846 847 bool OverlayPlaneBase::setCoeffRegs(double *coeff, int mantSize, 848 coeffPtr pCoeff, int pos) 849 { 850 int maxVal, icoeff, res; 851 int sign; 852 double c; 853 854 sign = 0; 855 maxVal = 1 << mantSize; 856 c = *coeff; 857 if (c < 0.0) { 858 sign = 1; 859 c = -c; 860 } 861 862 res = 12 - mantSize; 863 if ((icoeff = (int)(c * 4 * maxVal + 0.5)) < maxVal) { 864 pCoeff[pos].exponent = 3; 865 pCoeff[pos].mantissa = icoeff << res; 866 *coeff = (double)icoeff / (double)(4 * maxVal); 867 } else if ((icoeff = (int)(c * 2 * maxVal + 0.5)) < maxVal) { 868 pCoeff[pos].exponent = 2; 869 pCoeff[pos].mantissa = icoeff << res; 870 *coeff = (double)icoeff / (double)(2 * maxVal); 871 } else if ((icoeff = (int)(c * maxVal + 0.5)) < maxVal) { 872 pCoeff[pos].exponent = 1; 873 pCoeff[pos].mantissa = icoeff << res; 874 *coeff = (double)icoeff / (double)(maxVal); 875 } else if ((icoeff = (int)(c * maxVal * 0.5 + 0.5)) < maxVal) { 876 pCoeff[pos].exponent = 0; 877 pCoeff[pos].mantissa = icoeff << res; 878 *coeff = (double)icoeff / (double)(maxVal / 2); 879 } else { 880 // Coeff out of range 881 return false; 882 } 883 884 pCoeff[pos].sign = sign; 885 if (sign) 886 *coeff = -(*coeff); 887 return true; 888 } 889 890 void OverlayPlaneBase::updateCoeff(int taps, double fCutoff, 891 bool isHoriz, bool isY, 892 coeffPtr pCoeff) 893 { 894 int i, j, j1, num, pos, mantSize; 895 double pi = 3.1415926535, val, sinc, window, sum; 896 double rawCoeff[MAX_TAPS * 32], coeffs[N_PHASES][MAX_TAPS]; 897 double diff; 898 int tapAdjust[MAX_TAPS], tap2Fix; 899 bool isVertAndUV; 900 901 if (isHoriz) 902 mantSize = 7; 903 else 904 mantSize = 6; 905 906 isVertAndUV = !isHoriz && !isY; 907 num = taps * 16; 908 for (i = 0; i < num * 2; i++) { 909 val = (1.0 / fCutoff) * taps * pi * (i - num) / (2 * num); 910 if (val == 0.0) 911 sinc = 1.0; 912 else 913 sinc = sin(val) / val; 914 915 // Hamming window 916 window = (0.54 - 0.46 * cos(2 * i * pi / (2 * num - 1))); 917 rawCoeff[i] = sinc * window; 918 } 919 920 for (i = 0; i < N_PHASES; i++) { 921 // Normalise the coefficients 922 sum = 0.0; 923 for (j = 0; j < taps; j++) { 924 pos = i + j * 32; 925 sum += rawCoeff[pos]; 926 } 927 for (j = 0; j < taps; j++) { 928 pos = i + j * 32; 929 coeffs[i][j] = rawCoeff[pos] / sum; 930 } 931 932 // Set the register values 933 for (j = 0; j < taps; j++) { 934 pos = j + i * taps; 935 if ((j == (taps - 1) / 2) && !isVertAndUV) 936 setCoeffRegs(&coeffs[i][j], mantSize + 2, pCoeff, pos); 937 else 938 setCoeffRegs(&coeffs[i][j], mantSize, pCoeff, pos); 939 } 940 941 tapAdjust[0] = (taps - 1) / 2; 942 for (j = 1, j1 = 1; j <= tapAdjust[0]; j++, j1++) { 943 tapAdjust[j1] = tapAdjust[0] - j; 944 tapAdjust[++j1] = tapAdjust[0] + j; 945 } 946 947 // Adjust the coefficients 948 sum = 0.0; 949 for (j = 0; j < taps; j++) 950 sum += coeffs[i][j]; 951 if (sum != 1.0) { 952 for (j1 = 0; j1 < taps; j1++) { 953 tap2Fix = tapAdjust[j1]; 954 diff = 1.0 - sum; 955 coeffs[i][tap2Fix] += diff; 956 pos = tap2Fix + i * taps; 957 if ((tap2Fix == (taps - 1) / 2) && !isVertAndUV) 958 setCoeffRegs(&coeffs[i][tap2Fix], mantSize + 2, pCoeff, pos); 959 else 960 setCoeffRegs(&coeffs[i][tap2Fix], mantSize, pCoeff, pos); 961 962 sum = 0.0; 963 for (j = 0; j < taps; j++) 964 sum += coeffs[i][j]; 965 if (sum == 1.0) 966 break; 967 } 968 } 969 } 970 } 971 972 bool OverlayPlaneBase::scalingSetup(BufferMapper& mapper) 973 { 974 int xscaleInt, xscaleFract, yscaleInt, yscaleFract; 975 int xscaleIntUV, xscaleFractUV; 976 int yscaleIntUV, yscaleFractUV; 977 int deinterlace_factor = 1; 978 // UV is half the size of Y -- YUV420 979 int uvratio = 2; 980 uint32_t newval; 981 coeffRec xcoeffY[N_HORIZ_Y_TAPS * N_PHASES]; 982 coeffRec xcoeffUV[N_HORIZ_UV_TAPS * N_PHASES]; 983 int i, j, pos; 984 bool scaleChanged = false; 985 int x, y, w, h; 986 987 OverlayBackBufferBlk *backBuffer = mBackBuffer[mCurrent]->buf; 988 if (!backBuffer) { 989 ELOGTRACE("invalid back buffer"); 990 return false; 991 } 992 993 x = mPosition.x; 994 y = mPosition.y; 995 w = mPosition.w; 996 h = mPosition.h; 997 998 // check position 999 checkPosition(x, y, w, h); 1000 VLOGTRACE("final position (%d, %d, %d, %d)", x, y, w, h); 1001 1002 if ((w <= 0) || (h <= 0)) { 1003 ELOGTRACE("invalid dst width/height"); 1004 return false; 1005 } 1006 1007 // setup dst position 1008 backBuffer->DWINPOS = (y << 16) | x; 1009 backBuffer->DWINSZ = (h << 16) | w; 1010 1011 uint32_t srcWidth = mapper.getCrop().w; 1012 uint32_t srcHeight = mapper.getCrop().h; 1013 uint32_t dstWidth = w; 1014 uint32_t dstHeight = h; 1015 1016 VLOGTRACE("src (%dx%d), dst (%dx%d)", 1017 srcWidth, srcHeight, 1018 dstWidth, dstHeight); 1019 1020 // Y down-scale factor as a multiple of 4096 1021 if (srcWidth == dstWidth && srcHeight == dstHeight) { 1022 xscaleFract = (1 << 12); 1023 yscaleFract = (1 << 12)/deinterlace_factor; 1024 } else { 1025 xscaleFract = ((srcWidth - 1) << 12) / dstWidth; 1026 yscaleFract = ((srcHeight - 1) << 12) / (dstHeight * deinterlace_factor); 1027 } 1028 1029 // Calculate the UV scaling factor 1030 xscaleFractUV = xscaleFract / uvratio; 1031 yscaleFractUV = yscaleFract / uvratio; 1032 1033 // To keep the relative Y and UV ratios exact, round the Y scales 1034 // to a multiple of the Y/UV ratio. 1035 xscaleFract = xscaleFractUV * uvratio; 1036 yscaleFract = yscaleFractUV * uvratio; 1037 1038 // Integer (un-multiplied) values 1039 xscaleInt = xscaleFract >> 12; 1040 yscaleInt = yscaleFract >> 12; 1041 1042 xscaleIntUV = xscaleFractUV >> 12; 1043 yscaleIntUV = yscaleFractUV >> 12; 1044 1045 // Check scaling ratio 1046 if (xscaleInt > INTEL_OVERLAY_MAX_SCALING_RATIO) { 1047 ELOGTRACE("xscaleInt > %d", INTEL_OVERLAY_MAX_SCALING_RATIO); 1048 return false; 1049 } 1050 1051 // shouldn't get here 1052 if (xscaleIntUV > INTEL_OVERLAY_MAX_SCALING_RATIO) { 1053 ELOGTRACE("xscaleIntUV > %d", INTEL_OVERLAY_MAX_SCALING_RATIO); 1054 return false; 1055 } 1056 1057 newval = (xscaleInt << 15) | 1058 ((xscaleFract & 0xFFF) << 3) | ((yscaleFract & 0xFFF) << 20); 1059 if (newval != backBuffer->YRGBSCALE) { 1060 scaleChanged = true; 1061 backBuffer->YRGBSCALE = newval; 1062 } 1063 1064 newval = (xscaleIntUV << 15) | ((xscaleFractUV & 0xFFF) << 3) | 1065 ((yscaleFractUV & 0xFFF) << 20); 1066 if (newval != backBuffer->UVSCALE) { 1067 scaleChanged = true; 1068 backBuffer->UVSCALE = newval; 1069 } 1070 1071 newval = yscaleInt << 16 | yscaleIntUV; 1072 if (newval != backBuffer->UVSCALEV) { 1073 scaleChanged = true; 1074 backBuffer->UVSCALEV = newval; 1075 } 1076 1077 // Recalculate coefficients if the scaling changed 1078 // Only Horizontal coefficients so far. 1079 if (scaleChanged) { 1080 double fCutoffY; 1081 double fCutoffUV; 1082 1083 fCutoffY = xscaleFract / 4096.0; 1084 fCutoffUV = xscaleFractUV / 4096.0; 1085 1086 // Limit to between 1.0 and 3.0 1087 if (fCutoffY < MIN_CUTOFF_FREQ) 1088 fCutoffY = MIN_CUTOFF_FREQ; 1089 if (fCutoffY > MAX_CUTOFF_FREQ) 1090 fCutoffY = MAX_CUTOFF_FREQ; 1091 if (fCutoffUV < MIN_CUTOFF_FREQ) 1092 fCutoffUV = MIN_CUTOFF_FREQ; 1093 if (fCutoffUV > MAX_CUTOFF_FREQ) 1094 fCutoffUV = MAX_CUTOFF_FREQ; 1095 1096 updateCoeff(N_HORIZ_Y_TAPS, fCutoffY, true, true, xcoeffY); 1097 updateCoeff(N_HORIZ_UV_TAPS, fCutoffUV, true, false, xcoeffUV); 1098 1099 for (i = 0; i < N_PHASES; i++) { 1100 for (j = 0; j < N_HORIZ_Y_TAPS; j++) { 1101 pos = i * N_HORIZ_Y_TAPS + j; 1102 backBuffer->Y_HCOEFS[pos] = 1103 (xcoeffY[pos].sign << 15 | 1104 xcoeffY[pos].exponent << 12 | 1105 xcoeffY[pos].mantissa); 1106 } 1107 } 1108 for (i = 0; i < N_PHASES; i++) { 1109 for (j = 0; j < N_HORIZ_UV_TAPS; j++) { 1110 pos = i * N_HORIZ_UV_TAPS + j; 1111 backBuffer->UV_HCOEFS[pos] = 1112 (xcoeffUV[pos].sign << 15 | 1113 xcoeffUV[pos].exponent << 12 | 1114 xcoeffUV[pos].mantissa); 1115 } 1116 } 1117 } 1118 1119 XLOGTRACE(); 1120 return true; 1121 } 1122 1123 bool OverlayPlaneBase::colorSetup(BufferMapper& mapper) 1124 { 1125 CTRACE(); 1126 1127 OverlayBackBufferBlk *backBuffer = mBackBuffer[mCurrent]->buf; 1128 if (!backBuffer) { 1129 ELOGTRACE("invalid back buffer"); 1130 return false; 1131 } 1132 1133 if (mPipeConfig == (0x2 << 6)) 1134 return true; 1135 1136 uint32_t format = mapper.getFormat(); 1137 if (format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar && 1138 format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled) { 1139 1140 VLOGTRACE("Not video layer, use default color setting"); 1141 backBuffer->OCLRC0 = (OVERLAY_INIT_CONTRAST << 18) | 1142 (OVERLAY_INIT_BRIGHTNESS & 0xff); 1143 backBuffer->OCLRC1 = OVERLAY_INIT_SATURATION; 1144 backBuffer->OCONFIG &= ~(1 << 5); 1145 1146 return true; 1147 } 1148 1149 struct VideoPayloadBuffer *payload; 1150 payload = (struct VideoPayloadBuffer *)mapper.getCpuAddress(SUB_BUFFER1); 1151 // check payload 1152 if (!payload) { 1153 ELOGTRACE("no payload found"); 1154 return false; 1155 } 1156 1157 // BT.601 or BT.709 1158 backBuffer->OCONFIG &= ~(1 << 5); 1159 backBuffer->OCONFIG |= (payload->csc_mode << 5); 1160 1161 if (payload->video_range) { 1162 // full range, no need to do level expansion 1163 backBuffer->OCLRC0 = 0x1000000; 1164 backBuffer->OCLRC1 = 0x80; 1165 } else { 1166 // level expansion for limited range 1167 backBuffer->OCLRC0 = (OVERLAY_INIT_CONTRAST << 18) | 1168 (OVERLAY_INIT_BRIGHTNESS & 0xff); 1169 backBuffer->OCLRC1 = OVERLAY_INIT_SATURATION; 1170 } 1171 1172 return true; 1173 } 1174 1175 bool OverlayPlaneBase::setDataBuffer(BufferMapper& grallocMapper) 1176 { 1177 BufferMapper *mapper; 1178 BufferMapper *rotatedMapper = 0; 1179 bool ret; 1180 uint32_t format; 1181 1182 RETURN_FALSE_IF_NOT_INIT(); 1183 1184 // get gralloc mapper 1185 mapper = &grallocMapper; 1186 format = grallocMapper.getFormat(); 1187 if (format == OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar || 1188 format == OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled) { 1189 struct VideoPayloadBuffer *payload; 1190 payload = (struct VideoPayloadBuffer *)grallocMapper.getCpuAddress(SUB_BUFFER1); 1191 if (!payload) { 1192 ELOGTRACE("invalid payload buffer"); 1193 return 0; 1194 } 1195 1196 mBobDeinterlace = payload->bob_deinterlace; 1197 } 1198 1199 if (mTransform && !useOverlayRotation(grallocMapper)) { 1200 if (!rotatedBufferReady(grallocMapper, rotatedMapper)) { 1201 DLOGTRACE("rotated buffer is not ready"); 1202 return false; 1203 } 1204 1205 if (!rotatedMapper) { 1206 ELOGTRACE("failed to get rotated buffer"); 1207 return false; 1208 } 1209 mapper = rotatedMapper; 1210 } 1211 1212 OverlayBackBufferBlk *backBuffer = mBackBuffer[mCurrent]->buf; 1213 if (!backBuffer) { 1214 ELOGTRACE("invalid back buffer"); 1215 return false; 1216 } 1217 1218 ret = bufferOffsetSetup(*mapper); 1219 if (ret == false) { 1220 ELOGTRACE("failed to set up buffer offsets"); 1221 return false; 1222 } 1223 1224 ret = coordinateSetup(*mapper); 1225 if (ret == false) { 1226 ELOGTRACE("failed to set up overlay coordinates"); 1227 return false; 1228 } 1229 1230 ret = scalingSetup(*mapper); 1231 if (ret == false) { 1232 ELOGTRACE("failed to set up scaling parameters"); 1233 return false; 1234 } 1235 1236 backBuffer->OCMD |= 0x1; 1237 1238 if (mBobDeinterlace && !mTransform) { 1239 backBuffer->OCMD |= BUF_TYPE_FIELD; 1240 backBuffer->OCMD &= ~FIELD_SELECT; 1241 backBuffer->OCMD |= FIELD0; 1242 backBuffer->OCMD &= ~(BUFFER_SELECT); 1243 backBuffer->OCMD |= BUFFER0; 1244 } else { 1245 backBuffer->OCMD &= ~BUF_TYPE; 1246 backBuffer->OCMD &= ~FIELD_SELECT; 1247 backBuffer->OCMD &= ~(BUFFER_SELECT); 1248 } 1249 1250 ret = colorSetup(*mapper); 1251 if (ret == false) { 1252 ELOGTRACE("failed to set up color parameters"); 1253 return false; 1254 } 1255 1256 // add to active ttm buffers if it's a rotated buffer 1257 if (rotatedMapper) { 1258 updateActiveTTMBuffers(mapper); 1259 } 1260 1261 return true; 1262 } 1263 1264 } // namespace intel 1265 } // namespace android 1266 1267