hwc_utils.cpp revision 0edd0eba442e8b6db2fc2758ecd48e888d251d02
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * Copyright (C) 2012-2013, The Linux Foundation All rights reserved. 4 * 5 * Not a Contribution, Apache license notifications and license are retained 6 * for attribution purposes only. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20#define HWC_UTILS_DEBUG 0 21#include <sys/ioctl.h> 22#include <binder/IServiceManager.h> 23#include <EGL/egl.h> 24#include <cutils/properties.h> 25#include <gralloc_priv.h> 26#include <overlay.h> 27#include <overlayRotator.h> 28#include "hwc_utils.h" 29#include "hwc_mdpcomp.h" 30#include "hwc_fbupdate.h" 31#include "hwc_video.h" 32#include "mdp_version.h" 33#include "hwc_copybit.h" 34#include "external.h" 35#include "hwc_qclient.h" 36#include "QService.h" 37#include "comptype.h" 38 39using namespace qClient; 40using namespace qService; 41using namespace android; 42using namespace overlay; 43using namespace overlay::utils; 44namespace ovutils = overlay::utils; 45 46namespace qhwc { 47 48static int openFramebufferDevice(hwc_context_t *ctx) 49{ 50 struct fb_fix_screeninfo finfo; 51 struct fb_var_screeninfo info; 52 53 int fb_fd = openFb(HWC_DISPLAY_PRIMARY); 54 55 if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &info) == -1) 56 return -errno; 57 58 if (int(info.width) <= 0 || int(info.height) <= 0) { 59 // the driver doesn't return that information 60 // default to 160 dpi 61 info.width = ((info.xres * 25.4f)/160.0f + 0.5f); 62 info.height = ((info.yres * 25.4f)/160.0f + 0.5f); 63 } 64 65 float xdpi = (info.xres * 25.4f) / info.width; 66 float ydpi = (info.yres * 25.4f) / info.height; 67 68#ifdef MSMFB_METADATA_GET 69 struct msmfb_metadata metadata; 70 memset(&metadata, 0 , sizeof(metadata)); 71 metadata.op = metadata_op_frame_rate; 72 73 if (ioctl(fb_fd, MSMFB_METADATA_GET, &metadata) == -1) { 74 ALOGE("Error retrieving panel frame rate"); 75 return -errno; 76 } 77 78 float fps = metadata.data.panel_frame_rate; 79#else 80 //XXX: Remove reserved field usage on all baselines 81 //The reserved[3] field is used to store FPS by the driver. 82 float fps = info.reserved[3] & 0xFF; 83#endif 84 85 if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &finfo) == -1) 86 return -errno; 87 88 if (finfo.smem_len <= 0) 89 return -errno; 90 91 ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd = fb_fd; 92 //xres, yres may not be 32 aligned 93 ctx->dpyAttr[HWC_DISPLAY_PRIMARY].stride = finfo.line_length /(info.xres/8); 94 ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres = info.xres; 95 ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres = info.yres; 96 ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xdpi = xdpi; 97 ctx->dpyAttr[HWC_DISPLAY_PRIMARY].ydpi = ydpi; 98 ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period = 1000000000l / fps; 99 100 return 0; 101} 102 103void initContext(hwc_context_t *ctx) 104{ 105 if(openFramebufferDevice(ctx) < 0) { 106 ALOGE("%s: failed to open framebuffer!!", __FUNCTION__); 107 } 108 109 overlay::Overlay::initOverlay(); 110 ctx->mOverlay = overlay::Overlay::getInstance(); 111 ctx->mRotMgr = new RotMgr(); 112 ctx->mMDP.version = qdutils::MDPVersion::getInstance().getMDPVersion(); 113 ctx->mMDP.hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay(); 114 ctx->mMDP.panel = qdutils::MDPVersion::getInstance().getPanelType(); 115 overlay::Overlay::initOverlay(); 116 ctx->mOverlay = overlay::Overlay::getInstance(); 117 ctx->mRotMgr = new RotMgr(); 118 119 //Is created and destroyed only once for primary 120 //For external it could get created and destroyed multiple times depending 121 //on what external we connect to. 122 ctx->mFBUpdate[HWC_DISPLAY_PRIMARY] = 123 IFBUpdate::getObject(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres, 124 HWC_DISPLAY_PRIMARY); 125 126 ctx->mVidOv[HWC_DISPLAY_PRIMARY] = 127 IVideoOverlay::getObject(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres, 128 HWC_DISPLAY_PRIMARY); 129 130 // Check if the target supports copybit compostion (dyn/mdp/c2d) to 131 // decide if we need to open the copybit module. 132 int compositionType = 133 qdutils::QCCompositionType::getInstance().getCompositionType(); 134 135 if (compositionType & (qdutils::COMPOSITION_TYPE_DYN | 136 qdutils::COMPOSITION_TYPE_MDP | 137 qdutils::COMPOSITION_TYPE_C2D)) { 138 ctx->mCopyBit[HWC_DISPLAY_PRIMARY] = new CopyBit(); 139 } 140 141 ctx->mExtDisplay = new ExternalDisplay(ctx); 142 for (uint32_t i = 0; i < MAX_DISPLAYS; i++) 143 ctx->mLayerCache[i] = new LayerCache(); 144 ctx->mMDPComp = MDPComp::getObject(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres); 145 MDPComp::init(ctx); 146 147 pthread_mutex_init(&(ctx->vstate.lock), NULL); 148 pthread_cond_init(&(ctx->vstate.cond), NULL); 149 ctx->vstate.enable = false; 150 ctx->vstate.fakevsync = false; 151 ctx->mExtDispConfiguring = false; 152 153 //Right now hwc starts the service but anybody could do it, or it could be 154 //independent process as well. 155 QService::init(); 156 sp<IQClient> client = new QClient(ctx); 157 interface_cast<IQService>( 158 defaultServiceManager()->getService( 159 String16("display.qservice")))->connect(client); 160 161 ALOGI("Initializing Qualcomm Hardware Composer"); 162 ALOGI("MDP version: %d", ctx->mMDP.version); 163} 164 165void closeContext(hwc_context_t *ctx) 166{ 167 if(ctx->mOverlay) { 168 delete ctx->mOverlay; 169 ctx->mOverlay = NULL; 170 } 171 172 if(ctx->mRotMgr) { 173 delete ctx->mRotMgr; 174 ctx->mRotMgr = NULL; 175 } 176 177 for(int i = 0; i < MAX_DISPLAYS; i++) { 178 if(ctx->mCopyBit[i]) { 179 delete ctx->mCopyBit[i]; 180 ctx->mCopyBit[i] = NULL; 181 } 182 } 183 184 if(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd) { 185 close(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd); 186 ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd = -1; 187 } 188 189 if(ctx->mExtDisplay) { 190 delete ctx->mExtDisplay; 191 ctx->mExtDisplay = NULL; 192 } 193 194 for(int i = 0; i < MAX_DISPLAYS; i++) { 195 if(ctx->mFBUpdate[i]) { 196 delete ctx->mFBUpdate[i]; 197 ctx->mFBUpdate[i] = NULL; 198 } 199 if(ctx->mVidOv[i]) { 200 delete ctx->mVidOv[i]; 201 ctx->mVidOv[i] = NULL; 202 } 203 } 204 205 if(ctx->mMDPComp) { 206 delete ctx->mMDPComp; 207 ctx->mMDPComp = NULL; 208 } 209 210 pthread_mutex_destroy(&(ctx->vstate.lock)); 211 pthread_cond_destroy(&(ctx->vstate.cond)); 212} 213 214 215void dumpsys_log(android::String8& buf, const char* fmt, ...) 216{ 217 va_list varargs; 218 va_start(varargs, fmt); 219 buf.appendFormatV(fmt, varargs); 220 va_end(varargs); 221} 222 223/* Calculates the destination position based on the action safe rectangle */ 224void getActionSafePosition(hwc_context_t *ctx, int dpy, uint32_t& x, 225 uint32_t& y, uint32_t& w, uint32_t& h) { 226 227 // if external supports underscan, do nothing 228 // it will be taken care in the driver 229 if(ctx->mExtDisplay->isCEUnderscanSupported()) 230 return; 231 232 float wRatio = 1.0; 233 float hRatio = 1.0; 234 float xRatio = 1.0; 235 float yRatio = 1.0; 236 237 float fbWidth = ctx->dpyAttr[dpy].xres; 238 float fbHeight = ctx->dpyAttr[dpy].yres; 239 240 float asX = 0; 241 float asY = 0; 242 float asW = fbWidth; 243 float asH= fbHeight; 244 char value[PROPERTY_VALUE_MAX]; 245 246 // Apply action safe parameters 247 property_get("hw.actionsafe.width", value, "0"); 248 int asWidthRatio = atoi(value); 249 property_get("hw.actionsafe.height", value, "0"); 250 int asHeightRatio = atoi(value); 251 // based on the action safe ratio, get the Action safe rectangle 252 asW = fbWidth * (1.0f - asWidthRatio / 100.0f); 253 asH = fbHeight * (1.0f - asHeightRatio / 100.0f); 254 asX = (fbWidth - asW) / 2; 255 asY = (fbHeight - asH) / 2; 256 257 // calculate the position ratio 258 xRatio = (float)x/fbWidth; 259 yRatio = (float)y/fbHeight; 260 wRatio = (float)w/fbWidth; 261 hRatio = (float)h/fbHeight; 262 263 //Calculate the position... 264 x = (xRatio * asW) + asX; 265 y = (yRatio * asH) + asY; 266 w = (wRatio * asW); 267 h = (hRatio * asH); 268 269 return; 270} 271 272bool needsScaling(hwc_layer_1_t const* layer) { 273 int dst_w, dst_h, src_w, src_h; 274 275 hwc_rect_t displayFrame = layer->displayFrame; 276 hwc_rect_t sourceCrop = layer->sourceCrop; 277 278 dst_w = displayFrame.right - displayFrame.left; 279 dst_h = displayFrame.bottom - displayFrame.top; 280 281 src_w = sourceCrop.right - sourceCrop.left; 282 src_h = sourceCrop.bottom - sourceCrop.top; 283 284 if(((src_w != dst_w) || (src_h != dst_h))) 285 return true; 286 287 return false; 288} 289 290bool isAlphaScaled(hwc_layer_1_t const* layer) { 291 if(needsScaling(layer) && isAlphaPresent(layer)) { 292 return true; 293 } 294 return false; 295} 296 297bool isAlphaPresent(hwc_layer_1_t const* layer) { 298 private_handle_t *hnd = (private_handle_t *)layer->handle; 299 if(hnd) { 300 int format = hnd->format; 301 switch(format) { 302 case HAL_PIXEL_FORMAT_RGBA_8888: 303 case HAL_PIXEL_FORMAT_BGRA_8888: 304 // In any more formats with Alpha go here.. 305 return true; 306 default : return false; 307 } 308 } 309 return false; 310} 311 312void setListStats(hwc_context_t *ctx, 313 const hwc_display_contents_1_t *list, int dpy) { 314 315 ctx->listStats[dpy].numAppLayers = list->numHwLayers - 1; 316 ctx->listStats[dpy].fbLayerIndex = list->numHwLayers - 1; 317 ctx->listStats[dpy].skipCount = 0; 318 ctx->listStats[dpy].needsAlphaScale = false; 319 ctx->listStats[dpy].preMultipliedAlpha = false; 320 ctx->listStats[dpy].yuvCount = 0; 321 322 for (size_t i = 0; i < list->numHwLayers; i++) { 323 hwc_layer_1_t const* layer = &list->hwLayers[i]; 324 private_handle_t *hnd = (private_handle_t *)layer->handle; 325 326 //reset stored yuv index 327 ctx->listStats[dpy].yuvIndices[i] = -1; 328 329 if(list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) { 330 continue; 331 //We disregard FB being skip for now! so the else if 332 } else if (isSkipLayer(&list->hwLayers[i])) { 333 ctx->listStats[dpy].skipCount++; 334 } else if (UNLIKELY(isYuvBuffer(hnd))) { 335 int& yuvCount = ctx->listStats[dpy].yuvCount; 336 ctx->listStats[dpy].yuvIndices[yuvCount] = i; 337 yuvCount++; 338 339 if(layer->transform & HWC_TRANSFORM_ROT_90) 340 ctx->mNeedsRotator = true; 341 } 342 if(layer->blending == HWC_BLENDING_PREMULT) 343 ctx->listStats[dpy].preMultipliedAlpha = true; 344 345 if(!ctx->listStats[dpy].needsAlphaScale) 346 ctx->listStats[dpy].needsAlphaScale = isAlphaScaled(layer); 347 } 348} 349 350 351static inline void calc_cut(float& leftCutRatio, float& topCutRatio, 352 float& rightCutRatio, float& bottomCutRatio, int orient) { 353 if(orient & HAL_TRANSFORM_FLIP_H) { 354 swap(leftCutRatio, rightCutRatio); 355 } 356 if(orient & HAL_TRANSFORM_FLIP_V) { 357 swap(topCutRatio, bottomCutRatio); 358 } 359 if(orient & HAL_TRANSFORM_ROT_90) { 360 //Anti clock swapping 361 float tmpCutRatio = leftCutRatio; 362 leftCutRatio = topCutRatio; 363 topCutRatio = rightCutRatio; 364 rightCutRatio = bottomCutRatio; 365 bottomCutRatio = tmpCutRatio; 366 } 367} 368 369bool isSecuring(hwc_context_t* ctx) { 370 if((ctx->mMDP.version < qdutils::MDSS_V5) && 371 (ctx->mMDP.version > qdutils::MDP_V3_0) && 372 ctx->mSecuring) { 373 return true; 374 } 375 return false; 376} 377 378bool isSecureModePolicy(int mdpVersion) { 379 if (mdpVersion < qdutils::MDSS_V5) 380 return true; 381 else 382 return false; 383} 384 385//Crops source buffer against destination and FB boundaries 386void calculate_crop_rects(hwc_rect_t& crop, hwc_rect_t& dst, 387 const hwc_rect_t& scissor, int orient) { 388 389 int& crop_l = crop.left; 390 int& crop_t = crop.top; 391 int& crop_r = crop.right; 392 int& crop_b = crop.bottom; 393 int crop_w = crop.right - crop.left; 394 int crop_h = crop.bottom - crop.top; 395 396 int& dst_l = dst.left; 397 int& dst_t = dst.top; 398 int& dst_r = dst.right; 399 int& dst_b = dst.bottom; 400 int dst_w = abs(dst.right - dst.left); 401 int dst_h = abs(dst.bottom - dst.top); 402 403 const int& sci_l = scissor.left; 404 const int& sci_t = scissor.top; 405 const int& sci_r = scissor.right; 406 const int& sci_b = scissor.bottom; 407 int sci_w = abs(sci_r - sci_l); 408 int sci_h = abs(sci_b - sci_t); 409 410 float leftCutRatio = 0.0f, rightCutRatio = 0.0f, topCutRatio = 0.0f, 411 bottomCutRatio = 0.0f; 412 413 if(dst_l < sci_l) { 414 leftCutRatio = (float)(sci_l - dst_l) / (float)dst_w; 415 dst_l = sci_l; 416 } 417 418 if(dst_r > sci_r) { 419 rightCutRatio = (float)(dst_r - sci_r) / (float)dst_w; 420 dst_r = sci_r; 421 } 422 423 if(dst_t < sci_t) { 424 topCutRatio = (float)(sci_t - dst_t) / (float)dst_h; 425 dst_t = sci_t; 426 } 427 428 if(dst_b > sci_b) { 429 bottomCutRatio = (float)(dst_b - sci_b) / (float)dst_h; 430 dst_b = sci_b; 431 } 432 433 calc_cut(leftCutRatio, topCutRatio, rightCutRatio, bottomCutRatio, orient); 434 crop_l += crop_w * leftCutRatio; 435 crop_t += crop_h * topCutRatio; 436 crop_r -= crop_w * rightCutRatio; 437 crop_b -= crop_h * bottomCutRatio; 438} 439 440void getNonWormholeRegion(hwc_display_contents_1_t* list, 441 hwc_rect_t& nwr) 442{ 443 uint32_t last = list->numHwLayers - 1; 444 hwc_rect_t fbDisplayFrame = list->hwLayers[last].displayFrame; 445 //Initiliaze nwr to first frame 446 nwr.left = list->hwLayers[0].displayFrame.left; 447 nwr.top = list->hwLayers[0].displayFrame.top; 448 nwr.right = list->hwLayers[0].displayFrame.right; 449 nwr.bottom = list->hwLayers[0].displayFrame.bottom; 450 451 for (uint32_t i = 1; i < last; i++) { 452 hwc_rect_t displayFrame = list->hwLayers[i].displayFrame; 453 nwr.left = min(nwr.left, displayFrame.left); 454 nwr.top = min(nwr.top, displayFrame.top); 455 nwr.right = max(nwr.right, displayFrame.right); 456 nwr.bottom = max(nwr.bottom, displayFrame.bottom); 457 } 458 459 //Intersect with the framebuffer 460 nwr.left = max(nwr.left, fbDisplayFrame.left); 461 nwr.top = max(nwr.top, fbDisplayFrame.top); 462 nwr.right = min(nwr.right, fbDisplayFrame.right); 463 nwr.bottom = min(nwr.bottom, fbDisplayFrame.bottom); 464 465} 466 467bool isExternalActive(hwc_context_t* ctx) { 468 return ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive; 469} 470 471void closeAcquireFds(hwc_display_contents_1_t* list) { 472 for(uint32_t i = 0; list && i < list->numHwLayers; i++) { 473 //Close the acquireFenceFds 474 //HWC_FRAMEBUFFER are -1 already by SF, rest we close. 475 if(list->hwLayers[i].acquireFenceFd >= 0) { 476 close(list->hwLayers[i].acquireFenceFd); 477 list->hwLayers[i].acquireFenceFd = -1; 478 } 479 } 480} 481 482int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy, 483 int fd) { 484 int ret = 0; 485 struct mdp_buf_sync data; 486 int acquireFd[MAX_NUM_LAYERS]; 487 int count = 0; 488 int releaseFd = -1; 489 int fbFd = -1; 490 memset(&data, 0, sizeof(data)); 491 bool swapzero = false; 492 data.flags = MDP_BUF_SYNC_FLAG_WAIT; 493 data.acq_fen_fd = acquireFd; 494 data.rel_fen_fd = &releaseFd; 495 char property[PROPERTY_VALUE_MAX]; 496 if(property_get("debug.egl.swapinterval", property, "1") > 0) { 497 if(atoi(property) == 0) 498 swapzero = true; 499 } 500 501 //Accumulate acquireFenceFds 502 for(uint32_t i = 0; i < list->numHwLayers; i++) { 503 if(list->hwLayers[i].compositionType == HWC_OVERLAY && 504 list->hwLayers[i].acquireFenceFd != -1) { 505 if(UNLIKELY(swapzero)) 506 acquireFd[count++] = -1; 507 else 508 acquireFd[count++] = list->hwLayers[i].acquireFenceFd; 509 } 510 if(list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) { 511 if(UNLIKELY(swapzero)) 512 acquireFd[count++] = -1; 513 else if(fd != -1) { 514 //set the acquireFD from fd - which is coming from c2d 515 acquireFd[count++] = fd; 516 // Buffer sync IOCTL should be async when using c2d fence is 517 // used 518 data.flags &= ~MDP_BUF_SYNC_FLAG_WAIT; 519 } else if(list->hwLayers[i].acquireFenceFd != -1) 520 acquireFd[count++] = list->hwLayers[i].acquireFenceFd; 521 } 522 } 523 524 data.acq_fen_fd_cnt = count; 525 fbFd = ctx->dpyAttr[dpy].fd; 526 //Waits for acquire fences, returns a release fence 527 if(LIKELY(!swapzero)) { 528 uint64_t start = systemTime(); 529 ret = ioctl(fbFd, MSMFB_BUFFER_SYNC, &data); 530 ALOGD_IF(HWC_UTILS_DEBUG, "%s: time taken for MSMFB_BUFFER_SYNC IOCTL = %d", 531 __FUNCTION__, (size_t) ns2ms(systemTime() - start)); 532 } 533 534 if(ret < 0) { 535 ALOGE("ioctl MSMFB_BUFFER_SYNC failed, err=%s", 536 strerror(errno)); 537 } 538 539 for(uint32_t i = 0; i < list->numHwLayers; i++) { 540 if(list->hwLayers[i].compositionType == HWC_OVERLAY || 541 list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) { 542 //Populate releaseFenceFds. 543 if(UNLIKELY(swapzero)) 544 list->hwLayers[i].releaseFenceFd = -1; 545 else 546 list->hwLayers[i].releaseFenceFd = dup(releaseFd); 547 } 548 } 549 550 if(fd >= 0) { 551 close(fd); 552 fd = -1; 553 } 554 555 if (ctx->mCopyBit[dpy]) 556 ctx->mCopyBit[dpy]->setReleaseFd(releaseFd); 557 if(UNLIKELY(swapzero)){ 558 list->retireFenceFd = -1; 559 close(releaseFd); 560 } else { 561 list->retireFenceFd = releaseFd; 562 } 563 564 return ret; 565} 566 567void trimLayer(hwc_context_t *ctx, const int& dpy, const int& transform, 568 hwc_rect_t& crop, hwc_rect_t& dst) { 569 int hw_w = ctx->dpyAttr[dpy].xres; 570 int hw_h = ctx->dpyAttr[dpy].yres; 571 if(dst.left < 0 || dst.top < 0 || 572 dst.right > hw_w || dst.bottom > hw_h) { 573 hwc_rect_t scissor = {0, 0, hw_w, hw_h }; 574 qhwc::calculate_crop_rects(crop, dst, scissor, transform); 575 } 576} 577 578void setMdpFlags(hwc_layer_1_t *layer, 579 ovutils::eMdpFlags &mdpFlags, 580 int rotDownscale) { 581 private_handle_t *hnd = (private_handle_t *)layer->handle; 582 MetaData_t *metadata = (MetaData_t *)hnd->base_metadata; 583 const int& transform = layer->transform; 584 585 if(layer->blending == HWC_BLENDING_PREMULT) { 586 ovutils::setMdpFlags(mdpFlags, 587 ovutils::OV_MDP_BLEND_FG_PREMULT); 588 } 589 590 if(isYuvBuffer(hnd)) { 591 if(isSecureBuffer(hnd)) { 592 ovutils::setMdpFlags(mdpFlags, 593 ovutils::OV_MDP_SECURE_OVERLAY_SESSION); 594 } 595 if(metadata && (metadata->operation & PP_PARAM_INTERLACED) && 596 metadata->interlaced) { 597 ovutils::setMdpFlags(mdpFlags, 598 ovutils::OV_MDP_DEINTERLACE); 599 } 600 //Pre-rotation will be used using rotator. 601 if(transform & HWC_TRANSFORM_ROT_90) { 602 ovutils::setMdpFlags(mdpFlags, 603 ovutils::OV_MDP_SOURCE_ROTATED_90); 604 } 605 } 606 607 //No 90 component and no rot-downscale then flips done by MDP 608 //If we use rot then it might as well do flips 609 if(!(layer->transform & HWC_TRANSFORM_ROT_90) && !rotDownscale) { 610 if(layer->transform & HWC_TRANSFORM_FLIP_H) { 611 ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_FLIP_H); 612 } 613 614 if(layer->transform & HWC_TRANSFORM_FLIP_V) { 615 ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_FLIP_V); 616 } 617 } 618 619 if(metadata && 620 ((metadata->operation & PP_PARAM_HSIC) 621 || (metadata->operation & PP_PARAM_IGC) 622 || (metadata->operation & PP_PARAM_SHARP2))) { 623 ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_PP_EN); 624 } 625} 626 627static inline int configRotator(Rotator *rot, const Whf& whf, 628 const eMdpFlags& mdpFlags, const eTransform& orient, 629 const int& downscale) { 630 rot->setSource(whf); 631 rot->setFlags(mdpFlags); 632 rot->setTransform(orient); 633 rot->setDownscale(downscale); 634 if(!rot->commit()) return -1; 635 return 0; 636} 637 638static inline int configMdp(Overlay *ov, const PipeArgs& parg, 639 const eTransform& orient, const hwc_rect_t& crop, 640 const hwc_rect_t& pos, const MetaData_t *metadata, 641 const eDest& dest) { 642 ov->setSource(parg, dest); 643 ov->setTransform(orient, dest); 644 645 int crop_w = crop.right - crop.left; 646 int crop_h = crop.bottom - crop.top; 647 Dim dcrop(crop.left, crop.top, crop_w, crop_h); 648 ov->setCrop(dcrop, dest); 649 650 int posW = pos.right - pos.left; 651 int posH = pos.bottom - pos.top; 652 Dim position(pos.left, pos.top, posW, posH); 653 ov->setPosition(position, dest); 654 655 if (metadata) 656 ov->setVisualParams(*metadata, dest); 657 658 if (!ov->commit(dest)) { 659 return -1; 660 } 661 return 0; 662} 663 664static inline void updateSource(eTransform& orient, Whf& whf, 665 hwc_rect_t& crop) { 666 Dim srcCrop(crop.left, crop.top, 667 crop.right - crop.left, 668 crop.bottom - crop.top); 669 //getMdpOrient will switch the flips if the source is 90 rotated. 670 //Clients in Android dont factor in 90 rotation while deciding the flip. 671 orient = static_cast<eTransform>(ovutils::getMdpOrient(orient)); 672 preRotateSource(orient, whf, srcCrop); 673 crop.left = srcCrop.x; 674 crop.top = srcCrop.y; 675 crop.right = srcCrop.x + srcCrop.w; 676 crop.bottom = srcCrop.y + srcCrop.h; 677} 678 679int configureLowRes(hwc_context_t *ctx, hwc_layer_1_t *layer, 680 const int& dpy, eMdpFlags& mdpFlags, const eZorder& z, 681 const eIsFg& isFg, const eDest& dest, Rotator **rot) { 682 683 private_handle_t *hnd = (private_handle_t *)layer->handle; 684 if(!hnd) { 685 ALOGE("%s: layer handle is NULL", __FUNCTION__); 686 return -1; 687 } 688 689 MetaData_t *metadata = (MetaData_t *)hnd->base_metadata; 690 691 hwc_rect_t crop = layer->sourceCrop; 692 hwc_rect_t dst = layer->displayFrame; 693 int transform = layer->transform; 694 eTransform orient = static_cast<eTransform>(transform); 695 int downscale = 0; 696 int rotFlags = ovutils::ROT_FLAGS_NONE; 697 Whf whf(hnd->width, hnd->height, 698 getMdpFormat(hnd->format), hnd->size); 699 700 if(isYuvBuffer(hnd) && ctx->mMDP.version >= qdutils::MDP_V4_2 && 701 ctx->mMDP.version < qdutils::MDSS_V5) { 702 downscale = getDownscaleFactor( 703 crop.right - crop.left, 704 crop.bottom - crop.top, 705 dst.right - dst.left, 706 dst.bottom - dst.top); 707 if(downscale) { 708 rotFlags = ROT_DOWNSCALE_ENABLED; 709 } 710 } 711 712 setMdpFlags(layer, mdpFlags, downscale); 713 trimLayer(ctx, dpy, transform, crop, dst); 714 715 if(isYuvBuffer(hnd) && //if 90 component or downscale, use rot 716 ((transform & HWC_TRANSFORM_ROT_90) || downscale)) { 717 *rot = ctx->mRotMgr->getNext(); 718 if(*rot == NULL) return -1; 719 //Configure rotator for pre-rotation 720 if(configRotator(*rot, whf, mdpFlags, orient, downscale) < 0) 721 return -1; 722 whf.format = (*rot)->getDstFormat(); 723 updateSource(orient, whf, crop); 724 rotFlags |= ovutils::ROT_PREROTATED; 725 } 726 727 //For the mdp, since either we are pre-rotating or MDP does flips 728 orient = OVERLAY_TRANSFORM_0; 729 transform = 0; 730 731 PipeArgs parg(mdpFlags, whf, z, isFg, static_cast<eRotFlags>(rotFlags)); 732 if(configMdp(ctx->mOverlay, parg, orient, crop, dst, metadata, dest) < 0) { 733 ALOGE("%s: commit failed for low res panel", __FUNCTION__); 734 return -1; 735 } 736 return 0; 737} 738 739int configureHighRes(hwc_context_t *ctx, hwc_layer_1_t *layer, 740 const int& dpy, eMdpFlags& mdpFlagsL, const eZorder& z, 741 const eIsFg& isFg, const eDest& lDest, const eDest& rDest, 742 Rotator **rot) { 743 private_handle_t *hnd = (private_handle_t *)layer->handle; 744 if(!hnd) { 745 ALOGE("%s: layer handle is NULL", __FUNCTION__); 746 return -1; 747 } 748 749 MetaData_t *metadata = (MetaData_t *)hnd->base_metadata; 750 751 int hw_w = ctx->dpyAttr[dpy].xres; 752 int hw_h = ctx->dpyAttr[dpy].yres; 753 hwc_rect_t crop = layer->sourceCrop; 754 hwc_rect_t dst = layer->displayFrame; 755 int transform = layer->transform; 756 eTransform orient = static_cast<eTransform>(transform); 757 const int downscale = 0; 758 int rotFlags = ROT_FLAGS_NONE; 759 760 Whf whf(hnd->width, hnd->height, 761 getMdpFormat(hnd->format), hnd->size); 762 763 setMdpFlags(layer, mdpFlagsL); 764 trimLayer(ctx, dpy, transform, crop, dst); 765 766 if(isYuvBuffer(hnd) && (transform & HWC_TRANSFORM_ROT_90)) { 767 (*rot) = ctx->mRotMgr->getNext(); 768 if((*rot) == NULL) return -1; 769 //Configure rotator for pre-rotation 770 if(configRotator(*rot, whf, mdpFlagsL, orient, downscale) < 0) 771 return -1; 772 whf.format = (*rot)->getDstFormat(); 773 updateSource(orient, whf, crop); 774 rotFlags |= ROT_PREROTATED; 775 } 776 777 eMdpFlags mdpFlagsR = mdpFlagsL; 778 setMdpFlags(mdpFlagsR, OV_MDSS_MDP_RIGHT_MIXER); 779 780 hwc_rect_t tmp_cropL, tmp_dstL; 781 hwc_rect_t tmp_cropR, tmp_dstR; 782 783 if(lDest != OV_INVALID) { 784 tmp_cropL = crop; 785 tmp_dstL = dst; 786 hwc_rect_t scissor = {0, 0, hw_w/2, hw_h }; 787 qhwc::calculate_crop_rects(tmp_cropL, tmp_dstL, scissor, 0); 788 } 789 if(rDest != OV_INVALID) { 790 tmp_cropR = crop; 791 tmp_dstR = dst; 792 hwc_rect_t scissor = {hw_w/2, 0, hw_w, hw_h }; 793 qhwc::calculate_crop_rects(tmp_cropR, tmp_dstR, scissor, 0); 794 } 795 796 //When buffer is flipped, contents of mixer config also needs to swapped. 797 //Not needed if the layer is confined to one half of the screen. 798 //If rotator has been used then it has also done the flips, so ignore them. 799 if((orient & OVERLAY_TRANSFORM_FLIP_V) && lDest != OV_INVALID 800 && rDest != OV_INVALID && rot == NULL) { 801 hwc_rect_t new_cropR; 802 new_cropR.left = tmp_cropL.left; 803 new_cropR.right = new_cropR.left + (tmp_cropR.right - tmp_cropR.left); 804 805 hwc_rect_t new_cropL; 806 new_cropL.left = new_cropR.right; 807 new_cropL.right = tmp_cropR.right; 808 809 tmp_cropL.left = new_cropL.left; 810 tmp_cropL.right = new_cropL.right; 811 812 tmp_cropR.left = new_cropR.left; 813 tmp_cropR.right = new_cropR.right; 814 815 } 816 817 //For the mdp, since either we are pre-rotating or MDP does flips 818 orient = OVERLAY_TRANSFORM_0; 819 transform = 0; 820 821 //configure left mixer 822 if(lDest != OV_INVALID) { 823 PipeArgs pargL(mdpFlagsL, whf, z, isFg, 824 static_cast<eRotFlags>(rotFlags)); 825 if(configMdp(ctx->mOverlay, pargL, orient, 826 tmp_cropL, tmp_dstL, metadata, lDest) < 0) { 827 ALOGE("%s: commit failed for left mixer config", __FUNCTION__); 828 return -1; 829 } 830 } 831 832 //configure right mixer 833 if(rDest != OV_INVALID) { 834 PipeArgs pargR(mdpFlagsR, whf, z, isFg, 835 static_cast<eRotFlags>(rotFlags)); 836 tmp_dstR.right = tmp_dstR.right - tmp_dstR.left; 837 tmp_dstR.left = 0; 838 if(configMdp(ctx->mOverlay, pargR, orient, 839 tmp_cropR, tmp_dstR, metadata, rDest) < 0) { 840 ALOGE("%s: commit failed for right mixer config", __FUNCTION__); 841 return -1; 842 } 843 } 844 845 return 0; 846} 847 848void LayerCache::resetLayerCache(int num) { 849 for(uint32_t i = 0; i < MAX_NUM_LAYERS; i++) { 850 hnd[i] = NULL; 851 } 852 numHwLayers = num; 853} 854 855void LayerCache::updateLayerCache(hwc_display_contents_1_t* list) { 856 857 int numFbLayers = 0; 858 int numCacheableLayers = 0; 859 860 canUseLayerCache = false; 861 //Bail if geometry changed or num of layers changed 862 if(list->flags & HWC_GEOMETRY_CHANGED || 863 list->numHwLayers != numHwLayers ) { 864 resetLayerCache(list->numHwLayers); 865 return; 866 } 867 868 for(uint32_t i = 0; i < list->numHwLayers; i++) { 869 //Bail on skip layers 870 if(list->hwLayers[i].flags & HWC_SKIP_LAYER) { 871 resetLayerCache(list->numHwLayers); 872 return; 873 } 874 875 if(list->hwLayers[i].compositionType == HWC_FRAMEBUFFER) { 876 numFbLayers++; 877 if(hnd[i] == NULL) { 878 hnd[i] = list->hwLayers[i].handle; 879 } else if (hnd[i] == 880 list->hwLayers[i].handle) { 881 numCacheableLayers++; 882 } else { 883 hnd[i] = NULL; 884 return; 885 } 886 } else { 887 hnd[i] = NULL; 888 } 889 } 890 if(numFbLayers == numCacheableLayers) 891 canUseLayerCache = true; 892 893 //XXX: The marking part is separate, if MDP comp wants 894 // to use it in the future. Right now getting MDP comp 895 // to use this is more trouble than it is worth. 896 markCachedLayersAsOverlay(list); 897} 898 899void LayerCache::markCachedLayersAsOverlay(hwc_display_contents_1_t* list) { 900 //This optimization only works if ALL the layer handles 901 //that were on the framebuffer didn't change. 902 if(canUseLayerCache){ 903 for(uint32_t i = 0; i < list->numHwLayers; i++) { 904 if (list->hwLayers[i].handle && 905 list->hwLayers[i].handle == hnd[i] && 906 list->hwLayers[i].compositionType != HWC_FRAMEBUFFER_TARGET) 907 { 908 list->hwLayers[i].compositionType = HWC_OVERLAY; 909 } 910 } 911 } 912} 913 914};//namespace qhwc 915