hwc/overlay: Video on 4k2k external, 4k2k rotation.

-Add support for Video via overlay on 4k2k external panel.
-Add support for rotating videos on 4k2k panels. We use
pre-rotation in hwc to rotate a video into a single buffer,
irrespective of panel size. Then this buffer is fed to MDP.
Rotator objects are managed by the new RotMgr.
-Cleaup mdpcomp and overlay.

Change-Id: Ifb08534747e8e18b6c58dd8a3e1a9947409100f1
This commit is contained in:
Saurabh Shah
2013-02-26 10:15:15 -08:00
committed by Gerrit - the friendly Code Review server
parent 893a34a75b
commit acf102021a
22 changed files with 1005 additions and 1274 deletions

View File

@@ -27,6 +27,7 @@
#include <utils/Trace.h> #include <utils/Trace.h>
#include <overlay.h> #include <overlay.h>
#include <overlayRotator.h>
#include <fb_priv.h> #include <fb_priv.h>
#include <mdp_version.h> #include <mdp_version.h>
#include "hwc_utils.h" #include "hwc_utils.h"
@@ -100,11 +101,11 @@ static void reset(hwc_context_t *ctx, int numDisplays,
if(ctx->mFBUpdate[i]) if(ctx->mFBUpdate[i])
ctx->mFBUpdate[i]->reset(); ctx->mFBUpdate[i]->reset();
if(ctx->mVidOv[i])
ctx->mVidOv[i]->reset();
if(ctx->mCopyBit[i]) if(ctx->mCopyBit[i])
ctx->mCopyBit[i]->reset(); ctx->mCopyBit[i]->reset();
} }
VideoOverlay::reset();
} }
//clear prev layer prop flags and realloc for current frame //clear prev layer prop flags and realloc for current frame
@@ -135,7 +136,7 @@ static int hwc_prepare_primary(hwc_composer_device_1 *dev,
int ret = ctx->mMDPComp->prepare(ctx, list); int ret = ctx->mMDPComp->prepare(ctx, list);
if(!ret) { if(!ret) {
// IF MDPcomp fails use this route // IF MDPcomp fails use this route
VideoOverlay::prepare(ctx, list, dpy); ctx->mVidOv[dpy]->prepare(ctx, list);
ctx->mFBUpdate[dpy]->prepare(ctx, list); ctx->mFBUpdate[dpy]->prepare(ctx, list);
} }
ctx->mLayerCache[dpy]->updateLayerCache(list); ctx->mLayerCache[dpy]->updateLayerCache(list);
@@ -161,7 +162,7 @@ static int hwc_prepare_external(hwc_composer_device_1 *dev,
if(fbLayer->handle) { if(fbLayer->handle) {
setListStats(ctx, list, dpy); setListStats(ctx, list, dpy);
reset_layer_prop(ctx, dpy); reset_layer_prop(ctx, dpy);
VideoOverlay::prepare(ctx, list, dpy); ctx->mVidOv[dpy]->prepare(ctx, list);
ctx->mFBUpdate[dpy]->prepare(ctx, list); ctx->mFBUpdate[dpy]->prepare(ctx, list);
ctx->mLayerCache[dpy]->updateLayerCache(list); ctx->mLayerCache[dpy]->updateLayerCache(list);
if(ctx->mCopyBit[dpy]) if(ctx->mCopyBit[dpy])
@@ -188,6 +189,7 @@ static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays,
reset(ctx, numDisplays, displays); reset(ctx, numDisplays, displays);
ctx->mOverlay->configBegin(); ctx->mOverlay->configBegin();
ctx->mRotMgr->configBegin();
for (int32_t i = numDisplays; i >= 0; i--) { for (int32_t i = numDisplays; i >= 0; i--) {
hwc_display_contents_1_t *list = displays[i]; hwc_display_contents_1_t *list = displays[i];
@@ -205,6 +207,8 @@ static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays,
} }
ctx->mOverlay->configDone(); ctx->mOverlay->configDone();
ctx->mRotMgr->configDone();
return ret; return ret;
} }
@@ -250,6 +254,7 @@ static int hwc_blank(struct hwc_composer_device_1* dev, int dpy, int blank)
if(blank) { if(blank) {
ctx->mOverlay->configBegin(); ctx->mOverlay->configBegin();
ctx->mOverlay->configDone(); ctx->mOverlay->configDone();
ctx->mRotMgr->clear();
ret = ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_POWERDOWN); ret = ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_POWERDOWN);
if(ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected == true) { if(ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected == true) {
@@ -344,12 +349,12 @@ static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd); copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
if(list->numHwLayers > 1) if(list->numHwLayers > 1)
hwc_sync(ctx, list, dpy, fd); hwc_sync(ctx, list, dpy, fd);
if (!VideoOverlay::draw(ctx, list, dpy)) { if (!ctx->mVidOv[dpy]->draw(ctx, list)) {
ALOGE("%s: VideoOverlay::draw fail!", __FUNCTION__); ALOGE("%s: VideoOverlay draw failed", __FUNCTION__);
ret = -1; ret = -1;
} }
if (!ctx->mMDPComp->draw(ctx, list)) { if (!ctx->mMDPComp->draw(ctx, list)) {
ALOGE("%s: MDPComp::draw fail!", __FUNCTION__); ALOGE("%s: MDPComp draw failed", __FUNCTION__);
ret = -1; ret = -1;
} }
@@ -365,7 +370,7 @@ static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
if(!(fbLayer->flags & HWC_SKIP_LAYER) && if(!(fbLayer->flags & HWC_SKIP_LAYER) &&
(list->numHwLayers > 1)) { (list->numHwLayers > 1)) {
if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) { if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__); ALOGE("%s: FBUpdate draw failed", __FUNCTION__);
ret = -1; ret = -1;
} }
} }
@@ -400,7 +405,7 @@ static int hwc_set_external(hwc_context_t *ctx,
if(list->numHwLayers > 1) if(list->numHwLayers > 1)
hwc_sync(ctx, list, dpy, fd); hwc_sync(ctx, list, dpy, fd);
if (!VideoOverlay::draw(ctx, list, dpy)) { if (!ctx->mVidOv[dpy]->draw(ctx, list)) {
ALOGE("%s: VideoOverlay::draw fail!", __FUNCTION__); ALOGE("%s: VideoOverlay::draw fail!", __FUNCTION__);
ret = -1; ret = -1;
} }
@@ -549,6 +554,9 @@ void hwc_dump(struct hwc_composer_device_1* dev, char *buff, int buff_len)
char ovDump[2048] = {'\0'}; char ovDump[2048] = {'\0'};
ctx->mOverlay->getDump(ovDump, 2048); ctx->mOverlay->getDump(ovDump, 2048);
dumpsys_log(aBuf, ovDump); dumpsys_log(aBuf, ovDump);
ovDump[0] = '\0';
ctx->mRotMgr->getDump(ovDump, 2048);
dumpsys_log(aBuf, ovDump);
strlcpy(buff, aBuf.string(), buff_len); strlcpy(buff, aBuf.string(), buff_len);
} }

View File

@@ -71,7 +71,8 @@ bool FBUpdateLowRes::configure(hwc_context_t *ctx,
ALOGE("%s:NULL private handle for layer!", __FUNCTION__); ALOGE("%s:NULL private handle for layer!", __FUNCTION__);
return false; return false;
} }
ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size); ovutils::Whf info(hnd->width, hnd->height,
ovutils::getMdpFormat(hnd->format), hnd->size);
//Request an RGB pipe //Request an RGB pipe
ovutils::eDest dest = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, mDpy); ovutils::eDest dest = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, mDpy);
@@ -171,7 +172,8 @@ bool FBUpdateHighRes::configure(hwc_context_t *ctx,
ALOGE("%s:NULL private handle for layer!", __FUNCTION__); ALOGE("%s:NULL private handle for layer!", __FUNCTION__);
return false; return false;
} }
ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size); ovutils::Whf info(hnd->width, hnd->height,
ovutils::getMdpFormat(hnd->format), hnd->size);
//Request left RGB pipe //Request left RGB pipe
ovutils::eDest destL = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, mDpy); ovutils::eDest destL = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, mDpy);

View File

@@ -21,11 +21,14 @@
#include "external.h" #include "external.h"
#include "qdMetaData.h" #include "qdMetaData.h"
#include "mdp_version.h" #include "mdp_version.h"
#include <overlayRotator.h>
using overlay::Rotator;
using namespace overlay::utils;
namespace ovutils = overlay::utils;
namespace qhwc { namespace qhwc {
namespace ovutils = overlay::utils;
//==============MDPComp======================================================== //==============MDPComp========================================================
IdleInvalidator *MDPComp::idleInvalidator = NULL; IdleInvalidator *MDPComp::idleInvalidator = NULL;
@@ -188,6 +191,8 @@ void MDPComp::reset(hwc_context_t *ctx,
if(mCurrentFrame.pipeLayer[i].pipeInfo) { if(mCurrentFrame.pipeLayer[i].pipeInfo) {
delete mCurrentFrame.pipeLayer[i].pipeInfo; delete mCurrentFrame.pipeLayer[i].pipeInfo;
mCurrentFrame.pipeLayer[i].pipeInfo = NULL; mCurrentFrame.pipeLayer[i].pipeInfo = NULL;
//We dont own the rotator
mCurrentFrame.pipeLayer[i].rot = NULL;
} }
} }
free(mCurrentFrame.pipeLayer); free(mCurrentFrame.pipeLayer);
@@ -196,20 +201,6 @@ void MDPComp::reset(hwc_context_t *ctx,
mCurrentFrame.count = 0; mCurrentFrame.count = 0;
} }
void MDPComp::setVidInfo(hwc_layer_1_t *layer,
ovutils::eMdpFlags &mdpFlags) {
private_handle_t *hnd = (private_handle_t *)layer->handle;
MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
if(isSecureBuffer(hnd)) {
ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
}
if(metadata && (metadata->operation & PP_PARAM_INTERLACED) &&
metadata->interlaced) {
ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_DEINTERLACE);
}
}
bool MDPComp::isWidthValid(hwc_context_t *ctx, hwc_layer_1_t *layer) { bool MDPComp::isWidthValid(hwc_context_t *ctx, hwc_layer_1_t *layer) {
const int dpy = HWC_DISPLAY_PRIMARY; const int dpy = HWC_DISPLAY_PRIMARY;
@@ -363,9 +354,7 @@ bool MDPComp::setup(hwc_context_t* ctx, hwc_display_contents_1_t* list) {
for (int index = 0 ; index < mCurrentFrame.count; index++) { for (int index = 0 ; index < mCurrentFrame.count; index++) {
hwc_layer_1_t* layer = &list->hwLayers[index]; hwc_layer_1_t* layer = &list->hwLayers[index];
MdpPipeInfo* cur_pipe = mCurrentFrame.pipeLayer[index].pipeInfo; if(configure(ctx, layer, mCurrentFrame.pipeLayer[index]) != 0 ) {
if(configure(ctx, layer, cur_pipe) != 0 ) {
ALOGD_IF(isDebug(), "%s: MDPComp failed to configure overlay for \ ALOGD_IF(isDebug(), "%s: MDPComp failed to configure overlay for \
layer %d",__FUNCTION__, index); layer %d",__FUNCTION__, index);
return false; return false;
@@ -417,134 +406,17 @@ bool MDPComp::prepare(hwc_context_t *ctx,
* Configures pipe(s) for MDP composition * Configures pipe(s) for MDP composition
*/ */
int MDPCompLowRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer, int MDPCompLowRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
MdpPipeInfo* mdpInfo) { PipeLayerPair& pipeLayerPair) {
const int dpy = HWC_DISPLAY_PRIMARY; const int dpy = HWC_DISPLAY_PRIMARY;
private_handle_t *hnd = (private_handle_t *)layer->handle; MdpPipeInfoLowRes& mdp_info =
overlay::Overlay& ov = *ctx->mOverlay; *(static_cast<MdpPipeInfoLowRes*>(pipeLayerPair.pipeInfo));
eMdpFlags mdpFlags = OV_MDP_BACKEND_COMPOSITION;
eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
eIsFg isFg = IS_FG_OFF;
eDest dest = mdp_info.index;
if(!hnd) { return configureLowRes(ctx, layer, dpy, mdpFlags, zOrder, isFg, dest,
ALOGE("%s: layer handle is NULL", __FUNCTION__); &pipeLayerPair.rot);
return -1;
}
MdpPipeInfoLowRes& mdp_info = *(MdpPipeInfoLowRes*)mdpInfo;
int hw_w = ctx->dpyAttr[dpy].xres;
int hw_h = ctx->dpyAttr[dpy].yres;
hwc_rect_t crop = layer->sourceCrop;
hwc_rect_t dst = layer->displayFrame;
int crop_w = crop.right - crop.left;
int crop_h = crop.bottom - crop.top;
int dst_w = dst.right - dst.left;
int dst_h = dst.bottom - dst.top;
if(dst.left < 0 || dst.top < 0 ||
dst.right > hw_w || dst.bottom > hw_h) {
ALOGD_IF(isDebug(),"%s: Destination has negative coordinates",
__FUNCTION__);
hwc_rect_t scissor = {0, 0, hw_w, hw_h };
qhwc::calculate_crop_rects(crop, dst, scissor, layer->transform);
//Update calulated width and height
crop_w = crop.right - crop.left;
crop_h = crop.bottom - crop.top;
dst_w = dst.right - dst.left;
dst_h = dst.bottom - dst.top;
}
if( (dst_w > hw_w)|| (dst_h > hw_h)) {
ALOGD_IF(isDebug(),"%s: Dest rect exceeds FB", __FUNCTION__);
dst_w = hw_w;
dst_h = hw_h;
}
// Determine pipe to set based on pipe index
ovutils::eDest dest = mdp_info.index;
ovutils::eZorder zOrder = ovutils::ZORDER_0;
if(mdp_info.zOrder == 0 ) {
zOrder = ovutils::ZORDER_0;
} else if(mdp_info.zOrder == 1 ) {
zOrder = ovutils::ZORDER_1;
} else if(mdp_info.zOrder == 2 ) {
zOrder = ovutils::ZORDER_2;
} else if(mdp_info.zOrder == 3) {
zOrder = ovutils::ZORDER_3;
}
// Order order order
// setSource - just setting source
// setParameter - changes src w/h/f accordingly
// setCrop - ROI - src_rect
// setPosition - dst_rect
// commit - commit changes to mdp driver
// queueBuffer - not here, happens when draw is called
ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
if(isYuvBuffer(hnd))
setVidInfo(layer, mdpFlags);
ovutils::setMdpFlags(mdpFlags,ovutils::OV_MDP_BACKEND_COMPOSITION);
if(layer->blending == HWC_BLENDING_PREMULT) {
ovutils::setMdpFlags(mdpFlags,
ovutils::OV_MDP_BLEND_FG_PREMULT);
}
ovutils::eTransform orient = overlay::utils::OVERLAY_TRANSFORM_0 ;
if(!(layer->transform & HWC_TRANSFORM_ROT_90)) {
if(layer->transform & HWC_TRANSFORM_FLIP_H) {
ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_FLIP_H);
}
if(layer->transform & HWC_TRANSFORM_FLIP_V) {
ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_FLIP_V);
}
} else {
orient = static_cast<ovutils::eTransform>(layer->transform);
}
ovutils::eRotFlags rotFlags = ovutils::ROT_FLAGS_NONE;
if(isYuvBuffer(hnd) && (ctx->mMDP.version >= qdutils::MDP_V4_2 &&
ctx->mMDP.version < qdutils::MDSS_V5)) {
rotFlags = ovutils::ROT_DOWNSCALE_ENABLED;
}
ovutils::PipeArgs parg(mdpFlags,
info,
zOrder,
ovutils::IS_FG_OFF,
rotFlags);
ov.setSource(parg, dest);
ov.setTransform(orient, dest);
ovutils::Dim dcrop(crop.left, crop.top, crop_w, crop_h);
ov.setCrop(dcrop, dest);
ovutils::Dim dim(dst.left, dst.top, dst_w, dst_h);
ov.setPosition(dim, dest);
ALOGD_IF(isDebug(),"%s: MDP set: crop[%d,%d,%d,%d] dst[%d,%d,%d,%d] \
nPipe: %d zorder: %d",__FUNCTION__, dcrop.x,
dcrop.y,dcrop.w, dcrop.h, dim.x, dim.y, dim.w, dim.h,
mdp_info.index, mdp_info.zOrder);
if (!ov.commit(dest)) {
ALOGE("%s: commit failed", __FUNCTION__);
return -1;
}
return 0;
} }
int MDPCompLowRes::pipesNeeded(hwc_context_t *ctx, int MDPCompLowRes::pipesNeeded(hwc_context_t *ctx,
@@ -572,6 +444,7 @@ bool MDPCompLowRes::allocLayerPipes(hwc_context_t *ctx,
hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex]; hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
PipeLayerPair& info = currentFrame.pipeLayer[nYuvIndex]; PipeLayerPair& info = currentFrame.pipeLayer[nYuvIndex];
info.pipeInfo = new MdpPipeInfoLowRes; info.pipeInfo = new MdpPipeInfoLowRes;
info.rot = NULL;
MdpPipeInfoLowRes& pipe_info = *(MdpPipeInfoLowRes*)info.pipeInfo; MdpPipeInfoLowRes& pipe_info = *(MdpPipeInfoLowRes*)info.pipeInfo;
pipe_info.index = getMdpPipe(ctx, MDPCOMP_OV_VG); pipe_info.index = getMdpPipe(ctx, MDPCOMP_OV_VG);
if(pipe_info.index == ovutils::OV_INVALID) { if(pipe_info.index == ovutils::OV_INVALID) {
@@ -592,6 +465,7 @@ bool MDPCompLowRes::allocLayerPipes(hwc_context_t *ctx,
PipeLayerPair& info = currentFrame.pipeLayer[index]; PipeLayerPair& info = currentFrame.pipeLayer[index];
info.pipeInfo = new MdpPipeInfoLowRes; info.pipeInfo = new MdpPipeInfoLowRes;
info.rot = NULL;
MdpPipeInfoLowRes& pipe_info = *(MdpPipeInfoLowRes*)info.pipeInfo; MdpPipeInfoLowRes& pipe_info = *(MdpPipeInfoLowRes*)info.pipeInfo;
pipe_info.index = getMdpPipe(ctx, MDPCOMP_OV_ANY); pipe_info.index = getMdpPipe(ctx, MDPCOMP_OV_ANY);
@@ -628,36 +502,42 @@ bool MDPCompLowRes::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
for(int i = 0; i < numHwLayers; i++ ) for(int i = 0; i < numHwLayers; i++ )
{ {
hwc_layer_1_t *layer = &list->hwLayers[i]; hwc_layer_1_t *layer = &list->hwLayers[i];
if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
continue;
}
MdpPipeInfoLowRes& pipe_info =
*(MdpPipeInfoLowRes*)mCurrentFrame.pipeLayer[i].pipeInfo;
ovutils::eDest dest = pipe_info.index;
if(dest == ovutils::OV_INVALID) {
ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, dest);
return false;
}
if (ctx ) {
private_handle_t *hnd = (private_handle_t *)layer->handle; private_handle_t *hnd = (private_handle_t *)layer->handle;
if(!hnd) { if(!hnd) {
ALOGE("%s handle null", __FUNCTION__); ALOGE("%s handle null", __FUNCTION__);
return false; return false;
} }
MdpPipeInfoLowRes& pipe_info =
*(MdpPipeInfoLowRes*)mCurrentFrame.pipeLayer[i].pipeInfo;
ovutils::eDest dest = pipe_info.index;
if(dest == ovutils::OV_INVALID) {
ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, dest);
return false;
}
if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
continue;
}
ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \ ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
using pipe: %d", __FUNCTION__, layer, using pipe: %d", __FUNCTION__, layer,
hnd, dest ); hnd, dest );
if (!ov.queueBuffer(hnd->fd, hnd->offset, dest)) { int fd = hnd->fd;
uint32_t offset = hnd->offset;
Rotator *rot = mCurrentFrame.pipeLayer[i].rot;
if(rot) {
if(!rot->queueBuffer(fd, offset))
return false;
fd = rot->getDstMemId();
offset = rot->getDstOffset();
}
if (!ov.queueBuffer(fd, offset, dest)) {
ALOGE("%s: queueBuffer failed for external", __FUNCTION__); ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
return false; return false;
} }
}
layerProp[i].mFlags &= ~HWC_MDPCOMP; layerProp[i].mFlags &= ~HWC_MDPCOMP;
} }
@@ -774,212 +654,17 @@ bool MDPCompHighRes::allocLayerPipes(hwc_context_t *ctx,
* Configures pipe(s) for MDP composition * Configures pipe(s) for MDP composition
*/ */
int MDPCompHighRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer, int MDPCompHighRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
MdpPipeInfo* mdpInfo) { PipeLayerPair& pipeLayerPair) {
const int dpy = HWC_DISPLAY_PRIMARY; const int dpy = HWC_DISPLAY_PRIMARY;
private_handle_t *hnd = (private_handle_t *)layer->handle; MdpPipeInfoHighRes& mdp_info =
overlay::Overlay& ov = *ctx->mOverlay; *(static_cast<MdpPipeInfoHighRes*>(pipeLayerPair.pipeInfo));
eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
if(!hnd) { eIsFg isFg = IS_FG_OFF;
ALOGE("%s: layer handle is NULL", __FUNCTION__); eMdpFlags mdpFlagsL = OV_MDP_BACKEND_COMPOSITION;
return -1; eDest lDest = mdp_info.lIndex;
} eDest rDest = mdp_info.rIndex;
return configureHighRes(ctx, layer, dpy, mdpFlagsL, zOrder, isFg, lDest,
MdpPipeInfoHighRes& mdp_info = *(MdpPipeInfoHighRes*)mdpInfo; rDest, &pipeLayerPair.rot);
int hw_w = ctx->dpyAttr[dpy].xres;
int hw_h = ctx->dpyAttr[dpy].yres;
hwc_rect_t crop = layer->sourceCrop;
hwc_rect_t dst = layer->displayFrame;
int crop_w = crop.right - crop.left;
int crop_h = crop.bottom - crop.top;
int dst_w = dst.right - dst.left;
int dst_h = dst.bottom - dst.top;
if(dst.left < 0 || dst.top < 0 ||
dst.right > hw_w || dst.bottom > hw_h) {
ALOGD_IF(isDebug(),"%s: Destination has negative coordinates",
__FUNCTION__);
hwc_rect_t scissor = {0, 0, hw_w, hw_h };
qhwc::calculate_crop_rects(crop, dst, scissor, 0);
//Update calulated width and height
crop_w = crop.right - crop.left;
crop_h = crop.bottom - crop.top;
dst_w = dst.right - dst.left;
dst_h = dst.bottom - dst.top;
}
if( (dst_w > hw_w)|| (dst_h > hw_h)) {
ALOGD_IF(isDebug(),"%s: Dest rect exceeds FB", __FUNCTION__);
dst_w = hw_w;
dst_h = hw_h;
}
// Determine pipe to set based on pipe index
ovutils::eDest l_dest = mdp_info.lIndex;
ovutils::eDest r_dest = mdp_info.rIndex;
ovutils::eZorder zOrder = ovutils::ZORDER_0;
if(mdp_info.zOrder == 0 ) {
zOrder = ovutils::ZORDER_0;
} else if(mdp_info.zOrder == 1 ) {
zOrder = ovutils::ZORDER_1;
} else if(mdp_info.zOrder == 2 ) {
zOrder = ovutils::ZORDER_2;
} else if(mdp_info.zOrder == 3) {
zOrder = ovutils::ZORDER_3;
}
// Order order order
// setSource - just setting source
// setParameter - changes src w/h/f accordingly
// setCrop - ROI - src_rect
// setPosition - dst_rect
// commit - commit changes to mdp driver
// queueBuffer - not here, happens when draw is called
ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
ovutils::eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
if(isYuvBuffer(hnd))
setVidInfo(layer, mdpFlagsL);
ovutils::setMdpFlags(mdpFlagsL,ovutils::OV_MDP_BACKEND_COMPOSITION);
if(layer->blending == HWC_BLENDING_PREMULT) {
ovutils::setMdpFlags(mdpFlagsL,
ovutils::OV_MDP_BLEND_FG_PREMULT);
}
ovutils::eTransform orient = overlay::utils::OVERLAY_TRANSFORM_0 ;
if(!(layer->transform & HWC_TRANSFORM_ROT_90)) {
if(layer->transform & HWC_TRANSFORM_FLIP_H) {
ovutils::setMdpFlags(mdpFlagsL, ovutils::OV_MDP_FLIP_H);
}
if(layer->transform & HWC_TRANSFORM_FLIP_V) {
ovutils::setMdpFlags(mdpFlagsL, ovutils::OV_MDP_FLIP_V);
}
} else {
orient = static_cast<ovutils::eTransform>(layer->transform);
}
ovutils::eMdpFlags mdpFlagsR = mdpFlagsL;
ovutils::setMdpFlags(mdpFlagsR, ovutils::OV_MDSS_MDP_RIGHT_MIXER);
hwc_rect_t tmp_cropL, tmp_dstL;
hwc_rect_t tmp_cropR, tmp_dstR;
if(l_dest != ovutils::OV_INVALID) {
tmp_cropL = crop;
tmp_dstL = dst;
hwc_rect_t scissor = {0, 0, hw_w/2, hw_h };
qhwc::calculate_crop_rects(tmp_cropL, tmp_dstL, scissor, 0);
}
if(r_dest != ovutils::OV_INVALID) {
tmp_cropR = crop;
tmp_dstR = dst;
hwc_rect_t scissor = {hw_w/2, 0, hw_w, hw_h };
qhwc::calculate_crop_rects(tmp_cropR, tmp_dstR, scissor, 0);
}
//When buffer is flipped, contents of mixer config also needs to swapped.
//Not needed if the layer is confined to one half of the screen.
if(layer->transform & HWC_TRANSFORM_FLIP_V &&
l_dest != ovutils::OV_INVALID && r_dest != ovutils::OV_INVALID ) {
hwc_rect_t new_cropR;
new_cropR.left = tmp_cropL.left;
new_cropR.right = new_cropR.left + (tmp_cropR.right - tmp_cropR.left);
hwc_rect_t new_cropL;
new_cropL.left = new_cropR.right;
new_cropL.right = tmp_cropR.right;
tmp_cropL.left = new_cropL.left;
tmp_cropL.right = new_cropL.right;
tmp_cropR.left = new_cropR.left;
tmp_cropR.right = new_cropR.right;
ALOGD_IF(isDebug(),"rects on V flip: \
cropL(%d,%d,%d,%d) dstL(%d,%d,%d,%d) \
cropR(%d,%d,%d,%d) dstR(%d,%d,%d,%d)",
tmp_cropL.left, tmp_cropL.top, tmp_cropL.right, tmp_cropL.bottom,
tmp_dstL.left, tmp_dstL.top, tmp_dstL.right, tmp_dstL.bottom,
tmp_cropR.left, tmp_cropR.top, tmp_cropR.right, tmp_cropR.bottom,
tmp_dstR.left, tmp_dstR.top, tmp_dstR.right, tmp_dstR.bottom);
}
//**** configure left mixer ****
if(l_dest != ovutils::OV_INVALID) {
ovutils::PipeArgs pargL(mdpFlagsL,
info,
zOrder,
ovutils::IS_FG_OFF,
ovutils::ROT_FLAGS_NONE);
ov.setSource(pargL, l_dest);
ov.setTransform(orient, l_dest);
ovutils::Dim dcropL(tmp_cropL.left, tmp_cropL.top,
tmp_cropL.right - tmp_cropL.left,
tmp_cropL.bottom - tmp_cropL.top);
ov.setCrop(dcropL, l_dest);
ovutils::Dim dimL(tmp_dstL.left , tmp_dstL.top,
tmp_dstL.right - tmp_dstL.left,
tmp_dstL.bottom - tmp_dstL.top);
ov.setPosition(dimL, l_dest);
ALOGD_IF(isDebug(),"%s: MDP set: LEFT: \
crop[%d,%d,%d,%d] dst[%d,%d,%d,%d] pipeIndexL: %d zorder: %d",
__FUNCTION__, dcropL.x, dcropL.y,dcropL.w, dcropL.h,
dimL.x, dimL.y, dimL.w, dimL.h,
mdp_info.lIndex, mdp_info.zOrder);
if (!ov.commit(l_dest)) {
ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
return -1;
}
}
//**** configure right mixer ****
if(r_dest != ovutils::OV_INVALID) {
ovutils::PipeArgs pargR(mdpFlagsR,
info,
zOrder,
ovutils::IS_FG_OFF,
ovutils::ROT_FLAGS_NONE);
ov.setSource(pargR, r_dest);
ov.setTransform(orient, r_dest);
ovutils::Dim dcropR(tmp_cropR.left, tmp_cropR.top,
tmp_cropR.right - tmp_cropR.left,
tmp_cropR.bottom - tmp_cropR.top);
ov.setCrop(dcropR, r_dest);
ovutils::Dim dimR(tmp_dstR.left - hw_w/2, tmp_dstR.top,
tmp_dstR.right - tmp_dstR.left,
tmp_dstR.bottom - tmp_dstR.top);
ov.setPosition(dimR, r_dest);
ALOGD_IF(isDebug(),"%s: MDP set: RIGHT: \
crop[%d,%d,%d,%d] dst[%d,%d,%d,%d] pipeIndexR: %d zorder: %d",
__FUNCTION__, dcropR.x, dcropR.y,dcropR.w, dcropR.h,
dimR.x, dimR.y, dimR.w, dimR.h,
mdp_info.rIndex, mdp_info.zOrder);
if (!ov.commit(r_dest)) {
ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
return -1;
}
}
return 0;
} }
bool MDPCompHighRes::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) { bool MDPCompHighRes::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
@@ -1006,6 +691,11 @@ bool MDPCompHighRes::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
for(int i = 0; i < numHwLayers; i++ ) for(int i = 0; i < numHwLayers; i++ )
{ {
hwc_layer_1_t *layer = &list->hwLayers[i]; hwc_layer_1_t *layer = &list->hwLayers[i];
private_handle_t *hnd = (private_handle_t *)layer->handle;
if(!hnd) {
ALOGE("%s handle null", __FUNCTION__);
return false;
}
if(!(layerProp[i].mFlags & HWC_MDPCOMP)) { if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
continue; continue;
@@ -1013,50 +703,44 @@ bool MDPCompHighRes::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
MdpPipeInfoHighRes& pipe_info = MdpPipeInfoHighRes& pipe_info =
*(MdpPipeInfoHighRes*)mCurrentFrame.pipeLayer[i].pipeInfo; *(MdpPipeInfoHighRes*)mCurrentFrame.pipeLayer[i].pipeInfo;
Rotator *rot = mCurrentFrame.pipeLayer[i].rot;
ovutils::eDest indexL = pipe_info.lIndex; ovutils::eDest indexL = pipe_info.lIndex;
ovutils::eDest indexR = pipe_info.rIndex; ovutils::eDest indexR = pipe_info.rIndex;
int fd = hnd->fd;
int offset = hnd->offset;
if(rot) {
rot->queueBuffer(fd, offset);
fd = rot->getDstMemId();
offset = rot->getDstOffset();
}
//************* play left mixer ********** //************* play left mixer **********
if(indexL != ovutils::OV_INVALID) { if(indexL != ovutils::OV_INVALID) {
ovutils::eDest destL = (ovutils::eDest)indexL; ovutils::eDest destL = (ovutils::eDest)indexL;
if (ctx ) {
private_handle_t *hnd = (private_handle_t *)layer->handle;
if(!hnd) {
ALOGE("%s handle null", __FUNCTION__);
return false;
}
ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \ ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
using pipe: %d", __FUNCTION__, layer, hnd, indexL ); using pipe: %d", __FUNCTION__, layer, hnd, indexL );
if (!ov.queueBuffer(fd, offset, destL)) {
if (!ov.queueBuffer(hnd->fd, hnd->offset, destL)) { ALOGE("%s: queueBuffer failed for left mixer", __FUNCTION__);
ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
return false; return false;
} }
} }
}
//************* play right mixer ********** //************* play right mixer **********
if(indexR != ovutils::OV_INVALID) { if(indexR != ovutils::OV_INVALID) {
ovutils::eDest destR = (ovutils::eDest)indexR; ovutils::eDest destR = (ovutils::eDest)indexR;
if (ctx ) {
private_handle_t *hnd = (private_handle_t *)layer->handle;
if(!hnd) {
ALOGE("%s handle null", __FUNCTION__);
return false;
}
ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \ ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
using pipe: %d", __FUNCTION__, layer, hnd, indexR ); using pipe: %d", __FUNCTION__, layer, hnd, indexR );
if (!ov.queueBuffer(fd, offset, destR)) {
if (!ov.queueBuffer(hnd->fd, hnd->offset, destR)) { ALOGE("%s: queueBuffer failed for right mixer", __FUNCTION__);
ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
return false; return false;
} }
} }
}
layerProp[i].mFlags &= ~HWC_MDPCOMP; layerProp[i].mFlags &= ~HWC_MDPCOMP;
} }
return true; return true;
} }
}; //namespace }; //namespace

View File

@@ -28,10 +28,13 @@
#define DEFAULT_IDLE_TIME 2000 #define DEFAULT_IDLE_TIME 2000
#define MAX_PIPES_PER_MIXER 4 #define MAX_PIPES_PER_MIXER 4
namespace overlay {
class Rotator;
};
namespace qhwc { namespace qhwc {
namespace ovutils = overlay::utils; namespace ovutils = overlay::utils;
class MDPComp { class MDPComp {
public: public:
virtual ~MDPComp(){}; virtual ~MDPComp(){};
@@ -67,6 +70,7 @@ protected:
struct PipeLayerPair { struct PipeLayerPair {
MdpPipeInfo *pipeInfo; MdpPipeInfo *pipeInfo;
native_handle_t* handle; native_handle_t* handle;
overlay::Rotator* rot;
}; };
/* introduced for mixed mode implementation */ /* introduced for mixed mode implementation */
@@ -83,7 +87,7 @@ protected:
hwc_display_contents_1_t* list,FrameInfo& current_frame) = 0; hwc_display_contents_1_t* list,FrameInfo& current_frame) = 0;
/* configures MPD pipes */ /* configures MPD pipes */
virtual int configure(hwc_context_t *ctx, hwc_layer_1_t *layer, virtual int configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
MdpPipeInfo* mdp_info) = 0; PipeLayerPair& pipeLayerPair) = 0;
/* Is rotation supported */ /* Is rotation supported */
virtual bool canRotate(){ return true; }; virtual bool canRotate(){ return true; };
@@ -97,8 +101,6 @@ protected:
eState getState() { return mState; }; eState getState() { return mState; };
/* reset state */ /* reset state */
void reset( hwc_context_t *ctx, hwc_display_contents_1_t* list ); void reset( hwc_context_t *ctx, hwc_display_contents_1_t* list );
/* configure MDP flags for video buffers */
void setVidInfo(hwc_layer_1_t *layer, ovutils::eMdpFlags &mdpFlags);
/* allocate MDP pipes from overlay */ /* allocate MDP pipes from overlay */
ovutils::eDest getMdpPipe(hwc_context_t *ctx, ePipeType type); ovutils::eDest getMdpPipe(hwc_context_t *ctx, ePipeType type);
/* checks for conditions where mdpcomp is not possible */ /* checks for conditions where mdpcomp is not possible */
@@ -136,7 +138,7 @@ private:
/* configure's overlay pipes for the frame */ /* configure's overlay pipes for the frame */
virtual int configure(hwc_context_t *ctx, hwc_layer_1_t *layer, virtual int configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
MdpPipeInfo* mdp_info); PipeLayerPair& pipeLayerPair);
/* allocates pipes to selected candidates */ /* allocates pipes to selected candidates */
virtual bool allocLayerPipes(hwc_context_t *ctx, virtual bool allocLayerPipes(hwc_context_t *ctx,
@@ -163,7 +165,7 @@ private:
/* configure's overlay pipes for the frame */ /* configure's overlay pipes for the frame */
virtual int configure(hwc_context_t *ctx, hwc_layer_1_t *layer, virtual int configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
MdpPipeInfo* mdp_info); PipeLayerPair& pipeLayerPair);
/* allocates pipes to selected candidates */ /* allocates pipes to selected candidates */
virtual bool allocLayerPipes(hwc_context_t *ctx, virtual bool allocLayerPipes(hwc_context_t *ctx,

View File

@@ -27,6 +27,7 @@
#include <stdlib.h> #include <stdlib.h>
#include "hwc_utils.h" #include "hwc_utils.h"
#include "hwc_fbupdate.h" #include "hwc_fbupdate.h"
#include "hwc_video.h"
#include "hwc_copybit.h" #include "hwc_copybit.h"
#include "comptype.h" #include "comptype.h"
#include "external.h" #include "external.h"
@@ -115,6 +116,11 @@ static void handle_uevent(hwc_context_t* ctx, const char* udata, int len)
delete ctx->mFBUpdate[dpy]; delete ctx->mFBUpdate[dpy];
ctx->mFBUpdate[dpy] = NULL; ctx->mFBUpdate[dpy] = NULL;
} }
if(ctx->mVidOv[dpy]) {
Locker::Autolock _l(ctx->mExtSetLock);
delete ctx->mVidOv[dpy];
ctx->mVidOv[dpy] = NULL;
}
if(ctx->mCopyBit[dpy]){ if(ctx->mCopyBit[dpy]){
Locker::Autolock _l(ctx->mExtSetLock); Locker::Autolock _l(ctx->mExtSetLock);
delete ctx->mCopyBit[dpy]; delete ctx->mCopyBit[dpy];
@@ -134,6 +140,8 @@ static void handle_uevent(hwc_context_t* ctx, const char* udata, int len)
ctx->mExtDisplay->processUEventOnline(udata); ctx->mExtDisplay->processUEventOnline(udata);
ctx->mFBUpdate[dpy] = ctx->mFBUpdate[dpy] =
IFBUpdate::getObject(ctx->dpyAttr[dpy].xres, dpy); IFBUpdate::getObject(ctx->dpyAttr[dpy].xres, dpy);
ctx->mVidOv[dpy] =
IVideoOverlay::getObject(ctx->dpyAttr[dpy].xres, dpy);
ctx->dpyAttr[dpy].isPause = false; ctx->dpyAttr[dpy].isPause = false;
if(usecopybit) if(usecopybit)
ctx->mCopyBit[dpy] = new CopyBit(); ctx->mCopyBit[dpy] = new CopyBit();

View File

@@ -25,9 +25,11 @@
#include <gralloc_priv.h> #include <gralloc_priv.h>
#include <fb_priv.h> #include <fb_priv.h>
#include <overlay.h> #include <overlay.h>
#include <overlayRotator.h>
#include "hwc_utils.h" #include "hwc_utils.h"
#include "hwc_mdpcomp.h" #include "hwc_mdpcomp.h"
#include "hwc_fbupdate.h" #include "hwc_fbupdate.h"
#include "hwc_video.h"
#include "mdp_version.h" #include "mdp_version.h"
#include "hwc_copybit.h" #include "hwc_copybit.h"
#include "external.h" #include "external.h"
@@ -38,6 +40,9 @@
using namespace qClient; using namespace qClient;
using namespace qService; using namespace qService;
using namespace android; using namespace android;
using namespace overlay;
using namespace overlay::utils;
namespace ovutils = overlay::utils;
namespace qhwc { namespace qhwc {
@@ -67,6 +72,7 @@ void initContext(hwc_context_t *ctx)
openFramebufferDevice(ctx); openFramebufferDevice(ctx);
overlay::Overlay::initOverlay(); overlay::Overlay::initOverlay();
ctx->mOverlay = overlay::Overlay::getInstance(); ctx->mOverlay = overlay::Overlay::getInstance();
ctx->mRotMgr = new RotMgr();
ctx->mMDP.version = qdutils::MDPVersion::getInstance().getMDPVersion(); ctx->mMDP.version = qdutils::MDPVersion::getInstance().getMDPVersion();
ctx->mMDP.hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay(); ctx->mMDP.hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay();
ctx->mMDP.panel = qdutils::MDPVersion::getInstance().getPanelType(); ctx->mMDP.panel = qdutils::MDPVersion::getInstance().getPanelType();
@@ -77,6 +83,10 @@ void initContext(hwc_context_t *ctx)
IFBUpdate::getObject(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres, IFBUpdate::getObject(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres,
HWC_DISPLAY_PRIMARY); HWC_DISPLAY_PRIMARY);
ctx->mVidOv[HWC_DISPLAY_PRIMARY] =
IVideoOverlay::getObject(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres,
HWC_DISPLAY_PRIMARY);
char value[PROPERTY_VALUE_MAX]; char value[PROPERTY_VALUE_MAX];
// Check if the target supports copybit compostion (dyn/mdp/c2d) to // Check if the target supports copybit compostion (dyn/mdp/c2d) to
// decide if we need to open the copybit module. // decide if we need to open the copybit module.
@@ -120,6 +130,11 @@ void closeContext(hwc_context_t *ctx)
ctx->mOverlay = NULL; ctx->mOverlay = NULL;
} }
if(ctx->mRotMgr) {
delete ctx->mRotMgr;
ctx->mRotMgr = NULL;
}
for(int i = 0; i < MAX_DISPLAYS; i++) { for(int i = 0; i < MAX_DISPLAYS; i++) {
if(ctx->mCopyBit[i]) { if(ctx->mCopyBit[i]) {
delete ctx->mCopyBit[i]; delete ctx->mCopyBit[i];
@@ -144,6 +159,10 @@ void closeContext(hwc_context_t *ctx)
delete ctx->mFBUpdate[i]; delete ctx->mFBUpdate[i];
ctx->mFBUpdate[i] = NULL; ctx->mFBUpdate[i] = NULL;
} }
if(ctx->mVidOv[i]) {
delete ctx->mVidOv[i];
ctx->mVidOv[i] = NULL;
}
} }
if(ctx->mMDPComp) { if(ctx->mMDPComp) {
@@ -492,6 +511,263 @@ int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy,
return ret; return ret;
} }
void trimLayer(hwc_context_t *ctx, const int& dpy, const int& transform,
hwc_rect_t& crop, hwc_rect_t& dst) {
int hw_w = ctx->dpyAttr[dpy].xres;
int hw_h = ctx->dpyAttr[dpy].yres;
if(dst.left < 0 || dst.top < 0 ||
dst.right > hw_w || dst.bottom > hw_h) {
hwc_rect_t scissor = {0, 0, hw_w, hw_h };
qhwc::calculate_crop_rects(crop, dst, scissor, transform);
}
}
void setMdpFlags(hwc_layer_1_t *layer,
ovutils::eMdpFlags &mdpFlags,
int rotDownscale) {
private_handle_t *hnd = (private_handle_t *)layer->handle;
MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
const int& transform = layer->transform;
if(layer->blending == HWC_BLENDING_PREMULT) {
ovutils::setMdpFlags(mdpFlags,
ovutils::OV_MDP_BLEND_FG_PREMULT);
}
if(isYuvBuffer(hnd)) {
if(isSecureBuffer(hnd)) {
ovutils::setMdpFlags(mdpFlags,
ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
}
if(metadata && (metadata->operation & PP_PARAM_INTERLACED) &&
metadata->interlaced) {
ovutils::setMdpFlags(mdpFlags,
ovutils::OV_MDP_DEINTERLACE);
}
//Pre-rotation will be used using rotator.
if(transform & HWC_TRANSFORM_ROT_90) {
ovutils::setMdpFlags(mdpFlags,
ovutils::OV_MDP_SOURCE_ROTATED_90);
}
}
//No 90 component and no rot-downscale then flips done by MDP
//If we use rot then it might as well do flips
if(!(layer->transform & HWC_TRANSFORM_ROT_90) && !rotDownscale) {
if(layer->transform & HWC_TRANSFORM_FLIP_H) {
ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_FLIP_H);
}
if(layer->transform & HWC_TRANSFORM_FLIP_V) {
ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_FLIP_V);
}
}
}
static inline int configRotator(Rotator *rot, const Whf& whf,
const eMdpFlags& mdpFlags, const eTransform& orient,
const int& downscale) {
rot->setSource(whf);
rot->setFlags(mdpFlags);
rot->setTransform(orient);
rot->setDownscale(downscale);
if(!rot->commit()) return -1;
return 0;
}
static inline int configMdp(Overlay *ov, const PipeArgs& parg,
const eTransform& orient, const hwc_rect_t& crop,
const hwc_rect_t& pos, const eDest& dest) {
ov->setSource(parg, dest);
ov->setTransform(orient, dest);
int crop_w = crop.right - crop.left;
int crop_h = crop.bottom - crop.top;
Dim dcrop(crop.left, crop.top, crop_w, crop_h);
ov->setCrop(dcrop, dest);
int posW = pos.right - pos.left;
int posH = pos.bottom - pos.top;
Dim position(pos.left, pos.top, posW, posH);
ov->setPosition(position, dest);
if (!ov->commit(dest)) {
return -1;
}
return 0;
}
static inline void updateSource(eTransform& orient, Whf& whf,
hwc_rect_t& crop) {
Dim srcCrop(crop.left, crop.top,
crop.right - crop.left,
crop.bottom - crop.top);
preRotateSource(orient, whf, srcCrop);
crop.left = srcCrop.x;
crop.top = srcCrop.y;
crop.right = srcCrop.x + srcCrop.w;
crop.bottom = srcCrop.y + srcCrop.h;
}
int configureLowRes(hwc_context_t *ctx, hwc_layer_1_t *layer,
const int& dpy, eMdpFlags& mdpFlags, const eZorder& z,
const eIsFg& isFg, const eDest& dest, Rotator **rot) {
private_handle_t *hnd = (private_handle_t *)layer->handle;
if(!hnd) {
ALOGE("%s: layer handle is NULL", __FUNCTION__);
return -1;
}
hwc_rect_t crop = layer->sourceCrop;
hwc_rect_t dst = layer->displayFrame;
int transform = layer->transform;
eTransform orient = static_cast<eTransform>(transform);
int downscale = 0;
int rotFlags = ovutils::ROT_FLAGS_NONE;
Whf whf(hnd->width, hnd->height,
getMdpFormat(hnd->format), hnd->size);
if(isYuvBuffer(hnd) && ctx->mMDP.version >= qdutils::MDP_V4_2 &&
ctx->mMDP.version < qdutils::MDSS_V5) {
downscale = getDownscaleFactor(
crop.right - crop.left,
crop.bottom - crop.top,
dst.right - dst.left,
dst.bottom - dst.top);
if(downscale) {
rotFlags = ROT_DOWNSCALE_ENABLED;
}
}
setMdpFlags(layer, mdpFlags, downscale);
trimLayer(ctx, dpy, transform, crop, dst);
if(isYuvBuffer(hnd) && //if 90 component or downscale, use rot
((transform & HWC_TRANSFORM_ROT_90) || downscale)) {
*rot = ctx->mRotMgr->getNext();
if(*rot == NULL) return -1;
//Configure rotator for pre-rotation
if(configRotator(*rot, whf, mdpFlags, orient, downscale) < 0)
return -1;
whf.format = (*rot)->getDstFormat();
updateSource(orient, whf, crop);
//For the mdp, since we are pre-rotating
transform = 0;
rotFlags |= ovutils::ROT_PREROTATED;
}
PipeArgs parg(mdpFlags, whf, z, isFg, static_cast<eRotFlags>(rotFlags));
if(configMdp(ctx->mOverlay, parg, orient, crop, dst, dest) < 0) {
ALOGE("%s: commit failed for low res panel", __FUNCTION__);
return -1;
}
return 0;
}
int configureHighRes(hwc_context_t *ctx, hwc_layer_1_t *layer,
const int& dpy, eMdpFlags& mdpFlagsL, const eZorder& z,
const eIsFg& isFg, const eDest& lDest, const eDest& rDest,
Rotator **rot) {
private_handle_t *hnd = (private_handle_t *)layer->handle;
if(!hnd) {
ALOGE("%s: layer handle is NULL", __FUNCTION__);
return -1;
}
int hw_w = ctx->dpyAttr[dpy].xres;
int hw_h = ctx->dpyAttr[dpy].yres;
hwc_rect_t crop = layer->sourceCrop;
hwc_rect_t dst = layer->displayFrame;
int transform = layer->transform;
eTransform orient = static_cast<eTransform>(transform);
const int downscale = 0;
int rotFlags = ROT_FLAGS_NONE;
Whf whf(hnd->width, hnd->height,
getMdpFormat(hnd->format), hnd->size);
setMdpFlags(layer, mdpFlagsL);
trimLayer(ctx, dpy, transform, crop, dst);
if(isYuvBuffer(hnd) && (transform & HWC_TRANSFORM_ROT_90)) {
(*rot) = ctx->mRotMgr->getNext();
if((*rot) == NULL) return -1;
//Configure rotator for pre-rotation
if(configRotator(*rot, whf, mdpFlagsL, orient, downscale) < 0)
return -1;
whf.format = (*rot)->getDstFormat();
updateSource(orient, whf, crop);
//For the mdp, since we are pre-rotating
transform = 0;
rotFlags |= ROT_PREROTATED;
}
eMdpFlags mdpFlagsR = mdpFlagsL;
setMdpFlags(mdpFlagsR, OV_MDSS_MDP_RIGHT_MIXER);
hwc_rect_t tmp_cropL, tmp_dstL;
hwc_rect_t tmp_cropR, tmp_dstR;
if(lDest != OV_INVALID) {
tmp_cropL = crop;
tmp_dstL = dst;
hwc_rect_t scissor = {0, 0, hw_w/2, hw_h };
qhwc::calculate_crop_rects(tmp_cropL, tmp_dstL, scissor, 0);
}
if(rDest != OV_INVALID) {
tmp_cropR = crop;
tmp_dstR = dst;
hwc_rect_t scissor = {hw_w/2, 0, hw_w, hw_h };
qhwc::calculate_crop_rects(tmp_cropR, tmp_dstR, scissor, 0);
}
//When buffer is flipped, contents of mixer config also needs to swapped.
//Not needed if the layer is confined to one half of the screen.
//If rotator has been used then it has also done the flips, so ignore them.
if(layer->transform & HWC_TRANSFORM_FLIP_V && lDest != OV_INVALID
&& rDest != OV_INVALID && rot == NULL) {
hwc_rect_t new_cropR;
new_cropR.left = tmp_cropL.left;
new_cropR.right = new_cropR.left + (tmp_cropR.right - tmp_cropR.left);
hwc_rect_t new_cropL;
new_cropL.left = new_cropR.right;
new_cropL.right = tmp_cropR.right;
tmp_cropL.left = new_cropL.left;
tmp_cropL.right = new_cropL.right;
tmp_cropR.left = new_cropR.left;
tmp_cropR.right = new_cropR.right;
}
//configure left mixer
if(lDest != OV_INVALID) {
PipeArgs pargL(mdpFlagsL, whf, z, isFg,
static_cast<eRotFlags>(rotFlags));
if(configMdp(ctx->mOverlay, pargL, orient,
tmp_cropL, tmp_dstL, lDest) < 0) {
ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
return -1;
}
}
//configure right mixer
if(rDest != OV_INVALID) {
PipeArgs pargR(mdpFlagsR, whf, z, isFg,
static_cast<eRotFlags>(rotFlags));
if(configMdp(ctx->mOverlay, pargR, orient,
tmp_cropR, tmp_dstR, rDest) < 0) {
ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
return -1;
}
}
return 0;
}
void LayerCache::resetLayerCache(int num) { void LayerCache::resetLayerCache(int num) {
for(uint32_t i = 0; i < MAX_NUM_LAYERS; i++) { for(uint32_t i = 0; i < MAX_NUM_LAYERS; i++) {
hnd[i] = NULL; hnd[i] = NULL;
@@ -556,7 +832,6 @@ void LayerCache::markCachedLayersAsOverlay(hwc_display_contents_1_t* list) {
} }
} }
} }
} }
};//namespace };//namespace qhwc

View File

@@ -27,6 +27,8 @@
#include <gr.h> #include <gr.h>
#include <gralloc_priv.h> #include <gralloc_priv.h>
#include <utils/String8.h> #include <utils/String8.h>
#include "qdMetaData.h"
#include <overlayUtils.h>
#define ALIGN_TO(x, align) (((x) + ((align)-1)) & ~((align)-1)) #define ALIGN_TO(x, align) (((x) + ((align)-1)) & ~((align)-1))
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) #define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
@@ -44,8 +46,12 @@
struct hwc_context_t; struct hwc_context_t;
struct framebuffer_device_t; struct framebuffer_device_t;
namespace ovutils = overlay::utils;
namespace overlay { namespace overlay {
class Overlay; class Overlay;
class Rotator;
class RotMgr;
} }
namespace qhwc { namespace qhwc {
@@ -53,6 +59,7 @@ namespace qhwc {
class QueuedBufferStore; class QueuedBufferStore;
class ExternalDisplay; class ExternalDisplay;
class IFBUpdate; class IFBUpdate;
class IVideoOverlay;
class MDPComp; class MDPComp;
class CopyBit; class CopyBit;
@@ -121,9 +128,6 @@ class LayerCache {
}; };
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Utility functions - implemented in hwc_utils.cpp // Utility functions - implemented in hwc_utils.cpp
void dumpLayer(hwc_layer_1_t const* l); void dumpLayer(hwc_layer_1_t const* l);
@@ -156,6 +160,27 @@ void closeAcquireFds(hwc_display_contents_1_t* list);
int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy, int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy,
int fd); int fd);
//Trims a layer's source crop which is outside of screen boundary.
void trimLayer(hwc_context_t *ctx, const int& dpy, const int& transform,
hwc_rect_t& crop, hwc_rect_t& dst);
//Sets appropriate mdp flags for a layer.
void setMdpFlags(hwc_layer_1_t *layer,
ovutils::eMdpFlags &mdpFlags,
int rotDownscale = 0);
//Routine to configure low resolution panels (<= 2048 width)
int configureLowRes(hwc_context_t *ctx, hwc_layer_1_t *layer, const int& dpy,
ovutils::eMdpFlags& mdpFlags, const ovutils::eZorder& z,
const ovutils::eIsFg& isFg, const ovutils::eDest& dest,
overlay::Rotator **rot);
//Routine to configure high resolution panels (> 2048 width)
int configureHighRes(hwc_context_t *ctx, hwc_layer_1_t *layer, const int& dpy,
ovutils::eMdpFlags& mdpFlags, const ovutils::eZorder& z,
const ovutils::eIsFg& isFg, const ovutils::eDest& lDest,
const ovutils::eDest& rDest, overlay::Rotator **rot);
// Inline utility functions // Inline utility functions
static inline bool isSkipLayer(const hwc_layer_1_t* l) { static inline bool isSkipLayer(const hwc_layer_1_t* l) {
return (UNLIKELY(l && (l->flags & HWC_SKIP_LAYER))); return (UNLIKELY(l && (l->flags & HWC_SKIP_LAYER)));
@@ -245,9 +270,12 @@ struct hwc_context_t {
//Overlay object - NULL for non overlay devices //Overlay object - NULL for non overlay devices
overlay::Overlay *mOverlay; overlay::Overlay *mOverlay;
//Holds a few rot objects
overlay::RotMgr *mRotMgr;
//Primary and external FB updater //Primary and external FB updater
qhwc::IFBUpdate *mFBUpdate[MAX_DISPLAYS]; qhwc::IFBUpdate *mFBUpdate[MAX_DISPLAYS];
qhwc::IVideoOverlay *mVidOv[MAX_DISPLAYS];
// External display related information // External display related information
qhwc::ExternalDisplay *mExtDisplay; qhwc::ExternalDisplay *mExtDisplay;
qhwc::MDPInfo mMDP; qhwc::MDPInfo mMDP;
@@ -273,6 +301,7 @@ struct hwc_context_t {
bool mDMAInUse; bool mDMAInUse;
}; };
namespace qhwc {
static inline bool isSkipPresent (hwc_context_t *ctx, int dpy) { static inline bool isSkipPresent (hwc_context_t *ctx, int dpy) {
return ctx->listStats[dpy].skipCount; return ctx->listStats[dpy].skipCount;
} }
@@ -280,5 +309,6 @@ static inline bool isSkipPresent (hwc_context_t *ctx, int dpy) {
static inline bool isYuvPresent (hwc_context_t *ctx, int dpy) { static inline bool isYuvPresent (hwc_context_t *ctx, int dpy) {
return ctx->listStats[dpy].yuvCount; return ctx->listStats[dpy].yuvCount;
} }
};
#endif //HWC_UTILS_H #endif //HWC_UTILS_H

View File

@@ -24,26 +24,36 @@
#include "hwc_utils.h" #include "hwc_utils.h"
#include "qdMetaData.h" #include "qdMetaData.h"
#include "mdp_version.h" #include "mdp_version.h"
#include <overlayRotator.h>
using overlay::Rotator;
namespace qhwc { namespace qhwc {
namespace ovutils = overlay::utils; namespace ovutils = overlay::utils;
//Static Members //===========IVideoOverlay=========================
bool VideoOverlay::sIsModeOn[] = {false}; IVideoOverlay* IVideoOverlay::getObject(const int& width, const int& dpy) {
ovutils::eDest VideoOverlay::sDest[] = {ovutils::OV_INVALID}; if(width > MAX_DISPLAY_DIM) {
return new VideoOverlayHighRes(dpy);
}
return new VideoOverlayLowRes(dpy);
}
//===========VideoOverlayLowRes=========================
VideoOverlayLowRes::VideoOverlayLowRes(const int& dpy): IVideoOverlay(dpy) {}
//Cache stats, figure out the state, config overlay //Cache stats, figure out the state, config overlay
bool VideoOverlay::prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list, bool VideoOverlayLowRes::prepare(hwc_context_t *ctx,
int dpy) { hwc_display_contents_1_t *list) {
if(ctx->listStats[dpy].yuvCount > 1) if(ctx->listStats[mDpy].yuvCount > 1)
return false; return false;
int yuvIndex = ctx->listStats[dpy].yuvIndices[0]; int yuvIndex = ctx->listStats[mDpy].yuvIndices[0];
sIsModeOn[dpy] = false; int hw_w = ctx->dpyAttr[mDpy].xres;
mModeOn = false;
int hw_w = ctx->dpyAttr[dpy].xres;
if(hw_w > MAX_DISPLAY_DIM) { if(hw_w > MAX_DISPLAY_DIM) {
ALOGD_IF(VIDEO_DEBUG,"%s, \ ALOGD_IF(VIDEO_DEBUG,"%s, \
@@ -61,7 +71,7 @@ bool VideoOverlay::prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list,
return false; return false;
} }
if(yuvIndex == -1 || ctx->listStats[dpy].yuvCount != 1) { if(yuvIndex == -1 || ctx->listStats[mDpy].yuvCount != 1) {
return false; return false;
} }
@@ -83,126 +93,55 @@ bool VideoOverlay::prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list,
} }
} }
} }
if(configure(ctx, dpy, layer)) {
if(configure(ctx, layer)) {
markFlags(layer); markFlags(layer);
sIsModeOn[dpy] = true; mModeOn = true;
} }
return sIsModeOn[dpy]; return mModeOn;
} }
void VideoOverlay::markFlags(hwc_layer_1_t *layer) { void VideoOverlayLowRes::markFlags(hwc_layer_1_t *layer) {
if(layer) { if(layer) {
layer->compositionType = HWC_OVERLAY; layer->compositionType = HWC_OVERLAY;
layer->hints |= HWC_HINT_CLEAR_FB; layer->hints |= HWC_HINT_CLEAR_FB;
} }
} }
bool VideoOverlay::configure(hwc_context_t *ctx, int dpy, bool VideoOverlayLowRes::configure(hwc_context_t *ctx,
hwc_layer_1_t *layer) { hwc_layer_1_t *layer) {
overlay::Overlay& ov = *(ctx->mOverlay); overlay::Overlay& ov = *(ctx->mOverlay);
private_handle_t *hnd = (private_handle_t *)layer->handle; private_handle_t *hnd = (private_handle_t *)layer->handle;
ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size); ovutils::Whf info(hnd->width, hnd->height,
ovutils::getMdpFormat(hnd->format), hnd->size);
//Request a VG pipe //Request a VG pipe
ovutils::eDest dest = ov.nextPipe(ovutils::OV_MDP_PIPE_VG, dpy); ovutils::eDest dest = ov.nextPipe(ovutils::OV_MDP_PIPE_VG, mDpy);
if(dest == ovutils::OV_INVALID) { //None available if(dest == ovutils::OV_INVALID) { //None available
return false; return false;
} }
sDest[dpy] = dest; mDest = dest;
ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE; ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
if (isSecureBuffer(hnd)) { ovutils::eZorder zOrder = ovutils::ZORDER_1;
ovutils::setMdpFlags(mdpFlags, ovutils::eIsFg isFg = ovutils::IS_FG_OFF;
ovutils::OV_MDP_SECURE_OVERLAY_SESSION); if (ctx->listStats[mDpy].numAppLayers == 1) {
isFg = ovutils::IS_FG_SET;
} }
if(layer->blending == HWC_BLENDING_PREMULT) { return (configureLowRes(ctx, layer, mDpy, mdpFlags, zOrder, isFg, dest,
ovutils::setMdpFlags(mdpFlags, &mRot) == 0 );
ovutils::OV_MDP_BLEND_FG_PREMULT);
} }
MetaData_t *metadata = (MetaData_t *)hnd->base_metadata; bool VideoOverlayLowRes::draw(hwc_context_t *ctx,
if (metadata && (metadata->operation & PP_PARAM_INTERLACED) && hwc_display_contents_1_t *list) {
metadata->interlaced) { if(!mModeOn) {
ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_DEINTERLACE);
}
ovutils::eIsFg isFgFlag = ovutils::IS_FG_OFF;
if (ctx->listStats[dpy].numAppLayers == 1) {
isFgFlag = ovutils::IS_FG_SET;
}
ovutils::eRotFlags rotFlags = ovutils::ROT_FLAGS_NONE;
if(ctx->mMDP.version >= qdutils::MDP_V4_2 &&
ctx->mMDP.version < qdutils::MDSS_V5) {
rotFlags = ovutils::ROT_DOWNSCALE_ENABLED;
}
ovutils::PipeArgs parg(mdpFlags,
info,
ovutils::ZORDER_1,
isFgFlag,
rotFlags);
ov.setSource(parg, dest);
int transform = layer->transform;
ovutils::eTransform orient =
static_cast<ovutils::eTransform>(transform);
hwc_rect_t sourceCrop = layer->sourceCrop;
hwc_rect_t displayFrame = layer->displayFrame;
//Calculate the rect for primary based on whether the supplied position
//is within or outside bounds.
const int fbWidth = ctx->dpyAttr[dpy].xres;
const int fbHeight = ctx->dpyAttr[dpy].yres;
if( displayFrame.left < 0 ||
displayFrame.top < 0 ||
displayFrame.right > fbWidth ||
displayFrame.bottom > fbHeight) {
hwc_rect_t scissor = {0, 0, fbWidth, fbHeight};
calculate_crop_rects(sourceCrop, displayFrame, scissor, transform);
}
// source crop x,y,w,h
ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top,
sourceCrop.right - sourceCrop.left,
sourceCrop.bottom - sourceCrop.top);
//Only for Primary
ov.setCrop(dcrop, dest);
ov.setTransform(orient, dest);
// position x,y,w,h
ovutils::Dim dpos(displayFrame.left,
displayFrame.top,
displayFrame.right - displayFrame.left,
displayFrame.bottom - displayFrame.top);
// Calculate the actionsafe dimensions for External(dpy = 1 or 2)
if(dpy)
getActionSafePosition(ctx, dpy, dpos.x, dpos.y, dpos.w, dpos.h);
ov.setPosition(dpos, dest);
if (!ov.commit(dest)) {
ALOGE("%s: commit fails", __FUNCTION__);
return false;
}
return true; return true;
} }
bool VideoOverlay::draw(hwc_context_t *ctx, hwc_display_contents_1_t *list, int yuvIndex = ctx->listStats[mDpy].yuvIndices[0];
int dpy)
{
if(!sIsModeOn[dpy]) {
return true;
}
int yuvIndex = ctx->listStats[dpy].yuvIndices[0];
if(yuvIndex == -1) { if(yuvIndex == -1) {
return true; return true;
} }
@@ -210,16 +149,148 @@ bool VideoOverlay::draw(hwc_context_t *ctx, hwc_display_contents_1_t *list,
private_handle_t *hnd = (private_handle_t *) private_handle_t *hnd = (private_handle_t *)
list->hwLayers[yuvIndex].handle; list->hwLayers[yuvIndex].handle;
bool ret = true;
overlay::Overlay& ov = *(ctx->mOverlay); overlay::Overlay& ov = *(ctx->mOverlay);
int fd = hnd->fd;
uint32_t offset = hnd->offset;
Rotator *rot = mRot;
if (!ov.queueBuffer(hnd->fd, hnd->offset, if(rot) {
sDest[dpy])) { if(!rot->queueBuffer(fd, offset))
ALOGE("%s: queueBuffer failed for dpy=%d", __FUNCTION__, dpy); return false;
ret = false; fd = rot->getDstMemId();
offset = rot->getDstOffset();
} }
return ret; if (!ov.queueBuffer(fd, offset, mDest)) {
ALOGE("%s: queueBuffer failed for dpy=%d", __FUNCTION__, mDpy);
return false;
} }
return true;
}
//===========VideoOverlayHighRes=========================
VideoOverlayHighRes::VideoOverlayHighRes(const int& dpy): IVideoOverlay(dpy) {}
//Cache stats, figure out the state, config overlay
bool VideoOverlayHighRes::prepare(hwc_context_t *ctx,
hwc_display_contents_1_t *list) {
int yuvIndex = ctx->listStats[mDpy].yuvIndices[0];
int hw_w = ctx->dpyAttr[mDpy].xres;
mModeOn = false;
if(!ctx->mMDP.hasOverlay) {
ALOGD_IF(VIDEO_DEBUG,"%s, this hw doesnt support overlay", __FUNCTION__);
return false;
}
if(yuvIndex == -1 || ctx->listStats[mDpy].yuvCount != 1) {
return false;
}
//index guaranteed to be not -1 at this point
hwc_layer_1_t *layer = &list->hwLayers[yuvIndex];
if(configure(ctx, layer)) {
markFlags(layer);
mModeOn = true;
}
return mModeOn;
}
void VideoOverlayHighRes::markFlags(hwc_layer_1_t *layer) {
if(layer) {
layer->compositionType = HWC_OVERLAY;
layer->hints |= HWC_HINT_CLEAR_FB;
}
}
bool VideoOverlayHighRes::configure(hwc_context_t *ctx,
hwc_layer_1_t *layer) {
int hw_w = ctx->dpyAttr[mDpy].xres;
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 VG pipe
mDestL = ovutils::OV_INVALID;
mDestR = ovutils::OV_INVALID;
hwc_rect_t dst = layer->displayFrame;
if(dst.left > hw_w/2) {
mDestR = ov.nextPipe(ovutils::OV_MDP_PIPE_VG, mDpy);
if(mDestR == ovutils::OV_INVALID)
return false;
} else if (dst.right <= hw_w/2) {
mDestL = ov.nextPipe(ovutils::OV_MDP_PIPE_VG, mDpy);
if(mDestL == ovutils::OV_INVALID)
return false;
} else {
mDestL = ov.nextPipe(ovutils::OV_MDP_PIPE_VG, mDpy);
mDestR = ov.nextPipe(ovutils::OV_MDP_PIPE_VG, mDpy);
if(mDestL == ovutils::OV_INVALID ||
mDestR == ovutils::OV_INVALID)
return false;
}
ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
ovutils::eZorder zOrder = ovutils::ZORDER_1;
ovutils::eIsFg isFg = ovutils::IS_FG_OFF;
if (ctx->listStats[mDpy].numAppLayers == 1) {
isFg = ovutils::IS_FG_SET;
}
return (configureHighRes(ctx, layer, mDpy, mdpFlags, zOrder, isFg, mDestL,
mDestR, &mRot) == 0 );
}
bool VideoOverlayHighRes::draw(hwc_context_t *ctx,
hwc_display_contents_1_t *list) {
if(!mModeOn) {
return true;
}
int yuvIndex = ctx->listStats[mDpy].yuvIndices[0];
if(yuvIndex == -1) {
return true;
}
private_handle_t *hnd = (private_handle_t *)
list->hwLayers[yuvIndex].handle;
overlay::Overlay& ov = *(ctx->mOverlay);
int fd = hnd->fd;
uint32_t offset = hnd->offset;
Rotator *rot = mRot;
if(rot) {
if(!rot->queueBuffer(fd, offset))
return false;
fd = rot->getDstMemId();
offset = rot->getDstOffset();
}
if(mDestL != ovutils::OV_INVALID) {
if (!ov.queueBuffer(fd, offset, mDestL)) {
ALOGE("%s: queueBuffer failed for dpy=%d's left mixer",
__FUNCTION__, mDpy);
return false;
}
}
if(mDestR != ovutils::OV_INVALID) {
if (!ov.queueBuffer(fd, offset, mDestR)) {
ALOGE("%s: queueBuffer failed for dpy=%d's right mixer"
, __FUNCTION__, mDpy);
return false;
}
}
return true;
}
}; //namespace qhwc }; //namespace qhwc

View File

@@ -23,38 +23,80 @@
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) #define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) #define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
namespace overlay {
class Rotator;
}
namespace qhwc { namespace qhwc {
namespace ovutils = overlay::utils; namespace ovutils = overlay::utils;
//Feature for using overlay to display videos. class IVideoOverlay {
class VideoOverlay {
public: public:
//Sets up members and prepares overlay if conditions are met explicit IVideoOverlay(const int& dpy) : mDpy(dpy), mModeOn(false),
static bool prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list, mRot(NULL) {}
int dpy); virtual ~IVideoOverlay() {};
//Draws layer if this feature is on virtual bool prepare(hwc_context_t *ctx,
static bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list, hwc_display_contents_1_t *list) = 0;
int dpy); virtual bool draw(hwc_context_t *ctx,
//resets values hwc_display_contents_1_t *list) = 0;
static void reset(); virtual void reset() = 0;
private: //Factory method that returns a low-res or high-res version
//Configures overlay for video prim and ext static IVideoOverlay *getObject(const int& width, const int& dpy);
static bool configure(hwc_context_t *ctx, int dpy, protected:
hwc_layer_1_t *yuvlayer); const int mDpy; // display to update
bool mModeOn; // if prepare happened
//Marks layer flags if this feature is used overlay::Rotator *mRot;
static void markFlags(hwc_layer_1_t *yuvLayer);
//Flags if this feature is on.
static bool sIsModeOn[MAX_DISPLAYS];
static ovutils::eDest sDest[MAX_DISPLAYS];
}; };
inline void VideoOverlay::reset() { class VideoOverlayLowRes : public IVideoOverlay {
for(uint32_t i = 0; i < MAX_DISPLAYS; i++) { public:
sIsModeOn[i] = false; explicit VideoOverlayLowRes(const int& dpy);
sDest[i] = ovutils::OV_INVALID; virtual ~VideoOverlayLowRes() {};
bool prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list);
bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list);
void reset();
private:
//Configures overlay for video prim and ext
bool configure(hwc_context_t *ctx, hwc_layer_1_t *yuvlayer);
//Marks layer flags if this feature is used
void markFlags(hwc_layer_1_t *yuvLayer);
//Flags if this feature is on.
bool mModeOn;
ovutils::eDest mDest;
};
class VideoOverlayHighRes : public IVideoOverlay {
public:
explicit VideoOverlayHighRes(const int& dpy);
virtual ~VideoOverlayHighRes() {};
bool prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list);
bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list);
void reset();
private:
//Configures overlay for video prim and ext
bool configure(hwc_context_t *ctx, hwc_layer_1_t *yuvlayer);
//Marks layer flags if this feature is used
void markFlags(hwc_layer_1_t *yuvLayer);
//Flags if this feature is on.
bool mModeOn;
ovutils::eDest mDestL;
ovutils::eDest mDestR;
};
//=================Inlines======================
inline void VideoOverlayLowRes::reset() {
mModeOn = false;
mDest = ovutils::OV_INVALID;
mRot = NULL;
} }
inline void VideoOverlayHighRes::reset() {
mModeOn = false;
mDestL = ovutils::OV_INVALID;
mDestR = ovutils::OV_INVALID;
mRot = NULL;
} }
}; //namespace qhwc }; //namespace qhwc
#endif //HWC_VIDEO_H #endif //HWC_VIDEO_H

View File

@@ -11,7 +11,6 @@ LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdoverlay\"
LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
LOCAL_SRC_FILES := \ LOCAL_SRC_FILES := \
overlay.cpp \ overlay.cpp \
overlayCtrl.cpp \
overlayUtils.cpp \ overlayUtils.cpp \
overlayMdp.cpp \ overlayMdp.cpp \
overlayRotator.cpp \ overlayRotator.cpp \

View File

@@ -1,91 +0,0 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
*
* 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.
*/
#include <cutils/properties.h>
#include "overlayCtrlData.h"
#include "fb_priv.h"
#include "gralloc_priv.h" //for interlace
namespace overlay{
bool Ctrl::init(uint32_t fbnum) {
// MDP/FD init
if(!mMdp.init(fbnum)) {
ALOGE("Ctrl failed to init fbnum=%d", fbnum);
return false;
}
if(!getScreenInfo(mInfo)) {
ALOGE("Ctrl failed to getScreenInfo");
return false;
}
return true;
}
bool Ctrl::setSource(const utils::PipeArgs& args)
{
return mMdp.setSource(args);
}
bool Ctrl::setPosition(const utils::Dim& dim)
{
if(!dim.check(mInfo.mFBWidth, mInfo.mFBHeight)) {
ALOGE("Ctrl setPosition error in dim");
dim.dump();
return false;
}
if(!mMdp.setPosition(dim, mInfo.mFBWidth, mInfo.mFBHeight)) {
ALOGE("Ctrl failed MDP setPosition");
return false;
}
return true;
}
bool Ctrl::setTransform(const utils::eTransform& orient)
{
if(!mMdp.setTransform(orient)) {
ALOGE("Ctrl setTransform failed for Mdp");
return false;
}
return true;
}
void Ctrl::setRotatorUsed(const bool& rotUsed) {
mMdp.setRotatorUsed(rotUsed);
}
bool Ctrl::setCrop(const utils::Dim& d)
{
if(!mMdp.setCrop(d)) {
ALOGE("Data setCrop failed in MDP setCrop");
return false;
}
return true;
}
utils::FrameBufferInfo* utils::FrameBufferInfo::sFBInfoInstance = 0;
void Ctrl::dump() const {
ALOGE("== Dump Ctrl start ==");
mInfo.dump("mInfo");
mMdp.dump();
ALOGE("== Dump Ctrl end ==");
}
} // overlay

View File

@@ -58,15 +58,13 @@ public:
bool close(); bool close();
/* set source using whf, orient and wait flag */ /* set source using whf, orient and wait flag */
bool setSource(const utils::PipeArgs& args); void setSource(const utils::PipeArgs& args);
/* set crop info and pass it down to mdp */ /* set crop info and pass it down to mdp */
bool setCrop(const utils::Dim& d); void setCrop(const utils::Dim& d);
/* set orientation */ /* set orientation */
bool setTransform(const utils::eTransform& p); void setTransform(const utils::eTransform& p);
/* set whether rotator can be used */
void setRotatorUsed(const bool& rotUsed);
/* set mdp position using dim */ /* set mdp position using dim */
bool setPosition(const utils::Dim& dim); void setPosition(const utils::Dim& dim);
/* mdp set overlay/commit changes */ /* mdp set overlay/commit changes */
bool commit(); bool commit();
@@ -74,40 +72,21 @@ public:
int getPipeId() const; int getPipeId() const;
/* ctrl fd */ /* ctrl fd */
int getFd() const; int getFd() const;
/* retrieve crop data */
/* access for screen info */
utils::ScreenInfo getScreenInfo() const;
/* retrieve cached crop data */
utils::Dim getCrop() const; utils::Dim getCrop() const;
utils::Dim getPosition() const;
/* Perform transformation calculations */ /* Set downscale */
void doTransform(); void setDownscale(int dscale_factor);
/* Update the src format based on rotator's dest */
/* Performs downscale calculations */ void updateSrcFormat(const uint32_t& rotDstFormat);
void doDownscale(int dscale_factor);
/* Get downscale factor */
int getDownscalefactor();
/* Update the src format */
void updateSrcformat(const uint32_t& inputsrcFormat);
/* dump the state of the object */ /* dump the state of the object */
void dump() const; void dump() const;
/* Return the dump in the specified buffer */ /* Return the dump in the specified buffer */
void getDump(char *buf, size_t len); void getDump(char *buf, size_t len);
private: private:
/* Retrieve screen info from underlying mdp */
bool getScreenInfo(utils::ScreenInfo& info);
// mdp ctrl struct(info e.g.) // mdp ctrl struct(info e.g.)
MdpCtrl mMdp; MdpCtrl mMdp;
/* Screen info */
utils::ScreenInfo mInfo;
}; };
@@ -115,28 +94,20 @@ class Data : utils::NoCopy {
public: public:
/* init, reset */ /* init, reset */
explicit Data(); explicit Data();
/* calls close */ /* calls close */
~Data(); ~Data();
/* init fd etc */ /* init fd etc */
bool init(uint32_t fbnum); bool init(uint32_t fbnum);
/* calls underlying mdp close */ /* calls underlying mdp close */
bool close(); bool close();
/* set overlay pipe id in the mdp struct */ /* set overlay pipe id in the mdp struct */
void setPipeId(int id); void setPipeId(int id);
/* get overlay id in the mdp struct */ /* get overlay id in the mdp struct */
int getPipeId() const; int getPipeId() const;
/* queue buffer to the overlay */ /* queue buffer to the overlay */
bool queueBuffer(int fd, uint32_t offset); bool queueBuffer(int fd, uint32_t offset);
/* sump the state of the obj */ /* sump the state of the obj */
void dump() const; void dump() const;
/* Return the dump in the specified buffer */ /* Return the dump in the specified buffer */
void getDump(char *buf, size_t len); void getDump(char *buf, size_t len);
@@ -171,17 +142,44 @@ inline bool Ctrl::close() {
return true; return true;
} }
inline bool Ctrl::commit() { inline bool Ctrl::init(uint32_t fbnum) {
if(!mMdp.set()) { // MDP/FD init
ALOGE("Ctrl commit failed set overlay"); if(!mMdp.init(fbnum)) {
ALOGE("Ctrl failed to init fbnum=%d", fbnum);
return false; return false;
} }
return true; return true;
} }
inline bool Ctrl::getScreenInfo(utils::ScreenInfo& info) { inline void Ctrl::setSource(const utils::PipeArgs& args)
if(!mMdp.getScreenInfo(info)){ {
ALOGE("Ctrl failed to get screen info"); mMdp.setSource(args);
}
inline void Ctrl::setPosition(const utils::Dim& dim)
{
mMdp.setPosition(dim);
}
inline void Ctrl::setTransform(const utils::eTransform& orient)
{
mMdp.setTransform(orient);
}
inline void Ctrl::setCrop(const utils::Dim& d)
{
mMdp.setCrop(d);
}
inline void Ctrl::dump() const {
ALOGE("== Dump Ctrl start ==");
mMdp.dump();
ALOGE("== Dump Ctrl end ==");
}
inline bool Ctrl::commit() {
if(!mMdp.set()) {
ALOGE("Ctrl commit failed set overlay");
return false; return false;
} }
return true; return true;
@@ -195,28 +193,20 @@ inline int Ctrl::getFd() const {
return mMdp.getFd(); return mMdp.getFd();
} }
inline void Ctrl::updateSrcformat(const uint32_t& inputsrcFormat) { inline void Ctrl::updateSrcFormat(const uint32_t& rotDstFmt) {
mMdp.updateSrcformat(inputsrcFormat); mMdp.updateSrcFormat(rotDstFmt);
}
inline utils::ScreenInfo Ctrl::getScreenInfo() const {
return mInfo;
} }
inline utils::Dim Ctrl::getCrop() const { inline utils::Dim Ctrl::getCrop() const {
return mMdp.getSrcRectDim(); return mMdp.getSrcRectDim();
} }
inline void Ctrl::doTransform() { inline utils::Dim Ctrl::getPosition() const {
return mMdp.doTransform(); return mMdp.getDstRectDim();
} }
inline void Ctrl::doDownscale(int dscale_factor) { inline void Ctrl::setDownscale(int dscale_factor) {
mMdp.doDownscale(dscale_factor); mMdp.setDownscale(dscale_factor);
}
inline int Ctrl::getDownscalefactor() {
return mMdp.getDownscalefactor();
} }
inline void Ctrl::getDump(char *buf, size_t len) { inline void Ctrl::getDump(char *buf, size_t len) {

View File

@@ -52,12 +52,11 @@ void MdpCtrl::reset() {
mOVInfo.id = MSMFB_NEW_REQUEST; mOVInfo.id = MSMFB_NEW_REQUEST;
mLkgo.id = MSMFB_NEW_REQUEST; mLkgo.id = MSMFB_NEW_REQUEST;
mOrientation = utils::OVERLAY_TRANSFORM_0; mOrientation = utils::OVERLAY_TRANSFORM_0;
mRotUsed = false; mDownscale = 0;
} }
bool MdpCtrl::close() { bool MdpCtrl::close() {
bool result = true; bool result = true;
if(MSMFB_NEW_REQUEST != static_cast<int>(mOVInfo.id)) { if(MSMFB_NEW_REQUEST != static_cast<int>(mOVInfo.id)) {
if(!mdp_wrapper::unsetOverlay(mFd.getFD(), mOVInfo.id)) { if(!mdp_wrapper::unsetOverlay(mFd.getFD(), mOVInfo.id)) {
ALOGE("MdpCtrl close error in unset"); ALOGE("MdpCtrl close error in unset");
@@ -66,6 +65,7 @@ bool MdpCtrl::close() {
} }
reset(); reset();
if(!mFd.close()) { if(!mFd.close()) {
result = false; result = false;
} }
@@ -73,8 +73,7 @@ bool MdpCtrl::close() {
return result; return result;
} }
bool MdpCtrl::setSource(const utils::PipeArgs& args) { void MdpCtrl::setSource(const utils::PipeArgs& args) {
setSrcWhf(args.whf); setSrcWhf(args.whf);
//TODO These are hardcoded. Can be moved out of setSource. //TODO These are hardcoded. Can be moved out of setSource.
@@ -85,111 +84,44 @@ bool MdpCtrl::setSource(const utils::PipeArgs& args) {
setFlags(args.mdpFlags); setFlags(args.mdpFlags);
setZ(args.zorder); setZ(args.zorder);
setIsFg(args.isFg); setIsFg(args.isFg);
return true;
} }
bool MdpCtrl::setCrop(const utils::Dim& d) { void MdpCtrl::setCrop(const utils::Dim& d) {
setSrcRectDim(d); setSrcRectDim(d);
return true;
} }
bool MdpCtrl::setPosition(const overlay::utils::Dim& d, void MdpCtrl::setPosition(const overlay::utils::Dim& d) {
int fbw, int fbh) setDstRectDim(d);
{
ovutils::Dim dim(d);
ovutils::Dim ovsrcdim = getSrcRectDim();
// Scaling of upto a max of 20 times supported
if(dim.w >(ovsrcdim.w * ovutils::HW_OV_MAGNIFICATION_LIMIT)){
dim.w = ovutils::HW_OV_MAGNIFICATION_LIMIT * ovsrcdim.w;
dim.x = (fbw - dim.w) / 2;
}
if(dim.h >(ovsrcdim.h * ovutils::HW_OV_MAGNIFICATION_LIMIT)) {
dim.h = ovutils::HW_OV_MAGNIFICATION_LIMIT * ovsrcdim.h;
dim.y = (fbh - dim.h) / 2;
} }
setDstRectDim(dim); void MdpCtrl::setTransform(const utils::eTransform& orient) {
return true;
}
bool MdpCtrl::setTransform(const utils::eTransform& orient) {
int rot = utils::getMdpOrient(orient); int rot = utils::getMdpOrient(orient);
setUserData(rot); setUserData(rot);
//getMdpOrient will switch the flips if the source is 90 rotated. //getMdpOrient will switch the flips if the source is 90 rotated.
//Clients in Android dont factor in 90 rotation while deciding the flip. //Clients in Android dont factor in 90 rotation while deciding the flip.
mOrientation = static_cast<utils::eTransform>(rot); mOrientation = static_cast<utils::eTransform>(rot);
return true;
}
void MdpCtrl::setRotatorUsed(const bool& rotUsed) {
//rotUsed dictates whether rotator hardware can be used.
//It is set if transformation or downscaling is required.
mRotUsed = rotUsed;
} }
void MdpCtrl::doTransform() { void MdpCtrl::doTransform() {
adjustSrcWhf(mRotUsed);
setRotationFlags(); setRotationFlags();
//180 will be H + V utils::Whf whf = getSrcWhf();
//270 will be H + V + 90 utils::Dim dim = getSrcRectDim();
if(mOrientation & utils::OVERLAY_TRANSFORM_FLIP_H) { utils::preRotateSource(mOrientation, whf, dim);
overlayTransFlipH(); setSrcWhf(whf);
} setSrcRectDim(dim);
if(mOrientation & utils::OVERLAY_TRANSFORM_FLIP_V) {
overlayTransFlipV();
}
if(mOrientation & utils::OVERLAY_TRANSFORM_ROT_90) {
overlayTransRot90();
}
} }
int MdpCtrl::getDownscalefactor() { void MdpCtrl::doDownscale() {
int dscale_factor = utils::ROT_DS_NONE; mOVInfo.src_rect.x >>= mDownscale;
int src_w = mOVInfo.src_rect.w; mOVInfo.src_rect.y >>= mDownscale;
int src_h = mOVInfo.src_rect.h; mOVInfo.src_rect.w >>= mDownscale;
int dst_w = mOVInfo.dst_rect.w; mOVInfo.src_rect.h >>= mDownscale;
int dst_h = mOVInfo.dst_rect.h;
// We need this check to engage the rotator whenever possible to assist MDP
// in performing video downscale.
// This saves bandwidth and avoids causing the driver to make too many panel
// -mode switches between BLT (writeback) and non-BLT (Direct) modes.
// Use-case: Video playback [with downscaling and rotation].
if (dst_w && dst_h)
{
uint32_t dscale = (src_w * src_h) / (dst_w * dst_h);
if(dscale < 2) {
// Down-scale to > 50% of orig.
dscale_factor = utils::ROT_DS_NONE;
} else if(dscale < 4) {
// Down-scale to between > 25% to <= 50% of orig.
dscale_factor = utils::ROT_DS_HALF;
} else if(dscale < 8) {
// Down-scale to between > 12.5% to <= 25% of orig.
dscale_factor = utils::ROT_DS_FOURTH;
} else {
// Down-scale to <= 12.5% of orig.
dscale_factor = utils::ROT_DS_EIGHTH;
}
}
return dscale_factor;
}
void MdpCtrl::doDownscale(int dscale_factor) {
if( dscale_factor ) {
mOVInfo.src_rect.x >>= dscale_factor;
mOVInfo.src_rect.y >>= dscale_factor;
mOVInfo.src_rect.w >>= dscale_factor;
mOVInfo.src_rect.h >>= dscale_factor;
}
} }
bool MdpCtrl::set() { bool MdpCtrl::set() {
//deferred calcs, so APIs could be called in any order. //deferred calcs, so APIs could be called in any order.
doTransform();
doDownscale();
utils::Whf whf = getSrcWhf(); utils::Whf whf = getSrcWhf();
if(utils::isYuv(whf.format)) { if(utils::isYuv(whf.format)) {
normalizeCrop(mOVInfo.src_rect.x, mOVInfo.src_rect.w); normalizeCrop(mOVInfo.src_rect.x, mOVInfo.src_rect.w);
@@ -213,23 +145,6 @@ bool MdpCtrl::set() {
return true; return true;
} }
bool MdpCtrl::getScreenInfo(overlay::utils::ScreenInfo& info) {
fb_fix_screeninfo finfo;
if (!mdp_wrapper::getFScreenInfo(mFd.getFD(), finfo)) {
return false;
}
fb_var_screeninfo vinfo;
if (!mdp_wrapper::getVScreenInfo(mFd.getFD(), vinfo)) {
return false;
}
info.mFBWidth = vinfo.xres;
info.mFBHeight = vinfo.yres;
info.mFBbpp = vinfo.bits_per_pixel;
info.mFBystride = finfo.line_length;
return true;
}
bool MdpCtrl::get() { bool MdpCtrl::get() {
mdp_overlay ov; mdp_overlay ov;
ov.id = mOVInfo.id; ov.id = mOVInfo.id;
@@ -241,24 +156,10 @@ bool MdpCtrl::get() {
return true; return true;
} }
//Adjust width, height if rotator is used post transform calcs. //Update src format based on rotator's destination format.
//At this point the format is already updated by updateSrcFormat void MdpCtrl::updateSrcFormat(const uint32_t& rotDestFmt) {
void MdpCtrl::adjustSrcWhf(const bool& rotUsed) {
if(rotUsed) {
utils::Whf whf = getSrcWhf(); utils::Whf whf = getSrcWhf();
if(whf.format == MDP_Y_CRCB_H2V2_TILE || whf.format = rotDestFmt;
whf.format == MDP_Y_CBCR_H2V2_TILE) {
whf.w = utils::alignup(whf.w, 64);
whf.h = utils::alignup(whf.h, 32);
}
setSrcWhf(whf);
}
}
//Update src format if rotator used based on rotator's destination format.
void MdpCtrl::updateSrcformat(const uint32_t& inputformat) {
utils::Whf whf = getSrcWhf();
whf.format = inputformat;
setSrcWhf(whf); setSrcWhf(whf);
} }

View File

@@ -33,151 +33,92 @@ class MdpCtrl {
public: public:
/* ctor reset */ /* ctor reset */
explicit MdpCtrl(); explicit MdpCtrl();
/* dtor close */ /* dtor close */
~MdpCtrl(); ~MdpCtrl();
/* init underlying device using fbnum */ /* init underlying device using fbnum */
bool init(uint32_t fbnum); bool init(uint32_t fbnum);
/* unset overlay, reset and close fd */ /* unset overlay, reset and close fd */
bool close(); bool close();
/* reset and set ov id to -1 / MSMFB_NEW_REQUEST */ /* reset and set ov id to -1 / MSMFB_NEW_REQUEST */
void reset(); void reset();
/* get orient / user_data[0] */
int getOrient() const;
/* returns session id */
int getPipeId() const;
/* returns the fd associated to ctrl*/
int getFd() const;
/* Get screen info. out: info*/
bool getScreenInfo(utils::ScreenInfo& info);
/* overlay get */
bool get();
/* returns flags from mdp structure */
int getFlags() const;
/* set flags to mdp structure */
void setFlags(int f);
/* set z order */
void setZ(utils::eZorder z);
/* set isFg flag */
void setIsFg(utils::eIsFg isFg);
/* calls overlay set /* calls overlay set
* Set would always consult last good known ov instance. * Set would always consult last good known ov instance.
* Only if it is different, set would actually exectue ioctl. * Only if it is different, set would actually exectue ioctl.
* On a sucess ioctl. last good known ov instance is updated */ * On a sucess ioctl. last good known ov instance is updated */
bool set(); bool set();
/* return a copy of src whf*/
utils::Whf getSrcWhf() const;
/* set src whf */
void setSrcWhf(const utils::Whf& whf);
/* adjust source width height format based on rot info */
void adjustSrcWhf(const bool& rotUsed);
/* swap src w/h*/
void swapSrcWH();
/* swap src rect w/h */
void swapSrcRectWH();
/* returns a copy to src rect dim */
utils::Dim getSrcRectDim() const;
/* set src/dst rect dim */
void setSrcRectDim(const utils::Dim d);
void setDstRectDim(const utils::Dim d);
/* returns a copy ro dst rect dim */
utils::Dim getDstRectDim() const;
/* returns user_data[0]*/
int getUserData() const;
/* sets user_data[0] */
void setUserData(int v);
/* return true if current overlay is different
* than last known good overlay */
bool ovChanged() const;
/* save mOVInfo to be last known good ov*/
void save();
/* restore last known good ov to be the current */
void restore();
/* Sets the source total width, height, format */ /* Sets the source total width, height, format */
bool setSource(const utils::PipeArgs& pargs); void setSource(const utils::PipeArgs& pargs);
/* /*
* Sets ROI, the unpadded region, for source buffer. * Sets ROI, the unpadded region, for source buffer.
* Should be called before a setPosition, for small clips.
* Dim - ROI dimensions. * Dim - ROI dimensions.
*/ */
bool setCrop(const utils::Dim& d); void setCrop(const utils::Dim& d);
void setTransform(const utils::eTransform& orient);
bool setTransform(const utils::eTransform& orient);
/* set whether rotator can be used */
void setRotatorUsed(const bool& rotUsed);
/* given a dim and w/h, set overlay dim */ /* given a dim and w/h, set overlay dim */
bool setPosition(const utils::Dim& dim, int w, int h); void setPosition(const utils::Dim& dim);
/* using user_data, sets/unsets roationvalue in mdp flags */ /* using user_data, sets/unsets roationvalue in mdp flags */
void setRotationFlags(); void setRotationFlags();
/* Perform transformation calculations */
void doTransform();
/* Performs downscale calculations */ /* Performs downscale calculations */
void doDownscale(int dscale_factor); void setDownscale(int dscale_factor);
/* Update the src format with rotator's dest*/
/* Get downscale factor */ void updateSrcFormat(const uint32_t& rotDstFormat);
int getDownscalefactor();
/* Update the src format */
void updateSrcformat(const uint32_t& inputsrcFormat);
/* dump state of the object */ /* dump state of the object */
void dump() const; void dump() const;
/* Return the dump in the specified buffer */ /* Return the dump in the specified buffer */
void getDump(char *buf, size_t len); void getDump(char *buf, size_t len);
private: /* returns session id */
int getPipeId() const;
/* returns the fd associated to ctrl*/
int getFd() const;
/* returns a copy ro dst rect dim */
utils::Dim getDstRectDim() const;
/* returns a copy to src rect dim */
utils::Dim getSrcRectDim() const;
/* helper functions for overlayTransform */ private:
void overlayTransFlipH(); /* Perform transformation calculations */
void overlayTransFlipV(); void doTransform();
void overlayTransRot90(); void doDownscale();
/* get orient / user_data[0] */
int getOrient() const;
/* overlay get */
bool get();
/* returns flags from mdp structure */
int getFlags() const;
/* set flags to mdp structure */
void setFlags(int f);
/* set z order */
void setZ(utils::eZorder z);
/* set isFg flag */
void setIsFg(utils::eIsFg isFg);
/* return a copy of src whf*/
utils::Whf getSrcWhf() const;
/* set src whf */
void setSrcWhf(const utils::Whf& whf);
/* set src/dst rect dim */
void setSrcRectDim(const utils::Dim d);
void setDstRectDim(const utils::Dim d);
/* returns user_data[0]*/
int getUserData() const;
/* sets user_data[0] */
void setUserData(int v);
/* return true if current overlay is different
* than last known good overlay */
bool ovChanged() const;
/* save mOVInfo to be last known good ov*/
void save();
/* restore last known good ov to be the current */
void restore();
utils::eTransform mOrientation; //Holds requested orientation utils::eTransform mOrientation; //Holds requested orientation
bool mRotUsed; //whether rotator should be used even if requested
//orientation is 0.
/* last good known ov info */ /* last good known ov info */
mdp_overlay mLkgo; mdp_overlay mLkgo;
/* Actual overlay mdp structure */ /* Actual overlay mdp structure */
mdp_overlay mOVInfo; mdp_overlay mOVInfo;
/* FD for the mdp fbnum */ /* FD for the mdp fbnum */
OvFD mFd; OvFD mFd;
int mDownscale;
}; };
@@ -210,37 +151,26 @@ class MdpData {
public: public:
/* ctor reset data */ /* ctor reset data */
explicit MdpData(); explicit MdpData();
/* dtor close*/ /* dtor close*/
~MdpData(); ~MdpData();
/* init FD */ /* init FD */
bool init(uint32_t fbnum); bool init(uint32_t fbnum);
/* memset0 the underlying mdp object */ /* memset0 the underlying mdp object */
void reset(); void reset();
/* close fd, and reset */ /* close fd, and reset */
bool close(); bool close();
/* set id of mdp data */ /* set id of mdp data */
void setPipeId(int id); void setPipeId(int id);
/* return ses id of data */ /* return ses id of data */
int getPipeId() const; int getPipeId() const;
/* get underlying fd*/ /* get underlying fd*/
int getFd() const; int getFd() const;
/* get memory_id */ /* get memory_id */
int getSrcMemoryId() const; int getSrcMemoryId() const;
/* calls wrapper play */ /* calls wrapper play */
bool play(int fd, uint32_t offset); bool play(int fd, uint32_t offset);
/* dump state of the object */ /* dump state of the object */
void dump() const; void dump() const;
/* Return the dump in the specified buffer */ /* Return the dump in the specified buffer */
void getDump(char *buf, size_t len); void getDump(char *buf, size_t len);
@@ -248,18 +178,11 @@ private:
/* actual overlay mdp data */ /* actual overlay mdp data */
msmfb_overlay_data mOvData; msmfb_overlay_data mOvData;
/* fd to mdp fbnum */ /* fd to mdp fbnum */
OvFD mFd; OvFD mFd;
}; };
//--------------Inlines--------------------------------- //--------------Inlines---------------------------------
namespace {
// just a helper func for common operations x-(y+z)
int compute(uint32_t x, uint32_t y, uint32_t z) {
return x-(y+z);
}
}
///// MdpCtrl ////// ///// MdpCtrl //////
@@ -299,6 +222,10 @@ inline void MdpCtrl::setIsFg(overlay::utils::eIsFg isFg) {
mOVInfo.is_fg = isFg; mOVInfo.is_fg = isFg;
} }
inline void MdpCtrl::setDownscale(int dscale) {
mDownscale = dscale;
}
inline bool MdpCtrl::ovChanged() const { inline bool MdpCtrl::ovChanged() const {
// 0 means same // 0 means same
if(0 == ::memcmp(&mOVInfo, &mLkgo, sizeof (mdp_overlay))) { if(0 == ::memcmp(&mOVInfo, &mLkgo, sizeof (mdp_overlay))) {
@@ -375,47 +302,6 @@ inline void MdpCtrl::setRotationFlags() {
mOVInfo.flags &= ~MDP_SOURCE_ROTATED_90; mOVInfo.flags &= ~MDP_SOURCE_ROTATED_90;
} }
inline void MdpCtrl::swapSrcWH() {
utils::swap(mOVInfo.src.width,
mOVInfo.src.height);
}
inline void MdpCtrl::swapSrcRectWH() {
utils::swap(mOVInfo.src_rect.w,
mOVInfo.src_rect.h);
}
inline void MdpCtrl::overlayTransFlipH()
{
utils::Dim d = getSrcRectDim();
utils::Whf whf = getSrcWhf();
d.x = compute(whf.w, d.x, d.w);
setSrcRectDim(d);
}
inline void MdpCtrl::overlayTransFlipV()
{
utils::Dim d = getSrcRectDim();
utils::Whf whf = getSrcWhf();
d.y = compute(whf.h, d.y, d.h);
setSrcRectDim(d);
}
inline void MdpCtrl::overlayTransRot90()
{
utils::Dim d = getSrcRectDim();
utils::Whf whf = getSrcWhf();
int tmp = d.x;
d.x = compute(whf.h,
d.y,
d.h);
d.y = tmp;
setSrcRectDim(d);
swapSrcWH();
swapSrcRectWH();
}
/////// MdpCtrl3D ////// /////// MdpCtrl3D //////
inline MdpCtrl3D::MdpCtrl3D() { reset(); } inline MdpCtrl3D::MdpCtrl3D() { reset(); }

View File

@@ -31,48 +31,38 @@ MdpRot::MdpRot() {
MdpRot::~MdpRot() { close(); } MdpRot::~MdpRot() { close(); }
inline void MdpRot::setEnable() { mRotImgInfo.enable = 1; } bool MdpRot::enabled() const { return mRotImgInfo.enable; }
inline void MdpRot::setDisable() { mRotImgInfo.enable = 0; } void MdpRot::setRotations(uint32_t r) { mRotImgInfo.rotations = r; }
inline bool MdpRot::enabled() const { return mRotImgInfo.enable; } int MdpRot::getDstMemId() const {
inline void MdpRot::setRotations(uint32_t r) { mRotImgInfo.rotations = r; }
inline int MdpRot::getDstMemId() const {
return mRotDataInfo.dst.memory_id; return mRotDataInfo.dst.memory_id;
} }
inline uint32_t MdpRot::getDstOffset() const { uint32_t MdpRot::getDstOffset() const {
return mRotDataInfo.dst.offset; return mRotDataInfo.dst.offset;
} }
inline uint32_t MdpRot::getDstFormat() const { uint32_t MdpRot::getDstFormat() const {
return mRotImgInfo.dst.format; return mRotImgInfo.dst.format;
} }
inline uint32_t MdpRot::getSessId() const { return mRotImgInfo.session_id; } uint32_t MdpRot::getSessId() const { return mRotImgInfo.session_id; }
inline void MdpRot::setSrcFB() {
mRotDataInfo.src.flags |= MDP_MEMORY_ID_TYPE_FB;
}
void MdpRot::setDownscale(int ds) { void MdpRot::setDownscale(int ds) {
if ((utils::ROT_DS_EIGHTH == ds) && (mRotImgInfo.src_rect.h & 0xF)) { if ((utils::ROT_DS_EIGHTH == ds) && (mRotImgInfo.src_rect.h & 0xF)) {
// Ensure src_rect.h is a multiple of 16 for 1/8 downscaling. // Ensure src_rect.h is a multiple of 16 for 1/8 downscaling.
// This is an undocumented MDP Rotator constraint. // This is an undocumented MDP Rotator constraint.
// Note that src_rect.h is already ensured to be 32 pixel height aligned
// for MDP_Y_CRCB_H2V2_TILE and MDP_Y_CBCR_H2V2_TILE formats.
mRotImgInfo.src_rect.h = utils::aligndown(mRotImgInfo.src_rect.h, 16); mRotImgInfo.src_rect.h = utils::aligndown(mRotImgInfo.src_rect.h, 16);
} }
mRotImgInfo.downscale_ratio = ds; mRotImgInfo.downscale_ratio = ds;
} }
inline void MdpRot::save() { void MdpRot::save() {
mLSRotImgInfo = mRotImgInfo; mLSRotImgInfo = mRotImgInfo;
} }
inline bool MdpRot::rotConfChanged() const { bool MdpRot::rotConfChanged() const {
// 0 means same // 0 means same
if(0 == ::memcmp(&mRotImgInfo, &mLSRotImgInfo, if(0 == ::memcmp(&mRotImgInfo, &mLSRotImgInfo,
sizeof (msm_rotator_img_info))) { sizeof (msm_rotator_img_info))) {
@@ -92,13 +82,7 @@ bool MdpRot::init()
void MdpRot::setSource(const overlay::utils::Whf& awhf) { void MdpRot::setSource(const overlay::utils::Whf& awhf) {
utils::Whf whf(awhf); utils::Whf whf(awhf);
mRotImgInfo.src.format = whf.format; mRotImgInfo.src.format = whf.format;
if(whf.format == MDP_Y_CRCB_H2V2_TILE ||
whf.format == MDP_Y_CBCR_H2V2_TILE) {
whf.w = utils::alignup(awhf.w, 64);
whf.h = utils::alignup(awhf.h, 32);
}
mRotImgInfo.src.width = whf.w; mRotImgInfo.src.width = whf.w;
mRotImgInfo.src.height = whf.h; mRotImgInfo.src.height = whf.h;
@@ -110,13 +94,13 @@ void MdpRot::setSource(const overlay::utils::Whf& awhf) {
mRotImgInfo.dst.height = whf.h; mRotImgInfo.dst.height = whf.h;
} }
inline void MdpRot::setFlags(const utils::eMdpFlags& flags) { void MdpRot::setFlags(const utils::eMdpFlags& flags) {
mRotImgInfo.secure = 0; mRotImgInfo.secure = 0;
if(flags & utils::OV_MDP_SECURE_OVERLAY_SESSION) if(flags & utils::OV_MDP_SECURE_OVERLAY_SESSION)
mRotImgInfo.secure = 1; mRotImgInfo.secure = 1;
} }
inline void MdpRot::setTransform(const utils::eTransform& rot) void MdpRot::setTransform(const utils::eTransform& rot)
{ {
int r = utils::getMdpOrient(rot); int r = utils::getMdpOrient(rot);
setRotations(r); setRotations(r);
@@ -126,14 +110,7 @@ inline void MdpRot::setTransform(const utils::eTransform& rot)
ALOGE_IF(DEBUG_OVERLAY, "%s: r=%d", __FUNCTION__, r); ALOGE_IF(DEBUG_OVERLAY, "%s: r=%d", __FUNCTION__, r);
} }
inline void MdpRot::setRotatorUsed(const bool& rotUsed) { void MdpRot::doTransform() {
setDisable();
if(rotUsed) {
setEnable();
}
}
inline void MdpRot::doTransform() {
if(mOrientation & utils::OVERLAY_TRANSFORM_ROT_90) if(mOrientation & utils::OVERLAY_TRANSFORM_ROT_90)
utils::swap(mRotImgInfo.dst.width, mRotImgInfo.dst.height); utils::swap(mRotImgInfo.dst.width, mRotImgInfo.dst.height);
} }
@@ -141,9 +118,11 @@ inline void MdpRot::doTransform() {
bool MdpRot::commit() { bool MdpRot::commit() {
doTransform(); doTransform();
if(rotConfChanged()) { if(rotConfChanged()) {
mRotImgInfo.enable = 1;
if(!overlay::mdp_wrapper::startRotator(mFd.getFD(), mRotImgInfo)) { if(!overlay::mdp_wrapper::startRotator(mFd.getFD(), mRotImgInfo)) {
ALOGE("MdpRot commit failed"); ALOGE("MdpRot commit failed");
dump(); dump();
mRotImgInfo.enable = 0;
return false; return false;
} }
save(); save();

View File

@@ -43,34 +43,26 @@ MdssRot::MdssRot() {
MdssRot::~MdssRot() { close(); } MdssRot::~MdssRot() { close(); }
inline void MdssRot::setEnable() { mEnabled = true; } bool MdssRot::enabled() const { return mEnabled; }
inline void MdssRot::setDisable() { mEnabled = false; } void MdssRot::setRotations(uint32_t flags) { mRotInfo.flags |= flags; }
inline bool MdssRot::enabled() const { return mEnabled; } int MdssRot::getDstMemId() const {
inline void MdssRot::setRotations(uint32_t flags) { mRotInfo.flags |= flags; }
inline int MdssRot::getDstMemId() const {
return mRotData.dst_data.memory_id; return mRotData.dst_data.memory_id;
} }
inline uint32_t MdssRot::getDstOffset() const { uint32_t MdssRot::getDstOffset() const {
return mRotData.dst_data.offset; return mRotData.dst_data.offset;
} }
inline uint32_t MdssRot::getDstFormat() const { uint32_t MdssRot::getDstFormat() const {
//For mdss src and dst formats are same //For mdss src and dst formats are same
return mRotInfo.src.format; return mRotInfo.src.format;
} }
inline uint32_t MdssRot::getSessId() const { return mRotInfo.id; } uint32_t MdssRot::getSessId() const { return mRotInfo.id; }
inline void MdssRot::setSrcFB() { bool MdssRot::init() {
mRotData.data.flags |= MDP_MEMORY_ID_TYPE_FB;
}
inline bool MdssRot::init() {
if(!utils::openDev(mFd, 0, Res::fbPath, O_RDWR)) { if(!utils::openDev(mFd, 0, Res::fbPath, O_RDWR)) {
ALOGE("MdssRot failed to init fb0"); ALOGE("MdssRot failed to init fb0");
return false; return false;
@@ -82,11 +74,6 @@ void MdssRot::setSource(const overlay::utils::Whf& awhf) {
utils::Whf whf(awhf); utils::Whf whf(awhf);
mRotInfo.src.format = whf.format; mRotInfo.src.format = whf.format;
if(whf.format == MDP_Y_CRCB_H2V2_TILE ||
whf.format == MDP_Y_CBCR_H2V2_TILE) {
whf.w = utils::alignup(awhf.w, 64);
whf.h = utils::alignup(awhf.h, 32);
}
mRotInfo.src.width = whf.w; mRotInfo.src.width = whf.w;
mRotInfo.src.height = whf.h; mRotInfo.src.height = whf.h;
@@ -98,13 +85,13 @@ void MdssRot::setSource(const overlay::utils::Whf& awhf) {
mRotInfo.dst_rect.h = whf.h; mRotInfo.dst_rect.h = whf.h;
} }
inline void MdssRot::setDownscale(int ds) {} void MdssRot::setDownscale(int ds) {}
inline void MdssRot::setFlags(const utils::eMdpFlags& flags) { void MdssRot::setFlags(const utils::eMdpFlags& flags) {
mRotInfo.flags |= flags; mRotInfo.flags |= flags;
} }
inline void MdssRot::setTransform(const utils::eTransform& rot) void MdssRot::setTransform(const utils::eTransform& rot)
{ {
int flags = utils::getMdpOrient(rot); int flags = utils::getMdpOrient(rot);
if (flags != -1) if (flags != -1)
@@ -115,14 +102,7 @@ inline void MdssRot::setTransform(const utils::eTransform& rot)
ALOGE_IF(DEBUG_OVERLAY, "%s: rot=%d", __FUNCTION__, flags); ALOGE_IF(DEBUG_OVERLAY, "%s: rot=%d", __FUNCTION__, flags);
} }
inline void MdssRot::setRotatorUsed(const bool& rotUsed) { void MdssRot::doTransform() {
setDisable();
if(rotUsed) {
setEnable();
}
}
inline void MdssRot::doTransform() {
if(mOrientation & utils::OVERLAY_TRANSFORM_ROT_90) if(mOrientation & utils::OVERLAY_TRANSFORM_ROT_90)
utils::swap(mRotInfo.dst_rect.w, mRotInfo.dst_rect.h); utils::swap(mRotInfo.dst_rect.w, mRotInfo.dst_rect.h);
} }
@@ -130,10 +110,11 @@ inline void MdssRot::doTransform() {
bool MdssRot::commit() { bool MdssRot::commit() {
doTransform(); doTransform();
mRotInfo.flags |= MDSS_MDP_ROT_ONLY; mRotInfo.flags |= MDSS_MDP_ROT_ONLY;
mEnabled = true;
if(!overlay::mdp_wrapper::setOverlay(mFd.getFD(), mRotInfo)) { if(!overlay::mdp_wrapper::setOverlay(mFd.getFD(), mRotInfo)) {
ALOGE("MdssRot commit failed!"); ALOGE("MdssRot commit failed!");
dump(); dump();
return false; return (mEnabled = false);
} }
mRotData.id = mRotInfo.id; mRotData.id = mRotInfo.id;
// reset rotation flags to avoid stale orientation values // reset rotation flags to avoid stale orientation values

View File

@@ -70,4 +70,65 @@ bool RotMem::close() {
return ret; return ret;
} }
RotMgr::RotMgr() {
for(int i = 0; i < MAX_ROT_SESS; i++) {
mRot[i] = 0;
}
mUseCount = 0;
}
RotMgr::~RotMgr() {
clear();
}
void RotMgr::configBegin() {
//Reset the number of objects used
mUseCount = 0;
}
void RotMgr::configDone() {
//Remove the top most unused objects. Videos come and go.
for(int i = mUseCount; i < MAX_ROT_SESS; i++) {
if(mRot[i]) {
delete mRot[i];
mRot[i] = 0;
}
}
}
Rotator* RotMgr::getNext() {
//Return a rot object, creating one if necessary
overlay::Rotator *rot = NULL;
if(mUseCount >= MAX_ROT_SESS) {
ALOGE("%s, MAX rotator sessions reached", __func__);
} else {
if(mRot[mUseCount] == NULL)
mRot[mUseCount] = overlay::Rotator::getRotator();
rot = mRot[mUseCount++];
}
return rot;
}
void RotMgr::clear() {
//Brute force obj destruction, helpful in suspend.
for(int i = 0; i < MAX_ROT_SESS; i++) {
if(mRot[i]) {
delete mRot[i];
mRot[i] = 0;
}
}
mUseCount = 0;
}
void RotMgr::getDump(char *buf, size_t len) {
for(int i = 0; i < MAX_ROT_SESS; i++) {
if(mRot[i]) {
mRot[i]->getDump(buf, len);
}
}
char str[32] = {'\0'};
snprintf(str, 32, "\n================\n");
strncat(buf, str, strlen(str));
}
} }

View File

@@ -43,22 +43,14 @@ class Rotator
public: public:
enum { TYPE_MDP, TYPE_MDSS }; enum { TYPE_MDP, TYPE_MDSS };
virtual ~Rotator(); virtual ~Rotator();
virtual bool init() = 0;
virtual bool close() = 0;
virtual void setSource(const utils::Whf& wfh) = 0; virtual void setSource(const utils::Whf& wfh) = 0;
virtual void setFlags(const utils::eMdpFlags& flags) = 0; virtual void setFlags(const utils::eMdpFlags& flags) = 0;
virtual void setTransform(const utils::eTransform& rot) = 0; virtual void setTransform(const utils::eTransform& rot) = 0;
virtual void setRotatorUsed(const bool& rotUsed) = 0;
virtual bool commit() = 0; virtual bool commit() = 0;
virtual void setRotations(uint32_t r) = 0;
virtual void setSrcFB() = 0;
virtual void setDownscale(int ds) = 0; virtual void setDownscale(int ds) = 0;
virtual int getDstMemId() const = 0; virtual int getDstMemId() const = 0;
virtual uint32_t getDstOffset() const = 0; virtual uint32_t getDstOffset() const = 0;
virtual uint32_t getDstFormat() const = 0; virtual uint32_t getDstFormat() const = 0;
virtual void setEnable() = 0;
virtual void setDisable() = 0;
virtual bool enabled () const = 0;
virtual uint32_t getSessId() const = 0; virtual uint32_t getSessId() const = 0;
virtual bool queueBuffer(int fd, uint32_t offset) = 0; virtual bool queueBuffer(int fd, uint32_t offset) = 0;
virtual void dump() const = 0; virtual void dump() const = 0;
@@ -116,22 +108,14 @@ struct RotMem {
class MdpRot : public Rotator { class MdpRot : public Rotator {
public: public:
virtual ~MdpRot(); virtual ~MdpRot();
virtual bool init();
virtual bool close();
virtual void setSource(const utils::Whf& wfh); virtual void setSource(const utils::Whf& wfh);
virtual void setFlags(const utils::eMdpFlags& flags); virtual void setFlags(const utils::eMdpFlags& flags);
virtual void setTransform(const utils::eTransform& rot); virtual void setTransform(const utils::eTransform& rot);
virtual void setRotatorUsed(const bool& rotUsed);
virtual bool commit(); virtual bool commit();
virtual void setRotations(uint32_t r);
virtual void setSrcFB();
virtual void setDownscale(int ds); virtual void setDownscale(int ds);
virtual int getDstMemId() const; virtual int getDstMemId() const;
virtual uint32_t getDstOffset() const; virtual uint32_t getDstOffset() const;
virtual uint32_t getDstFormat() const; virtual uint32_t getDstFormat() const;
virtual void setEnable();
virtual void setDisable();
virtual bool enabled () const;
virtual uint32_t getSessId() const; virtual uint32_t getSessId() const;
virtual bool queueBuffer(int fd, uint32_t offset); virtual bool queueBuffer(int fd, uint32_t offset);
virtual void dump() const; virtual void dump() const;
@@ -139,6 +123,10 @@ public:
private: private:
explicit MdpRot(); explicit MdpRot();
bool init();
bool close();
void setRotations(uint32_t r);
bool enabled () const;
/* remap rot buffers */ /* remap rot buffers */
bool remap(uint32_t numbufs); bool remap(uint32_t numbufs);
bool open_i(uint32_t numbufs, uint32_t bufsz); bool open_i(uint32_t numbufs, uint32_t bufsz);
@@ -178,22 +166,14 @@ private:
class MdssRot : public Rotator { class MdssRot : public Rotator {
public: public:
virtual ~MdssRot(); virtual ~MdssRot();
virtual bool init();
virtual bool close();
virtual void setSource(const utils::Whf& wfh); virtual void setSource(const utils::Whf& wfh);
virtual void setFlags(const utils::eMdpFlags& flags); virtual void setFlags(const utils::eMdpFlags& flags);
virtual void setTransform(const utils::eTransform& rot); virtual void setTransform(const utils::eTransform& rot);
virtual void setRotatorUsed(const bool& rotUsed);
virtual bool commit(); virtual bool commit();
virtual void setRotations(uint32_t r);
virtual void setSrcFB();
virtual void setDownscale(int ds); virtual void setDownscale(int ds);
virtual int getDstMemId() const; virtual int getDstMemId() const;
virtual uint32_t getDstOffset() const; virtual uint32_t getDstOffset() const;
virtual uint32_t getDstFormat() const; virtual uint32_t getDstFormat() const;
virtual void setEnable();
virtual void setDisable();
virtual bool enabled () const;
virtual uint32_t getSessId() const; virtual uint32_t getSessId() const;
virtual bool queueBuffer(int fd, uint32_t offset); virtual bool queueBuffer(int fd, uint32_t offset);
virtual void dump() const; virtual void dump() const;
@@ -201,6 +181,10 @@ public:
private: private:
explicit MdssRot(); explicit MdssRot();
bool init();
bool close();
void setRotations(uint32_t r);
bool enabled () const;
/* remap rot buffers */ /* remap rot buffers */
bool remap(uint32_t numbufs); bool remap(uint32_t numbufs);
bool open_i(uint32_t numbufs, uint32_t bufsz); bool open_i(uint32_t numbufs, uint32_t bufsz);
@@ -228,6 +212,28 @@ private:
friend Rotator* Rotator::getRotator(); friend Rotator* Rotator::getRotator();
}; };
// Holder of rotator objects. Manages lifetimes
class RotMgr {
public:
//Maximum sessions based on VG pipes, since rotator is used only for videos.
//Even though we can have 4 mixer stages, that much may be unnecessary.
enum { MAX_ROT_SESS = 3 };
RotMgr();
~RotMgr();
void configBegin();
void configDone();
overlay::Rotator *getNext();
void clear(); //Removes all instances
/* Returns rot dump.
* Expects a NULL terminated buffer of big enough size.
*/
void getDump(char *buf, size_t len);
private:
overlay::Rotator *mRot[MAX_ROT_SESS];
int mUseCount;
};
} // overlay } // overlay
#endif // OVERlAY_ROTATOR_H #endif // OVERlAY_ROTATOR_H

View File

@@ -89,67 +89,6 @@ namespace utils {
#define NUM_FB_DEVICES 3 #define NUM_FB_DEVICES 3
//-------------------------------------------------------- //--------------------------------------------------------
FrameBufferInfo::FrameBufferInfo() {
mFBWidth = 0;
mFBHeight = 0;
mBorderFillSupported = false;
OvFD mFd;
// Use open defined in overlayFD file to open fd for fb0
if(!overlay::open(mFd, 0, Res::fbPath)) {
ALOGE("FrameBufferInfo: failed to open fd");
return;
}
if (!mFd.valid()) {
ALOGE("FrameBufferInfo: FD not valid");
return;
}
fb_var_screeninfo vinfo;
if (!mdp_wrapper::getVScreenInfo(mFd.getFD(), vinfo)) {
ALOGE("FrameBufferInfo: failed getVScreenInfo on fb0");
mFd.close();
return;
}
int mdpVersion = qdutils::MDPVersion::getInstance().getMDPVersion();
if (mdpVersion < qdutils::MDSS_V5) {
mdp_overlay ov;
memset(&ov, 0, sizeof(ov));
ov.id = 1;
if (!mdp_wrapper::getOverlay(mFd.getFD(), ov)) {
ALOGE("FrameBufferInfo: failed getOverlay on fb0");
mFd.close();
return;
}
mBorderFillSupported = (ov.flags & MDP_BORDERFILL_SUPPORTED) ?
true : false;
} else {
// badger always support border fill
mBorderFillSupported = true;
}
mFd.close();
mFBWidth = vinfo.xres;
mFBHeight = vinfo.yres;
}
FrameBufferInfo* FrameBufferInfo::getInstance() {
if (!sFBInfoInstance) {
sFBInfoInstance = new FrameBufferInfo;
}
return sFBInfoInstance;
}
int FrameBufferInfo::getWidth() const {
return mFBWidth;
}
int FrameBufferInfo::getHeight() const {
return mFBHeight;
}
/* clears any VG pipes allocated to the fb devices */ /* clears any VG pipes allocated to the fb devices */
int initOverlay() { int initOverlay() {
@@ -293,6 +232,58 @@ int getHALFormat(int mdpFormat) {
return -1; return -1;
} }
int getDownscaleFactor(const int& src_w, const int& src_h,
const int& dst_w, const int& dst_h) {
int dscale_factor = utils::ROT_DS_NONE;
// We need this check to engage the rotator whenever possible to assist MDP
// in performing video downscale.
// This saves bandwidth and avoids causing the driver to make too many panel
// -mode switches between BLT (writeback) and non-BLT (Direct) modes.
// Use-case: Video playback [with downscaling and rotation].
if (dst_w && dst_h)
{
uint32_t dscale = (src_w * src_h) / (dst_w * dst_h);
if(dscale < 2) {
// Down-scale to > 50% of orig.
dscale_factor = utils::ROT_DS_NONE;
} else if(dscale < 4) {
// Down-scale to between > 25% to <= 50% of orig.
dscale_factor = utils::ROT_DS_HALF;
} else if(dscale < 8) {
// Down-scale to between > 12.5% to <= 25% of orig.
dscale_factor = utils::ROT_DS_FOURTH;
} else {
// Down-scale to <= 12.5% of orig.
dscale_factor = utils::ROT_DS_EIGHTH;
}
}
return dscale_factor;
}
static inline int compute(const uint32_t& x, const uint32_t& y,
const uint32_t& z) {
return x - ( y + z );
}
void preRotateSource(eTransform& tr, Whf& whf, Dim& srcCrop) {
if(tr & OVERLAY_TRANSFORM_FLIP_H) {
srcCrop.x = compute(whf.w, srcCrop.x, srcCrop.w);
}
if(tr & OVERLAY_TRANSFORM_FLIP_V) {
srcCrop.y = compute(whf.h, srcCrop.y, srcCrop.h);
}
if(tr & OVERLAY_TRANSFORM_ROT_90) {
int tmp = srcCrop.x;
srcCrop.x = compute(whf.h,
srcCrop.y,
srcCrop.h);
srcCrop.y = tmp;
swap(whf.w, whf.h);
swap(srcCrop.w, srcCrop.h);
}
tr = OVERLAY_TRANSFORM_0;
}
bool is3DTV() { bool is3DTV() {
char is3DTV = '0'; char is3DTV = '0';
IOFile fp(Res::edid3dInfoFile, "r"); IOFile fp(Res::edid3dInfoFile, "r");

View File

@@ -114,36 +114,6 @@ private:
const NoCopy& operator=(const NoCopy&); const NoCopy& operator=(const NoCopy&);
}; };
/*
* Utility class to query the framebuffer info for primary display
*
* Usage:
* Outside of functions:
* utils::FrameBufferInfo* utils::FrameBufferInfo::sFBInfoInstance = 0;
* Inside functions:
* utils::FrameBufferInfo::getInstance()->supportTrueMirroring()
*/
class FrameBufferInfo {
public:
/* ctor init */
explicit FrameBufferInfo();
/* Gets an instance if one does not already exist */
static FrameBufferInfo* getInstance();
/* Gets width of primary framebuffer */
int getWidth() const;
/* Gets height of primary framebuffer */
int getHeight() const;
private:
int mFBWidth;
int mFBHeight;
bool mBorderFillSupported;
static FrameBufferInfo *sFBInfoInstance;
};
/* 3D related utils, defines etc... /* 3D related utils, defines etc...
* The compound format passed to the overlay is * The compound format passed to the overlay is
@@ -163,18 +133,9 @@ enum { BARRIER_LAND = 1,
int initOverlay(void); int initOverlay(void);
inline uint32_t format3D(uint32_t x) { return x & 0xFF000; } inline uint32_t format3D(uint32_t x) { return x & 0xFF000; }
inline uint32_t colorFormat(uint32_t fmt) {
/*TODO enable this block only if format has interlace / 3D info in top bits.
if(fmt & INTERLACE_MASK) {
fmt = fmt ^ HAL_PIXEL_FORMAT_INTERLACE;
}
fmt = fmt & 0xFFF;*/
return fmt;
}
inline uint32_t format3DOutput(uint32_t x) { inline uint32_t format3DOutput(uint32_t x) {
return (x & 0xF000) >> SHIFT_OUT_3D; } return (x & 0xF000) >> SHIFT_OUT_3D; }
inline uint32_t format3DInput(uint32_t x) { return x & 0xF0000; } inline uint32_t format3DInput(uint32_t x) { return x & 0xF0000; }
uint32_t getColorFormat(uint32_t format);
bool isHDMIConnected (); bool isHDMIConnected ();
bool is3DTV(); bool is3DTV();
@@ -255,10 +216,8 @@ enum { MAX_PATH_LEN = 256 };
/** /**
* Rotator flags: not to be confused with orientation flags. * Rotator flags: not to be confused with orientation flags.
* Ususally, you want to open the rotator to make sure it is * Usually, you want to open the rotator to make sure it is
* ready for business. * ready for business.
* ROT_FLAG_DISABLED: Rotator not used unless required.
* ROT_FLAG_ENABLED: Rotator used even if not required.
* */ * */
enum eRotFlags { enum eRotFlags {
ROT_FLAGS_NONE = 0, ROT_FLAGS_NONE = 0,
@@ -268,6 +227,7 @@ enum { MAX_PATH_LEN = 256 };
//driver. If downscale optimizatation is required, //driver. If downscale optimizatation is required,
//then rotator will be used even if its 0 rotation case. //then rotator will be used even if its 0 rotation case.
ROT_DOWNSCALE_ENABLED = 1 << 1, ROT_DOWNSCALE_ENABLED = 1 << 1,
ROT_PREROTATED = 1 << 2,
}; };
enum eRotDownscale { enum eRotDownscale {
@@ -298,7 +258,6 @@ enum eMdpFlags {
OV_MDP_DEINTERLACE = MDP_DEINTERLACE, OV_MDP_DEINTERLACE = MDP_DEINTERLACE,
OV_MDP_SECURE_OVERLAY_SESSION = MDP_SECURE_OVERLAY_SESSION, OV_MDP_SECURE_OVERLAY_SESSION = MDP_SECURE_OVERLAY_SESSION,
OV_MDP_SOURCE_ROTATED_90 = MDP_SOURCE_ROTATED_90, OV_MDP_SOURCE_ROTATED_90 = MDP_SOURCE_ROTATED_90,
OV_MDP_MEMORY_ID_TYPE_FB = MDP_MEMORY_ID_TYPE_FB,
OV_MDP_BACKEND_COMPOSITION = MDP_BACKEND_COMPOSITION, OV_MDP_BACKEND_COMPOSITION = MDP_BACKEND_COMPOSITION,
OV_MDP_BLEND_FG_PREMULT = MDP_BLEND_FG_PREMULT, OV_MDP_BLEND_FG_PREMULT = MDP_BLEND_FG_PREMULT,
OV_MDP_FLIP_H = MDP_FLIP_LR, OV_MDP_FLIP_H = MDP_FLIP_LR,
@@ -307,7 +266,7 @@ enum eMdpFlags {
}; };
enum eZorder { enum eZorder {
ZORDER_0, ZORDER_0 = 0,
ZORDER_1, ZORDER_1,
ZORDER_2, ZORDER_2,
ZORDER_3, ZORDER_3,
@@ -422,6 +381,8 @@ struct ScreenInfo {
int getMdpFormat(int format); int getMdpFormat(int format);
int getHALFormat(int mdpFormat); int getHALFormat(int mdpFormat);
int getDownscaleFactor(const int& src_w, const int& src_h,
const int& dst_w, const int& dst_h);
/* flip is upside down and such. V, H flip /* flip is upside down and such. V, H flip
* rotation is 90, 180 etc * rotation is 90, 180 etc
@@ -597,12 +558,6 @@ inline int getMdpOrient(eTransform rotation) {
return -1; return -1;
} }
inline uint32_t getColorFormat(uint32_t format)
{
return (format == HAL_PIXEL_FORMAT_YV12) ?
format : colorFormat(format);
}
// FB0 // FB0
template <int CHAN> template <int CHAN>
inline Dim getPositionS3DImpl(const Whf& whf) inline Dim getPositionS3DImpl(const Whf& whf)
@@ -766,6 +721,7 @@ inline eMdpPipeType getPipeType(eDest dest) {
return OV_MDP_PIPE_ANY; return OV_MDP_PIPE_ANY;
} }
void preRotateSource(eTransform& tr, Whf& whf, Dim& srcCrop);
void getDump(char *buf, size_t len, const char *prefix, const mdp_overlay& ov); void getDump(char *buf, size_t len, const char *prefix, const mdp_overlay& ov);
void getDump(char *buf, size_t len, const char *prefix, const msmfb_img& ov); void getDump(char *buf, size_t len, const char *prefix, const msmfb_img& ov);
void getDump(char *buf, size_t len, const char *prefix, const mdp_rect& ov); void getDump(char *buf, size_t len, const char *prefix, const mdp_rect& ov);

View File

@@ -34,7 +34,7 @@
namespace overlay { namespace overlay {
GenericPipe::GenericPipe(int dpy) : mFbNum(dpy), mRot(0), mRotUsed(false), GenericPipe::GenericPipe(int dpy) : mFbNum(dpy), mRot(0), mRotUsed(false),
mRotDownscaleOpt(false), pipeState(CLOSED) { mRotDownscaleOpt(false), mPreRotated(false), pipeState(CLOSED) {
init(); init();
} }
@@ -47,6 +47,7 @@ bool GenericPipe::init()
ALOGE_IF(DEBUG_OVERLAY, "GenericPipe init"); ALOGE_IF(DEBUG_OVERLAY, "GenericPipe init");
mRotUsed = false; mRotUsed = false;
mRotDownscaleOpt = false; mRotDownscaleOpt = false;
mPreRotated = false;
if(mFbNum) if(mFbNum)
mFbNum = Overlay::getInstance()->getExtFbNum(); mFbNum = Overlay::getInstance()->getExtFbNum();
@@ -87,54 +88,31 @@ bool GenericPipe::close() {
return ret; return ret;
} }
bool GenericPipe::setSource( void GenericPipe::setSource(const utils::PipeArgs& args) {
const utils::PipeArgs& args)
{
utils::PipeArgs newargs(args);
//Interlace video handling.
if(newargs.whf.format & INTERLACE_MASK) {
setMdpFlags(newargs.mdpFlags, utils::OV_MDP_DEINTERLACE);
}
utils::Whf whf(newargs.whf);
//Extract HAL format from lower bytes. Deinterlace if interlaced.
whf.format = utils::getColorFormat(whf.format);
//Get MDP equivalent of HAL format.
whf.format = utils::getMdpFormat(whf.format);
newargs.whf = whf;
//Cache if user wants 0-rotation //Cache if user wants 0-rotation
mRotUsed = newargs.rotFlags & utils::ROT_0_ENABLED; mRotUsed = args.rotFlags & utils::ROT_0_ENABLED;
mRotDownscaleOpt = newargs.rotFlags & utils::ROT_DOWNSCALE_ENABLED; mRotDownscaleOpt = args.rotFlags & utils::ROT_DOWNSCALE_ENABLED;
mPreRotated = args.rotFlags & utils::ROT_PREROTATED;
mRot->setSource(newargs.whf); if(mPreRotated) mRotUsed = false;
mRot->setFlags(newargs.mdpFlags); mRot->setSource(args.whf);
return mCtrlData.ctrl.setSource(newargs); mRot->setFlags(args.mdpFlags);
mCtrlData.ctrl.setSource(args);
} }
bool GenericPipe::setCrop( void GenericPipe::setCrop(const overlay::utils::Dim& d) {
const overlay::utils::Dim& d) { mCtrlData.ctrl.setCrop(d);
return mCtrlData.ctrl.setCrop(d);
} }
bool GenericPipe::setTransform( void GenericPipe::setTransform(const utils::eTransform& orient) {
const utils::eTransform& orient)
{
//Rotation could be enabled by user for zero-rot or the layer could have //Rotation could be enabled by user for zero-rot or the layer could have
//some transform. Mark rotation enabled in either case. //some transform. Mark rotation enabled in either case.
mRotUsed |= (orient != utils::OVERLAY_TRANSFORM_0); mRotUsed |= ((orient & utils::OVERLAY_TRANSFORM_ROT_90) && !mPreRotated);
mRot->setTransform(orient); mRot->setTransform(orient);
mCtrlData.ctrl.setTransform(orient);
return mCtrlData.ctrl.setTransform(orient);
} }
bool GenericPipe::setPosition(const utils::Dim& d) void GenericPipe::setPosition(const utils::Dim& d) {
{ mCtrlData.ctrl.setPosition(d);
return mCtrlData.ctrl.setPosition(d);
}
void GenericPipe::setRotatorUsed(const bool& rotUsed) {
mRot->setRotatorUsed(rotUsed);
mCtrlData.ctrl.setRotatorUsed(rotUsed);
} }
bool GenericPipe::commit() { bool GenericPipe::commit() {
@@ -142,20 +120,16 @@ bool GenericPipe::commit() {
int downscale_factor = utils::ROT_DS_NONE; int downscale_factor = utils::ROT_DS_NONE;
if(mRotDownscaleOpt) { if(mRotDownscaleOpt) {
/* Can go ahead with calculation of downscale_factor since ovutils::Dim src(mCtrlData.ctrl.getCrop());
* we consider area when calculating it */ ovutils::Dim dst(mCtrlData.ctrl.getPosition());
downscale_factor = mCtrlData.ctrl.getDownscalefactor(); downscale_factor = ovutils::getDownscaleFactor(
if(downscale_factor) src.w, src.h, dst.w, dst.h);
mRotUsed = true; mRotUsed |= (downscale_factor && !mPreRotated);
} }
setRotatorUsed(mRotUsed);
mCtrlData.ctrl.doTransform();
mCtrlData.ctrl.doDownscale(downscale_factor);
mRot->setDownscale(downscale_factor);
if(mRotUsed) { if(mRotUsed) {
mRot->setDownscale(downscale_factor);
//If wanting to use rotator, start it. //If wanting to use rotator, start it.
if(!mRot->commit()) { if(!mRot->commit()) {
ALOGE("GenPipe Rotator commit failed"); ALOGE("GenPipe Rotator commit failed");
@@ -170,9 +144,10 @@ bool GenericPipe::commit() {
* The output format of the rotator might be different depending on * The output format of the rotator might be different depending on
* whether fastyuv mode is enabled in the rotator. * whether fastyuv mode is enabled in the rotator.
*/ */
mCtrlData.ctrl.updateSrcformat(mRot->getDstFormat()); mCtrlData.ctrl.updateSrcFormat(mRot->getDstFormat());
} }
mCtrlData.ctrl.setDownscale(downscale_factor);
ret = mCtrlData.ctrl.commit(); ret = mCtrlData.ctrl.commit();
//If mdp commit fails, flush rotator session, memory, fd and create a hollow //If mdp commit fails, flush rotator session, memory, fd and create a hollow
@@ -220,11 +195,6 @@ int GenericPipe::getCtrlFd() const {
return mCtrlData.ctrl.getFd(); return mCtrlData.ctrl.getFd();
} }
utils::ScreenInfo GenericPipe::getScreenInfo() const
{
return mCtrlData.ctrl.getScreenInfo();
}
utils::Dim GenericPipe::getCrop() const utils::Dim GenericPipe::getCrop() const
{ {
return mCtrlData.ctrl.getCrop(); return mCtrlData.ctrl.getCrop();

View File

@@ -43,48 +43,34 @@ public:
explicit GenericPipe(int dpy); explicit GenericPipe(int dpy);
/* dtor */ /* dtor */
~GenericPipe(); ~GenericPipe();
/* CTRL/DATA init. Not owning rotator, will not init it */
bool init(); bool init();
/* CTRL/DATA close. Not owning rotator, will not close it */
bool close(); bool close();
/* Control APIs */ /* Control APIs */
/* set source using whf, orient and wait flag */ /* set source using whf, orient and wait flag */
bool setSource(const utils::PipeArgs& args); void setSource(const utils::PipeArgs& args);
/* set crop a.k.a the region of interest */ /* set crop a.k.a the region of interest */
bool setCrop(const utils::Dim& d); void setCrop(const utils::Dim& d);
/* set orientation*/ /* set orientation*/
bool setTransform(const utils::eTransform& param); void setTransform(const utils::eTransform& param);
/* set mdp posision using dim */ /* set mdp posision using dim */
bool setPosition(const utils::Dim& dim); void setPosition(const utils::Dim& dim);
/* commit changes to the overlay "set"*/ /* commit changes to the overlay "set"*/
bool commit(); bool commit();
/* Data APIs */ /* Data APIs */
/* queue buffer to the overlay */ /* queue buffer to the overlay */
bool queueBuffer(int fd, uint32_t offset); bool queueBuffer(int fd, uint32_t offset);
/* return cached startup args */ /* return cached startup args */
const utils::PipeArgs& getArgs() const; const utils::PipeArgs& getArgs() const;
/* retrieve screen info */
utils::ScreenInfo getScreenInfo() const;
/* retrieve cached crop data */ /* retrieve cached crop data */
utils::Dim getCrop() const; utils::Dim getCrop() const;
/* is closed */ /* is closed */
bool isClosed() const; bool isClosed() const;
/* is open */ /* is open */
bool isOpen() const; bool isOpen() const;
/* return Ctrl fd. Used for S3D */ /* return Ctrl fd. Used for S3D */
int getCtrlFd() const; int getCtrlFd() const;
/* dump the state of the object */ /* dump the state of the object */
void dump() const; void dump() const;
/* Return the dump in the specified buffer */ /* Return the dump in the specified buffer */
void getDump(char *buf, size_t len); void getDump(char *buf, size_t len);
@@ -92,23 +78,17 @@ private:
/* set Closed pipe */ /* set Closed pipe */
bool setClosed(); bool setClosed();
/* Set whether rotator can be used */
void setRotatorUsed(const bool& rotUsed);
int mFbNum; int mFbNum;
/* Ctrl/Data aggregator */ /* Ctrl/Data aggregator */
CtrlData mCtrlData; CtrlData mCtrlData;
Rotator* mRot; Rotator* mRot;
//Whether rotator is used for 0-rot or otherwise //Whether rotator is used for 0-rot or otherwise
bool mRotUsed; bool mRotUsed;
//Whether we will do downscale opt. This is just a request. If the frame is //Whether we will do downscale opt. This is just a request. If the frame is
//not a candidate, we might not do it. //not a candidate, we might not do it.
bool mRotDownscaleOpt; bool mRotDownscaleOpt;
//Whether the source is prerotated.
bool mPreRotated;
/* Pipe open or closed */ /* Pipe open or closed */
enum ePipeState { enum ePipeState {
CLOSED, CLOSED,