hwc: Add support for plane alpha
HWC 1.2 API passes down the plane alpha and the blending
operation to apply. Pass this information to the MDP.
Change-Id: I7fbd17345d9157aa654e4b1031ac3e26adf87f37
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index f90420f..4b0ff9a 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -751,7 +751,7 @@
//Setup HWC methods
dev->device.common.tag = HARDWARE_DEVICE_TAG;
- dev->device.common.version = HWC_DEVICE_API_VERSION_1_1;
+ dev->device.common.version = HWC_DEVICE_API_VERSION_1_2;
dev->device.common.module = const_cast<hw_module_t*>(module);
dev->device.common.close = hwc_device_close;
dev->device.prepare = hwc_prepare;
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index ba3b5d2..79baa90 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -171,7 +171,10 @@
orient = ovutils::OVERLAY_TRANSFORM_0;
transform = 0;
ovutils::PipeArgs parg(mdpFlags, info, zOrder, isFg,
- static_cast<ovutils::eRotFlags>(rotFlags));
+ static_cast<ovutils::eRotFlags>(rotFlags),
+ ovutils::DEFAULT_PLANE_ALPHA,
+ (ovutils::eBlending)
+ getBlending(layer->blending));
ret = true;
if(configMdp(ctx->mOverlay, parg, orient, sourceCrop, displayFrame,
NULL, mDest) < 0) {
@@ -268,11 +271,16 @@
ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder);
+ //XXX: FB layer plane alpha is currently sent as zero from
+ //surfaceflinger
ovutils::PipeArgs pargL(mdpFlagsL,
info,
zOrder,
ovutils::IS_FG_OFF,
- ovutils::ROT_FLAGS_NONE);
+ ovutils::ROT_FLAGS_NONE,
+ ovutils::DEFAULT_PLANE_ALPHA,
+ (ovutils::eBlending)
+ getBlending(layer->blending));
ov.setSource(pargL, destL);
ovutils::eMdpFlags mdpFlagsR = mdpFlagsL;
@@ -281,7 +289,10 @@
info,
zOrder,
ovutils::IS_FG_OFF,
- ovutils::ROT_FLAGS_NONE);
+ ovutils::ROT_FLAGS_NONE,
+ ovutils::DEFAULT_PLANE_ALPHA,
+ (ovutils::eBlending)
+ getBlending(layer->blending));
ov.setSource(pargR, destR);
hwc_rect_t sourceCrop = layer->sourceCrop;
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 0e2eb2e..01e4c6d 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -545,6 +545,18 @@
return false;
}
+int getBlending(int blending) {
+ switch(blending) {
+ case HWC_BLENDING_NONE:
+ return overlay::utils::OVERLAY_BLENDING_OPAQUE;
+ case HWC_BLENDING_PREMULT:
+ return overlay::utils::OVERLAY_BLENDING_PREMULT;
+ case HWC_BLENDING_COVERAGE :
+ default:
+ return overlay::utils::OVERLAY_BLENDING_COVERAGE;
+ }
+}
+
//Crops source buffer against destination and FB boundaries
void calculate_crop_rects(hwc_rect_t& crop, hwc_rect_t& dst,
const hwc_rect_t& scissor, int orient) {
@@ -1035,7 +1047,10 @@
//For the mdp, since either we are pre-rotating or MDP does flips
orient = OVERLAY_TRANSFORM_0;
transform = 0;
- PipeArgs parg(mdpFlags, whf, z, isFg, static_cast<eRotFlags>(rotFlags));
+ PipeArgs parg(mdpFlags, whf, z, isFg,
+ static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
+ (ovutils::eBlending) getBlending(layer->blending));
+
if(configMdp(ctx->mOverlay, parg, orient, crop, dst, metadata, dest) < 0) {
ALOGE("%s: commit failed for low res panel", __FUNCTION__);
return -1;
@@ -1164,7 +1179,9 @@
//configure left mixer
if(lDest != OV_INVALID) {
PipeArgs pargL(mdpFlagsL, whf, z, isFg,
- static_cast<eRotFlags>(rotFlags));
+ static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
+ (ovutils::eBlending) getBlending(layer->blending));
+
if(configMdp(ctx->mOverlay, pargL, orient,
tmp_cropL, tmp_dstL, metadata, lDest) < 0) {
ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
@@ -1175,7 +1192,9 @@
//configure right mixer
if(rDest != OV_INVALID) {
PipeArgs pargR(mdpFlagsR, whf, z, isFg,
- static_cast<eRotFlags>(rotFlags));
+ static_cast<eRotFlags>(rotFlags),
+ layer->planeAlpha,
+ (ovutils::eBlending) getBlending(layer->blending));
tmp_dstR.right = tmp_dstR.right - lSplit;
tmp_dstR.left = tmp_dstR.left - lSplit;
if(configMdp(ctx->mOverlay, pargR, orient,
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 7b39ae5..b51fec4 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -170,6 +170,7 @@
bool needsScaling(hwc_context_t* ctx, hwc_layer_1_t const* layer, const int& dpy);
bool isAlphaPresent(hwc_layer_1_t const* layer);
int hwc_vsync_control(hwc_context_t* ctx, int dpy, int enable);
+int getBlending(int blending);
//Helper function to dump logs
void dumpsys_log(android::String8& buf, const char* fmt, ...);
@@ -275,8 +276,7 @@
void init_vsync_thread(hwc_context_t* ctx);
inline void getLayerResolution(const hwc_layer_1_t* layer,
- int& width, int& height)
-{
+ int& width, int& height) {
hwc_rect_t displayFrame = layer->displayFrame;
width = displayFrame.right - displayFrame.left;
height = displayFrame.bottom - displayFrame.top;
diff --git a/liboverlay/overlayMdp.cpp b/liboverlay/overlayMdp.cpp
index 2d88376..674e62d 100644
--- a/liboverlay/overlayMdp.cpp
+++ b/liboverlay/overlayMdp.cpp
@@ -94,13 +94,14 @@
setSrcWhf(args.whf);
//TODO These are hardcoded. Can be moved out of setSource.
- mOVInfo.alpha = 0xff;
mOVInfo.transp_mask = 0xffffffff;
//TODO These calls should ideally be a part of setPipeParams API
setFlags(args.mdpFlags);
setZ(args.zorder);
setIsFg(args.isFg);
+ setPlaneAlpha(args.planeAlpha);
+ setBlending(args.blending);
}
void MdpCtrl::setCrop(const utils::Dim& d) {
diff --git a/liboverlay/overlayMdp.h b/liboverlay/overlayMdp.h
index 056d982..5bfec6b 100644
--- a/liboverlay/overlayMdp.h
+++ b/liboverlay/overlayMdp.h
@@ -99,8 +99,13 @@
void setZ(utils::eZorder z);
/* set isFg flag */
void setIsFg(utils::eIsFg isFg);
- /* return a copy of src whf*/
+ /* return a copy of src whf*/
utils::Whf getSrcWhf() const;
+ /* set plane alpha */
+ void setPlaneAlpha(int planeAlpha);
+ /* set blending method */
+ void setBlending(overlay::utils::eBlending blending);
+
/* set src whf */
void setSrcWhf(const utils::Whf& whf);
/* set src/dst rect dim */
@@ -241,6 +246,24 @@
mDownscale = dscale;
}
+inline void MdpCtrl::setPlaneAlpha(int planeAlpha) {
+ mOVInfo.alpha = planeAlpha;
+}
+
+inline void MdpCtrl::setBlending(overlay::utils::eBlending blending) {
+ switch((int) blending) {
+ case utils::OVERLAY_BLENDING_OPAQUE:
+ mOVInfo.blend_op = BLEND_OP_OPAQUE;
+ break;
+ case utils::OVERLAY_BLENDING_PREMULT:
+ mOVInfo.blend_op = BLEND_OP_PREMULTIPLIED;
+ break;
+ case utils::OVERLAY_BLENDING_COVERAGE:
+ default:
+ mOVInfo.blend_op = BLEND_OP_COVERAGE;
+ }
+}
+
inline bool MdpCtrl::ovChanged() const {
#ifdef USES_POST_PROCESSING
// Some pp params are stored as pointer address,
diff --git a/liboverlay/overlayUtils.h b/liboverlay/overlayUtils.h
index b543018..e49a50c 100644
--- a/liboverlay/overlayUtils.h
+++ b/liboverlay/overlayUtils.h
@@ -212,6 +212,8 @@
enum { MAX_PATH_LEN = 256 };
+enum { DEFAULT_PLANE_ALPHA = 0xFF };
+
/**
* Rotator flags: not to be confused with orientation flags.
* Usually, you want to open the rotator to make sure it is
@@ -329,21 +331,36 @@
OVERLAY_TRANSFORM_INV = 0x80
};
+enum eBlending {
+ OVERLAY_BLENDING_UNDEFINED = 0x0,
+ /* No blending */
+ OVERLAY_BLENDING_OPAQUE,
+ /* src.rgb + dst.rgb*(1-src_alpha) */
+ OVERLAY_BLENDING_PREMULT,
+ /* src.rgb * src_alpha + dst.rgb (1 - src_alpha) */
+ OVERLAY_BLENDING_COVERAGE,
+};
+
// Used to consolidate pipe params
struct PipeArgs {
PipeArgs() : mdpFlags(OV_MDP_FLAGS_NONE),
zorder(Z_SYSTEM_ALLOC),
isFg(IS_FG_OFF),
- rotFlags(ROT_FLAGS_NONE){
+ rotFlags(ROT_FLAGS_NONE),
+ planeAlpha(DEFAULT_PLANE_ALPHA),
+ blending(OVERLAY_BLENDING_COVERAGE){
}
PipeArgs(eMdpFlags f, Whf _whf,
- eZorder z, eIsFg fg, eRotFlags r) :
+ eZorder z, eIsFg fg, eRotFlags r,
+ int pA = DEFAULT_PLANE_ALPHA, eBlending b = OVERLAY_BLENDING_COVERAGE) :
mdpFlags(f),
whf(_whf),
zorder(z),
isFg(fg),
- rotFlags(r) {
+ rotFlags(r),
+ planeAlpha(pA),
+ blending(b){
}
eMdpFlags mdpFlags; // for mdp_overlay flags
@@ -351,6 +368,8 @@
eZorder zorder; // stage number
eIsFg isFg; // control alpha & transp
eRotFlags rotFlags;
+ int planeAlpha;
+ eBlending blending;
};
// Cannot use HW_OVERLAY_MAGNIFICATION_LIMIT, since at the time