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

@@ -25,9 +25,11 @@
#include <gralloc_priv.h>
#include <fb_priv.h>
#include <overlay.h>
#include <overlayRotator.h>
#include "hwc_utils.h"
#include "hwc_mdpcomp.h"
#include "hwc_fbupdate.h"
#include "hwc_video.h"
#include "mdp_version.h"
#include "hwc_copybit.h"
#include "external.h"
@@ -38,6 +40,9 @@
using namespace qClient;
using namespace qService;
using namespace android;
using namespace overlay;
using namespace overlay::utils;
namespace ovutils = overlay::utils;
namespace qhwc {
@@ -67,6 +72,7 @@ void initContext(hwc_context_t *ctx)
openFramebufferDevice(ctx);
overlay::Overlay::initOverlay();
ctx->mOverlay = overlay::Overlay::getInstance();
ctx->mRotMgr = new RotMgr();
ctx->mMDP.version = qdutils::MDPVersion::getInstance().getMDPVersion();
ctx->mMDP.hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay();
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,
HWC_DISPLAY_PRIMARY);
ctx->mVidOv[HWC_DISPLAY_PRIMARY] =
IVideoOverlay::getObject(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres,
HWC_DISPLAY_PRIMARY);
char value[PROPERTY_VALUE_MAX];
// Check if the target supports copybit compostion (dyn/mdp/c2d) to
// decide if we need to open the copybit module.
@@ -120,6 +130,11 @@ void closeContext(hwc_context_t *ctx)
ctx->mOverlay = NULL;
}
if(ctx->mRotMgr) {
delete ctx->mRotMgr;
ctx->mRotMgr = NULL;
}
for(int i = 0; i < MAX_DISPLAYS; i++) {
if(ctx->mCopyBit[i]) {
delete ctx->mCopyBit[i];
@@ -144,6 +159,10 @@ void closeContext(hwc_context_t *ctx)
delete ctx->mFBUpdate[i];
ctx->mFBUpdate[i] = NULL;
}
if(ctx->mVidOv[i]) {
delete ctx->mVidOv[i];
ctx->mVidOv[i] = NULL;
}
}
if(ctx->mMDPComp) {
@@ -492,6 +511,263 @@ int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy,
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) {
for(uint32_t i = 0; i < MAX_NUM_LAYERS; i++) {
hnd[i] = NULL;
@@ -556,7 +832,6 @@ void LayerCache::markCachedLayersAsOverlay(hwc_display_contents_1_t* list) {
}
}
}
}
};//namespace
};//namespace qhwc