If the left split is not published by the driver then the default should be even split. This was missing from the configuration in utils. This is already taken care of in framebuffer configuration and mdp composition. Change-Id: I3db44481fd791809146752ddff56420dcbe89fb4
370 lines
13 KiB
C++
370 lines
13 KiB
C++
/*
|
|
* Copyright (C) 2010 The Android Open Source Project
|
|
* Copyright (C) 2012, The Linux Foundation. All rights reserved.
|
|
*
|
|
* Not a Contribution, Apache license notifications and license are
|
|
* retained for attribution purposes only.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#define DEBUG_FBUPDATE 0
|
|
#include <cutils/properties.h>
|
|
#include <gralloc_priv.h>
|
|
#include <overlay.h>
|
|
#include <overlayRotator.h>
|
|
#include "hwc_fbupdate.h"
|
|
#include "mdp_version.h"
|
|
#include "external.h"
|
|
|
|
using namespace qdutils;
|
|
using namespace overlay;
|
|
using overlay::Rotator;
|
|
|
|
namespace qhwc {
|
|
|
|
namespace ovutils = overlay::utils;
|
|
|
|
IFBUpdate* IFBUpdate::getObject(const int& width, const int& rightSplit,
|
|
const int& dpy) {
|
|
if(width > MAX_DISPLAY_DIM || rightSplit) {
|
|
return new FBUpdateHighRes(dpy);
|
|
}
|
|
return new FBUpdateLowRes(dpy);
|
|
}
|
|
|
|
inline void IFBUpdate::reset() {
|
|
mModeOn = false;
|
|
mRot = NULL;
|
|
}
|
|
|
|
//================= Low res====================================
|
|
FBUpdateLowRes::FBUpdateLowRes(const int& dpy): IFBUpdate(dpy) {}
|
|
|
|
inline void FBUpdateLowRes::reset() {
|
|
IFBUpdate::reset();
|
|
mDest = ovutils::OV_INVALID;
|
|
}
|
|
|
|
bool FBUpdateLowRes::prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
|
|
int fbZorder) {
|
|
if(!ctx->mMDP.hasOverlay) {
|
|
ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays",
|
|
__FUNCTION__);
|
|
return false;
|
|
}
|
|
mModeOn = configure(ctx, list, fbZorder);
|
|
return mModeOn;
|
|
}
|
|
|
|
// Configure
|
|
bool FBUpdateLowRes::configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
|
|
int fbZorder) {
|
|
bool ret = false;
|
|
hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
|
|
if (LIKELY(ctx->mOverlay)) {
|
|
int extOnlyLayerIndex = ctx->listStats[mDpy].extOnlyLayerIndex;
|
|
// ext only layer present..
|
|
if(extOnlyLayerIndex != -1) {
|
|
layer = &list->hwLayers[extOnlyLayerIndex];
|
|
layer->compositionType = HWC_OVERLAY;
|
|
}
|
|
overlay::Overlay& ov = *(ctx->mOverlay);
|
|
private_handle_t *hnd = (private_handle_t *)layer->handle;
|
|
ovutils::Whf info(hnd->width, hnd->height,
|
|
ovutils::getMdpFormat(hnd->format), hnd->size);
|
|
|
|
//Request a pipe
|
|
ovutils::eMdpPipeType type = ovutils::OV_MDP_PIPE_ANY;
|
|
if(qdutils::MDPVersion::getInstance().is8x26() && mDpy) {
|
|
//For 8x26 external always use DMA pipe
|
|
type = ovutils::OV_MDP_PIPE_DMA;
|
|
}
|
|
ovutils::eDest dest = ov.nextPipe(type, mDpy, Overlay::MIXER_DEFAULT);
|
|
if(dest == ovutils::OV_INVALID) { //None available
|
|
ALOGE("%s: No pipes available to configure fb for dpy %d",
|
|
__FUNCTION__, mDpy);
|
|
return false;
|
|
}
|
|
mDest = dest;
|
|
|
|
if((mDpy && ctx->deviceOrientation) &&
|
|
ctx->listStats[mDpy].isDisplayAnimating) {
|
|
fbZorder = 0;
|
|
}
|
|
|
|
ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_BLEND_FG_PREMULT;
|
|
ovutils::eIsFg isFg = ovutils::IS_FG_OFF;
|
|
ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder);
|
|
|
|
hwc_rect_t sourceCrop = layer->sourceCrop;
|
|
hwc_rect_t displayFrame = layer->displayFrame;
|
|
int transform = layer->transform;
|
|
int fbWidth = ctx->dpyAttr[mDpy].xres;
|
|
int fbHeight = ctx->dpyAttr[mDpy].yres;
|
|
int rotFlags = ovutils::ROT_FLAGS_NONE;
|
|
|
|
ovutils::eTransform orient =
|
|
static_cast<ovutils::eTransform>(transform);
|
|
if(mDpy && ctx->mExtOrientation) {
|
|
// If there is a external orientation set, use that
|
|
transform = ctx->mExtOrientation;
|
|
orient = static_cast<ovutils::eTransform >(ctx->mExtOrientation);
|
|
}
|
|
|
|
// Do not use getNonWormholeRegion() function to calculate the
|
|
// sourceCrop during animation on external display and
|
|
// Dont do wormhole calculation when extorientation is set on External
|
|
if(ctx->listStats[mDpy].isDisplayAnimating && mDpy) {
|
|
sourceCrop = layer->displayFrame;
|
|
displayFrame = sourceCrop;
|
|
} else if((!mDpy || (mDpy && !ctx->mExtOrientation))
|
|
&& extOnlyLayerIndex == -1) {
|
|
if(!qdutils::MDPVersion::getInstance().is8x26()) {
|
|
getNonWormholeRegion(list, sourceCrop);
|
|
displayFrame = sourceCrop;
|
|
}
|
|
}
|
|
ovutils::Dim dpos(displayFrame.left,
|
|
displayFrame.top,
|
|
displayFrame.right - displayFrame.left,
|
|
displayFrame.bottom - displayFrame.top);
|
|
|
|
if(mDpy && !qdutils::MDPVersion::getInstance().is8x26()) {
|
|
// Get Aspect Ratio for external
|
|
getAspectRatioPosition(ctx, mDpy, ctx->mExtOrientation, dpos.x,
|
|
dpos.y, dpos.w, dpos.h);
|
|
// Calculate the actionsafe dimensions for External(dpy = 1 or 2)
|
|
getActionSafePosition(ctx, mDpy, dpos.x, dpos.y, dpos.w, dpos.h);
|
|
// Convert dim to hwc_rect_t
|
|
displayFrame.left = dpos.x;
|
|
displayFrame.top = dpos.y;
|
|
displayFrame.right = dpos.w + displayFrame.left;
|
|
displayFrame.bottom = dpos.h + displayFrame.top;
|
|
}
|
|
setMdpFlags(layer, mdpFlags, 0, transform);
|
|
// For External use rotator if there is a rotation value set
|
|
if(mDpy && (ctx->mExtOrientation & HWC_TRANSFORM_ROT_90)) {
|
|
mRot = ctx->mRotMgr->getNext();
|
|
if(mRot == NULL) return -1;
|
|
//Configure rotator for pre-rotation
|
|
if(configRotator(mRot, info, sourceCrop, mdpFlags, orient, 0) < 0) {
|
|
ALOGE("%s: configRotator Failed!", __FUNCTION__);
|
|
mRot = NULL;
|
|
return -1;
|
|
}
|
|
info.format = (mRot)->getDstFormat();
|
|
updateSource(orient, info, sourceCrop);
|
|
rotFlags |= ovutils::ROT_PREROTATED;
|
|
}
|
|
//For the mdp, since either we are pre-rotating or MDP does flips
|
|
orient = ovutils::OVERLAY_TRANSFORM_0;
|
|
transform = 0;
|
|
ovutils::PipeArgs parg(mdpFlags, info, zOrder, isFg,
|
|
static_cast<ovutils::eRotFlags>(rotFlags));
|
|
ret = true;
|
|
if(configMdp(ctx->mOverlay, parg, orient, sourceCrop, displayFrame,
|
|
NULL, mDest) < 0) {
|
|
ALOGE("%s: configMdp failed for dpy %d", __FUNCTION__, mDpy);
|
|
ret = false;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
bool FBUpdateLowRes::draw(hwc_context_t *ctx, private_handle_t *hnd)
|
|
{
|
|
if(!mModeOn) {
|
|
return true;
|
|
}
|
|
bool ret = true;
|
|
overlay::Overlay& ov = *(ctx->mOverlay);
|
|
ovutils::eDest dest = mDest;
|
|
int fd = hnd->fd;
|
|
uint32_t offset = hnd->offset;
|
|
if(mRot) {
|
|
if(!mRot->queueBuffer(fd, offset))
|
|
return false;
|
|
fd = mRot->getDstMemId();
|
|
offset = mRot->getDstOffset();
|
|
}
|
|
if (!ov.queueBuffer(fd, offset, dest)) {
|
|
ALOGE("%s: queueBuffer failed for FBUpdate", __FUNCTION__);
|
|
ret = false;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
//================= High res====================================
|
|
FBUpdateHighRes::FBUpdateHighRes(const int& dpy): IFBUpdate(dpy) {}
|
|
|
|
inline void FBUpdateHighRes::reset() {
|
|
IFBUpdate::reset();
|
|
mDestLeft = ovutils::OV_INVALID;
|
|
mDestRight = ovutils::OV_INVALID;
|
|
mRot = NULL;
|
|
}
|
|
|
|
bool FBUpdateHighRes::prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
|
|
int fbZorder) {
|
|
if(!ctx->mMDP.hasOverlay) {
|
|
ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays",
|
|
__FUNCTION__);
|
|
return false;
|
|
}
|
|
ALOGD_IF(DEBUG_FBUPDATE, "%s, mModeOn = %d", __FUNCTION__, mModeOn);
|
|
mModeOn = configure(ctx, list, fbZorder);
|
|
return mModeOn;
|
|
}
|
|
|
|
// Configure
|
|
bool FBUpdateHighRes::configure(hwc_context_t *ctx,
|
|
hwc_display_contents_1 *list, int fbZorder) {
|
|
bool ret = false;
|
|
hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
|
|
if (LIKELY(ctx->mOverlay)) {
|
|
int extOnlyLayerIndex = ctx->listStats[mDpy].extOnlyLayerIndex;
|
|
// ext only layer present..
|
|
if(extOnlyLayerIndex != -1) {
|
|
layer = &list->hwLayers[extOnlyLayerIndex];
|
|
layer->compositionType = HWC_OVERLAY;
|
|
}
|
|
overlay::Overlay& ov = *(ctx->mOverlay);
|
|
private_handle_t *hnd = (private_handle_t *)layer->handle;
|
|
ovutils::Whf info(hnd->width, hnd->height,
|
|
ovutils::getMdpFormat(hnd->format), hnd->size);
|
|
|
|
//Request left pipe
|
|
ovutils::eDest destL = ov.nextPipe(ovutils::OV_MDP_PIPE_ANY, mDpy,
|
|
Overlay::MIXER_LEFT);
|
|
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;
|
|
}
|
|
//Request right pipe
|
|
ovutils::eDest destR = ov.nextPipe(ovutils::OV_MDP_PIPE_ANY, mDpy,
|
|
Overlay::MIXER_RIGHT);
|
|
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;
|
|
}
|
|
|
|
mDestLeft = destL;
|
|
mDestRight = destR;
|
|
|
|
ovutils::eMdpFlags mdpFlagsL = ovutils::OV_MDP_BLEND_FG_PREMULT;
|
|
|
|
ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder);
|
|
|
|
ovutils::PipeArgs pargL(mdpFlagsL,
|
|
info,
|
|
zOrder,
|
|
ovutils::IS_FG_OFF,
|
|
ovutils::ROT_FLAGS_NONE);
|
|
ov.setSource(pargL, destL);
|
|
|
|
ovutils::eMdpFlags mdpFlagsR = mdpFlagsL;
|
|
ovutils::setMdpFlags(mdpFlagsR, ovutils::OV_MDSS_MDP_RIGHT_MIXER);
|
|
ovutils::PipeArgs pargR(mdpFlagsR,
|
|
info,
|
|
zOrder,
|
|
ovutils::IS_FG_OFF,
|
|
ovutils::ROT_FLAGS_NONE);
|
|
ov.setSource(pargR, destR);
|
|
|
|
hwc_rect_t sourceCrop = layer->sourceCrop;
|
|
hwc_rect_t displayFrame = layer->displayFrame;
|
|
|
|
const float xres = ctx->dpyAttr[mDpy].xres;
|
|
const int lSplit = getLeftSplit(ctx, mDpy);
|
|
const float lSplitRatio = lSplit / xres;
|
|
const float lCropWidth =
|
|
(sourceCrop.right - sourceCrop.left) * lSplitRatio;
|
|
|
|
ovutils::Dim dcropL(
|
|
sourceCrop.left,
|
|
sourceCrop.top,
|
|
lCropWidth,
|
|
sourceCrop.bottom - sourceCrop.top);
|
|
|
|
ovutils::Dim dcropR(
|
|
sourceCrop.left + lCropWidth,
|
|
sourceCrop.top,
|
|
(sourceCrop.right - sourceCrop.left) - lCropWidth,
|
|
sourceCrop.bottom - sourceCrop.top);
|
|
|
|
ov.setCrop(dcropL, destL);
|
|
ov.setCrop(dcropR, destR);
|
|
|
|
int transform = layer->transform;
|
|
ovutils::eTransform orient =
|
|
static_cast<ovutils::eTransform>(transform);
|
|
ov.setTransform(orient, destL);
|
|
ov.setTransform(orient, destR);
|
|
|
|
const int lWidth = (lSplit - displayFrame.left);
|
|
const int rWidth = (displayFrame.right - lSplit);
|
|
const int height = displayFrame.bottom - displayFrame.top;
|
|
|
|
ovutils::Dim dposL(displayFrame.left,
|
|
displayFrame.top,
|
|
lWidth,
|
|
height);
|
|
ov.setPosition(dposL, destL);
|
|
|
|
ovutils::Dim dposR(0,
|
|
displayFrame.top,
|
|
rWidth,
|
|
height);
|
|
ov.setPosition(dposR, destR);
|
|
|
|
ret = true;
|
|
if (!ov.commit(destL)) {
|
|
ALOGE("%s: commit fails for left", __FUNCTION__);
|
|
ret = false;
|
|
}
|
|
if (!ov.commit(destR)) {
|
|
ALOGE("%s: commit fails for right", __FUNCTION__);
|
|
ret = false;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
bool FBUpdateHighRes::draw(hwc_context_t *ctx, private_handle_t *hnd)
|
|
{
|
|
if(!mModeOn) {
|
|
return true;
|
|
}
|
|
bool ret = true;
|
|
overlay::Overlay& ov = *(ctx->mOverlay);
|
|
ovutils::eDest destL = mDestLeft;
|
|
ovutils::eDest destR = mDestRight;
|
|
if (!ov.queueBuffer(hnd->fd, hnd->offset, destL)) {
|
|
ALOGE("%s: queue failed for left of dpy = %d",
|
|
__FUNCTION__, mDpy);
|
|
ret = false;
|
|
}
|
|
if (!ov.queueBuffer(hnd->fd, hnd->offset, destR)) {
|
|
ALOGE("%s: queue failed for right of dpy = %d",
|
|
__FUNCTION__, mDpy);
|
|
ret = false;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
}; //namespace qhwc
|