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