msm: display: plane alpha support

Clean up the blending rule to follow blend_op set from hwc.
Use modulate alpha for plane alpha when it is not 0xff.
Keep backward compatibility if blend_op is not set.

Change-Id: I02fd3c3c7b5ace2e6eec22b2db0284161404a0fc
Signed-off-by: Ken Zhang <kenz@codeaurora.org>
Signed-off-by: Naseer Ahmed <naseer@codeaurora.org>
This commit is contained in:
Naseer Ahmed 2013-04-11 20:06:06 -04:00 committed by Iliyan Malchev
parent 5e233e2b90
commit d25a3ce0e5
2 changed files with 112 additions and 46 deletions

View file

@ -2056,57 +2056,59 @@ void mdp4_mixer_blend_cfg(int mixer)
}
}
/*
* D(i+1) = Ks * S + Kd * D(i)
*/
void mdp4_mixer_blend_setup(int mixer)
static void mdp4_set_blend_by_op(struct mdp4_overlay_pipe *s_pipe,
struct mdp4_overlay_pipe *d_pipe,
int alpha_drop,
struct blend_cfg *blend)
{
struct mdp4_overlay_pipe *d_pipe;
struct mdp4_overlay_pipe *s_pipe;
struct blend_cfg *blend;
int i, off, ptype, alpha_drop;
int d_alpha, s_alpha;
unsigned char *overlay_base;
uint32 c0, c1, c2;
u32 op;
d_pipe = ctrl->stage[mixer][MDP4_MIXER_STAGE_BASE];
if (d_pipe == NULL) {
pr_err("%s: Error: no bg_pipe at mixer=%d\n", __func__, mixer);
return;
}
blend = &ctrl->blend[mixer][MDP4_MIXER_STAGE0];
for (i = MDP4_MIXER_STAGE0; i < MDP4_MIXER_STAGE_MAX; i++) {
blend->solidfill = 0;
blend->op = (MDP4_BLEND_FG_ALPHA_FG_CONST |
MDP4_BLEND_BG_ALPHA_BG_CONST);
s_pipe = ctrl->stage[mixer][i];
if (s_pipe == NULL) {
blend++;
d_pipe = NULL;
d_alpha = 0;
continue;
}
alpha_drop = 0; /* per stage */
/* alpha channel is lost on VG pipe when using QSEED or M/N */
if (s_pipe->pipe_type == OVERLAY_TYPE_VIDEO &&
s_pipe->alpha_enable &&
((s_pipe->op_mode & MDP4_OP_SCALEY_EN) ||
(s_pipe->op_mode & MDP4_OP_SCALEX_EN)) &&
!(s_pipe->op_mode & (MDP4_OP_SCALEX_PIXEL_RPT |
MDP4_OP_SCALEY_PIXEL_RPT)))
alpha_drop = 1;
d_pipe = mdp4_background_layer(mixer, s_pipe);
d_alpha = d_pipe->alpha_enable;
s_alpha = s_pipe->alpha_enable;
pr_debug("%s: stage=%d: bg: ndx=%d da=%d dalpha=%x "
"fg: ndx=%d sa=%d salpha=%x is_fg=%d alpha_drop=%d\n",
__func__, i-2, d_pipe->pipe_ndx, d_alpha, d_pipe->alpha,
s_pipe->pipe_ndx, s_alpha, s_pipe->alpha, s_pipe->is_fg,
alpha_drop);
/* base on fg's alpha */
blend->fg_alpha = s_pipe->alpha;
blend->bg_alpha = 0x0ff - s_pipe->alpha;
blend->op = MDP4_BLEND_FG_ALPHA_FG_CONST |
MDP4_BLEND_BG_ALPHA_BG_CONST;
blend->co3_sel = 1; /* use fg alpha */
op = s_pipe->blend_op;
if (op == BLEND_OP_OPAQUE) {
blend->bg_alpha = 0;
blend->fg_alpha = 0xff;
} else if ((op == BLEND_OP_PREMULTIPLIED) &&
(!alpha_drop) && s_alpha) {
blend->op = MDP4_BLEND_FG_ALPHA_FG_CONST |
MDP4_BLEND_BG_INV_ALPHA |
MDP4_BLEND_BG_ALPHA_FG_PIXEL;
if (blend->fg_alpha != 0xff) {
blend->bg_alpha = blend->fg_alpha;
blend->op |= MDP4_BLEND_BG_MOD_ALPHA;
}
} else if (!alpha_drop && s_alpha) {
blend->op = MDP4_BLEND_FG_ALPHA_FG_PIXEL |
MDP4_BLEND_BG_INV_ALPHA |
MDP4_BLEND_BG_ALPHA_FG_PIXEL;
if (blend->fg_alpha != 0xff) {
blend->bg_alpha = blend->fg_alpha;
blend->op |= MDP4_BLEND_FG_MOD_ALPHA |
MDP4_BLEND_BG_MOD_ALPHA;
}
}
if (!s_alpha && d_alpha)
blend->co3_sel = 0;
pr_debug("%s: op %d bg alpha %d, fg alpha %d blend: %x\n",
__func__, op, blend->bg_alpha, blend->fg_alpha, blend->op);
}
static void mdp4_set_blend_by_fmt(struct mdp4_overlay_pipe *s_pipe,
struct mdp4_overlay_pipe *d_pipe,
int alpha_drop,
struct blend_cfg *blend)
{
int ptype, d_alpha, s_alpha;
d_alpha = d_pipe->alpha_enable;
s_alpha = s_pipe->alpha_enable;
/* base on fg's alpha */
blend->bg_alpha = 0x0ff - s_pipe->alpha;
blend->fg_alpha = s_pipe->alpha;
@ -2144,6 +2146,60 @@ void mdp4_mixer_blend_setup(int mixer)
blend->bg_alpha = 0;
}
}
}
/*
* D(i+1) = Ks * S + Kd * D(i)
*/
void mdp4_mixer_blend_setup(int mixer)
{
struct mdp4_overlay_pipe *d_pipe;
struct mdp4_overlay_pipe *s_pipe;
struct blend_cfg *blend;
int i, off, alpha_drop;
unsigned char *overlay_base;
uint32 c0, c1, c2;
d_pipe = ctrl->stage[mixer][MDP4_MIXER_STAGE_BASE];
if (d_pipe == NULL) {
pr_err("%s: Error: no bg_pipe at mixer=%d\n", __func__, mixer);
return;
}
blend = &ctrl->blend[mixer][MDP4_MIXER_STAGE0];
for (i = MDP4_MIXER_STAGE0; i < MDP4_MIXER_STAGE_MAX; i++) {
blend->solidfill = 0;
blend->op = (MDP4_BLEND_FG_ALPHA_FG_CONST |
MDP4_BLEND_BG_ALPHA_BG_CONST);
s_pipe = ctrl->stage[mixer][i];
if (s_pipe == NULL) {
blend++;
d_pipe = NULL;
continue;
}
alpha_drop = 0; /* per stage */
/* alpha channel is lost on VG pipe when using QSEED or M/N */
if (s_pipe->pipe_type == OVERLAY_TYPE_VIDEO &&
s_pipe->alpha_enable &&
((s_pipe->op_mode & MDP4_OP_SCALEY_EN) ||
(s_pipe->op_mode & MDP4_OP_SCALEX_EN)) &&
!(s_pipe->op_mode & (MDP4_OP_SCALEX_PIXEL_RPT |
MDP4_OP_SCALEY_PIXEL_RPT)))
alpha_drop = 1;
d_pipe = mdp4_background_layer(mixer, s_pipe);
pr_debug("%s: stage=%d: bg: ndx=%d da=%d dalpha=%x "
"fg: ndx=%d sa=%d salpha=%x is_fg=%d alpha_drop=%d\n",
__func__, i-2, d_pipe->pipe_ndx, d_pipe->alpha_enable,
d_pipe->alpha, s_pipe->pipe_ndx, s_pipe->alpha_enable,
s_pipe->alpha, s_pipe->is_fg, alpha_drop);
if ((s_pipe->blend_op == BLEND_OP_NOT_DEFINED) ||
(s_pipe->blend_op >= BLEND_OP_MAX))
mdp4_set_blend_by_fmt(s_pipe, d_pipe,
alpha_drop, blend);
else
mdp4_set_blend_by_op(s_pipe, d_pipe, alpha_drop, blend);
if (s_pipe->transp != MDP_TRANSP_NOP) {
if (s_pipe->is_fg) {
@ -2579,6 +2635,7 @@ static int mdp4_overlay_req2pipe(struct mdp_overlay *req, int mixer,
pipe->is_fg = req->is_fg;/* control alpha and color key */
pipe->alpha = req->alpha & 0x0ff;
pipe->blend_op = req->blend_op;
pipe->transp = req->transp_mask;

View file

@ -350,6 +350,14 @@ struct mdp_overlay_pp_params {
struct mdp_sharp_cfg sharp_cfg;
};
enum {
BLEND_OP_NOT_DEFINED = 0,
BLEND_OP_OPAQUE,
BLEND_OP_PREMULTIPLIED,
BLEND_OP_COVERAGE,
BLEND_OP_MAX,
};
struct mdp_overlay {
struct msmfb_img src;
struct mdp_rect src_rect;
@ -358,6 +366,7 @@ struct mdp_overlay {
uint32_t is_fg; /* control alpha & transp */
uint32_t alpha;
uint32_t transp_mask;
uint32_t blend_op;
uint32_t flags;
uint32_t id;
uint32_t user_data[8];