// Configure bool FBUpdateSplit::configure(hwc_context_t *ctx, hwc_display_contents_1 *list, hwc_rect_t fbUpdatingRect, int fbZorder) { bool ret = false; hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1]; if (LIKELY(ctx->mOverlay)) { /* External only layer present */ int extOnlyLayerIndex = ctx->listStats[mDpy].extOnlyLayerIndex; if(extOnlyLayerIndex != -1) { layer = &list->hwLayers[extOnlyLayerIndex]; layer->compositionType = HWC_OVERLAY; } ovutils::Whf info(mAlignedFBWidth, mAlignedFBHeight, ovutils::getMdpFormat(HAL_PIXEL_FORMAT_RGBA_8888, mTileEnabled)); overlay::Overlay& ov = *(ctx->mOverlay); ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_BLEND_FG_PREMULT; ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder); ovutils::eTransform orient = static_cast<ovutils::eTransform>(layer->transform); const int hw_w = ctx->dpyAttr[mDpy].xres; const int hw_h = ctx->dpyAttr[mDpy].yres; const int lSplit = getLeftSplit(ctx, mDpy); mDestLeft = ovutils::OV_INVALID; mDestRight = ovutils::OV_INVALID; hwc_rect_t sourceCrop = fbUpdatingRect; hwc_rect_t displayFrame = fbUpdatingRect; ret = true; Overlay::PipeSpecs pipeSpecs; pipeSpecs.formatClass = Overlay::FORMAT_RGB; pipeSpecs.needsScaling = qhwc::needsScaling(layer); pipeSpecs.dpy = mDpy; pipeSpecs.fb = true; /* Configure left pipe */ if(displayFrame.left < lSplit) { pipeSpecs.mixer = Overlay::MIXER_LEFT; ovutils::eDest destL = ov.getPipe(pipeSpecs); if(destL == ovutils::OV_INVALID) { //None available ALOGE("%s: No pipes available to configure fb for dpy %d's left" " mixer", __FUNCTION__, mDpy); return false; } mDestLeft = destL; //XXX: FB layer plane alpha is currently sent as zero from //surfaceflinger ovutils::PipeArgs pargL(mdpFlags, info, zOrder, ovutils::IS_FG_OFF, ovutils::ROT_FLAGS_NONE, ovutils::DEFAULT_PLANE_ALPHA, (ovutils::eBlending) getBlending(layer->blending)); hwc_rect_t cropL = sourceCrop; hwc_rect_t dstL = displayFrame; hwc_rect_t scissorL = {0, 0, lSplit, hw_h }; qhwc::calculate_crop_rects(cropL, dstL, scissorL, 0); if (configMdp(ctx->mOverlay, pargL, orient, cropL, dstL, NULL, destL)< 0) { ALOGE("%s: configMdp fails for left FB", __FUNCTION__); ret = false; } } /* Configure right pipe */ if(displayFrame.right > lSplit) { pipeSpecs.mixer = Overlay::MIXER_RIGHT; ovutils::eDest destR = ov.getPipe(pipeSpecs); if(destR == ovutils::OV_INVALID) { //None available ALOGE("%s: No pipes available to configure fb for dpy %d's" " right mixer", __FUNCTION__, mDpy); return false; } mDestRight = destR; ovutils::eMdpFlags mdpFlagsR = mdpFlags; ovutils::setMdpFlags(mdpFlagsR, ovutils::OV_MDSS_MDP_RIGHT_MIXER); //XXX: FB layer plane alpha is currently sent as zero from //surfaceflinger ovutils::PipeArgs pargR(mdpFlagsR, info, zOrder, ovutils::IS_FG_OFF, ovutils::ROT_FLAGS_NONE, ovutils::DEFAULT_PLANE_ALPHA, (ovutils::eBlending) getBlending(layer->blending)); hwc_rect_t cropR = sourceCrop; hwc_rect_t dstR = displayFrame; hwc_rect_t scissorR = {lSplit, 0, hw_w, hw_h }; qhwc::calculate_crop_rects(cropR, dstR, scissorR, 0); dstR.left -= lSplit; dstR.right -= lSplit; if (configMdp(ctx->mOverlay, pargR, orient, cropR, dstR, NULL, destR) < 0) { ALOGE("%s: configMdp fails for right FB", __FUNCTION__); ret = false; } } } return ret; }
int allocate_overlay(int fd, GGLSurface gr_fb[]) { int ret = 0; if (!overlay_supported) return -EINVAL; if (!isDisplaySplit()) { // Check if overlay is already allocated if (MSMFB_NEW_REQUEST == overlayL_id) { struct mdp_overlay overlayL; memset(&overlayL, 0 , sizeof (struct mdp_overlay)); /* Fill Overlay Data */ overlayL.src.width = ALIGN(gr_fb[0].width, 32); overlayL.src.height = gr_fb[0].height; overlayL.src.format = map_mdp_pixel_format(); overlayL.src_rect.w = gr_fb[0].width; overlayL.src_rect.h = gr_fb[0].height; overlayL.dst_rect.w = gr_fb[0].width; overlayL.dst_rect.h = gr_fb[0].height; overlayL.alpha = 0xFF; overlayL.transp_mask = MDP_TRANSP_NOP; overlayL.id = MSMFB_NEW_REQUEST; ret = ioctl(fd, MSMFB_OVERLAY_SET, &overlayL); if (ret < 0) { perror("Overlay Set Failed"); return ret; } overlayL_id = overlayL.id; } } else { float xres = getFbXres(); int lSplit = getLeftSplit(); float lSplitRatio = lSplit / xres; float lCropWidth = gr_fb[0].width * lSplitRatio; int lWidth = lSplit; int rWidth = gr_fb[0].width - lSplit; int height = gr_fb[0].height; if (MSMFB_NEW_REQUEST == overlayL_id) { struct mdp_overlay overlayL; memset(&overlayL, 0 , sizeof (struct mdp_overlay)); /* Fill OverlayL Data */ overlayL.src.width = ALIGN(gr_fb[0].width, 32); overlayL.src.height = gr_fb[0].height; overlayL.src.format = map_mdp_pixel_format(); overlayL.src_rect.x = 0; overlayL.src_rect.y = 0; overlayL.src_rect.w = lCropWidth; overlayL.src_rect.h = gr_fb[0].height; overlayL.dst_rect.x = 0; overlayL.dst_rect.y = 0; overlayL.dst_rect.w = lWidth; overlayL.dst_rect.h = height; overlayL.alpha = 0xFF; overlayL.transp_mask = MDP_TRANSP_NOP; overlayL.id = MSMFB_NEW_REQUEST; ret = ioctl(fd, MSMFB_OVERLAY_SET, &overlayL); if (ret < 0) { perror("OverlayL Set Failed"); return ret; } overlayL_id = overlayL.id; } if (MSMFB_NEW_REQUEST == overlayR_id) { struct mdp_overlay overlayR; memset(&overlayR, 0 , sizeof (struct mdp_overlay)); /* Fill OverlayR Data */ overlayR.src.width = ALIGN(gr_fb[0].width, 32); overlayR.src.height = gr_fb[0].height; overlayR.src.format = map_mdp_pixel_format(); overlayR.src_rect.x = lCropWidth; overlayR.src_rect.y = 0; overlayR.src_rect.w = gr_fb[0].width - lCropWidth; overlayR.src_rect.h = gr_fb[0].height; overlayR.dst_rect.x = 0; overlayR.dst_rect.y = 0; overlayR.dst_rect.w = rWidth; overlayR.dst_rect.h = height; overlayR.alpha = 0xFF; overlayR.flags = MDSS_MDP_RIGHT_MIXER; overlayR.transp_mask = MDP_TRANSP_NOP; overlayR.id = MSMFB_NEW_REQUEST; ret = ioctl(fd, MSMFB_OVERLAY_SET, &overlayR); if (ret < 0) { perror("OverlayR Set Failed"); return ret; } overlayR_id = overlayR.id; } } return 0; }