Commit e7308b6c authored by Dave Airlie's avatar Dave Airlie Committed by Eric Anholt

glamor: Add support for CA rendering in a single pass.

It's been on the list to add dual source blending support to avoid the
two pass componentAlpha code.  Radeon has done this for a while in
EXA, so let's add support to bring glamor up to using it.

This adds dual blend to both render and composite glyphs paths.

Initial results show close to doubling of speed of x11perf -rgb10text.

v2: Fix breakage of all of CA acceleration for systems without
    GL_ARB_blend_func_extended.  Add CA support for all the ops we
    support in non-CA mode when blend_func_extended is present.  Clean
    up some comments and formatting.  (changes by anholt)
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
Signed-off-by: Eric Anholt's avatarEric Anholt <eric@anholt.net>
parent cab14a9a
......@@ -576,6 +576,8 @@ glamor_init(ScreenPtr screen, unsigned int flags)
epoxy_has_gl_extension("GL_NV_pack_subimage");
glamor_priv->has_vertex_array_object =
epoxy_has_gl_extension("GL_ARB_vertex_array_object");
glamor_priv->has_dual_blend =
epoxy_has_gl_extension("GL_ARB_blend_func_extended");
glamor_setup_debug_output(screen);
......
......@@ -186,7 +186,9 @@ static const glamor_facet glamor_facet_composite_glyphs_130 = {
.vs_exec = (" vec2 pos = primitive.zw * vec2(gl_VertexID&1, (gl_VertexID&2)>>1);\n"
GLAMOR_POS(gl_Position, (primitive.xy + pos))
" glyph_pos = (source + pos) * ATLAS_DIM_INV;\n"),
.fs_vars = ("varying vec2 glyph_pos;\n"),
.fs_vars = ("varying vec2 glyph_pos;\n"
"out vec4 color0;\n"
"out vec4 color1;\n"),
.fs_exec = (" vec4 mask = texture2D(atlas, glyph_pos);\n"),
.source_name = "source",
.locations = glamor_program_location_atlas,
......
......@@ -86,6 +86,12 @@ typedef struct glamor_composite_shader {
};
} glamor_composite_shader;
enum ca_state {
CA_NONE,
CA_TWO_PASS,
CA_DUAL_BLEND,
};
enum shader_source {
SHADER_SOURCE_SOLID,
SHADER_SOURCE_TEXTURE,
......@@ -106,6 +112,7 @@ enum shader_in {
SHADER_IN_NORMAL,
SHADER_IN_CA_SOURCE,
SHADER_IN_CA_ALPHA,
SHADER_IN_CA_DUAL_BLEND,
SHADER_IN_COUNT,
};
......@@ -202,6 +209,7 @@ typedef struct glamor_screen_private {
Bool has_rw_pbo;
Bool use_quads;
Bool has_vertex_array_object;
Bool has_dual_blend;
int max_fbo_size;
struct xorg_list
......
......@@ -344,6 +344,10 @@ glamor_build_program(ScreenPtr screen,
#endif
glBindAttribLocation(prog->prog, GLAMOR_VERTEX_SOURCE, prim->source_name);
}
if (prog->alpha == glamor_program_alpha_dual_blend) {
glBindFragDataLocationIndexed(prog->prog, 0, 0, "color0");
glBindFragDataLocationIndexed(prog->prog, 0, 1, "color1");
}
glamor_link_glsl_prog(screen, prog->prog, "%s_%s", prim->name, fill->name);
......@@ -474,11 +478,24 @@ glamor_set_blend(CARD8 op, glamor_program_alpha alpha, PicturePtr dst)
}
/* Set up the source alpha value for blending in component alpha mode. */
if (alpha != glamor_program_alpha_normal && op_info->source_alpha) {
if (dst_blend == GL_SRC_ALPHA)
if (alpha == glamor_program_alpha_dual_blend) {
switch (dst_blend) {
case GL_SRC_ALPHA:
dst_blend = GL_SRC1_COLOR;
break;
case GL_ONE_MINUS_SRC_ALPHA:
dst_blend = GL_ONE_MINUS_SRC1_COLOR;
break;
}
} else if (alpha != glamor_program_alpha_normal) {
switch (dst_blend) {
case GL_SRC_ALPHA:
dst_blend = GL_SRC_COLOR;
else if (dst_blend == GL_ONE_MINUS_SRC_ALPHA)
break;
case GL_ONE_MINUS_SRC_ALPHA:
dst_blend = GL_ONE_MINUS_SRC_COLOR;
break;
}
}
glEnable(GL_BLEND);
......@@ -547,7 +564,9 @@ static const glamor_facet *glamor_facet_source[glamor_program_source_count] = {
static const char *glamor_combine[] = {
[glamor_program_alpha_normal] = " gl_FragColor = source * mask.a;\n",
[glamor_program_alpha_ca_first] = " gl_FragColor = source.a * mask;\n",
[glamor_program_alpha_ca_second] = " gl_FragColor = source * mask;\n"
[glamor_program_alpha_ca_second] = " gl_FragColor = source * mask;\n",
[glamor_program_alpha_dual_blend] = " color0 = source * mask;\n"
" color1 = source.a * mask;\n"
};
static Bool
......@@ -567,9 +586,9 @@ glamor_setup_one_program_render(ScreenPtr screen,
if (!fill)
return FALSE;
prog->alpha = alpha;
if (!glamor_build_program(screen, prog, prim, fill, glamor_combine[alpha], defines))
return FALSE;
prog->alpha = alpha;
}
return TRUE;
......@@ -585,6 +604,7 @@ glamor_setup_program_render(CARD8 op,
const char *defines)
{
ScreenPtr screen = dst->pDrawable->pScreen;
glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
glamor_program_alpha alpha;
glamor_program_source source_type;
glamor_program *prog;
......@@ -593,10 +613,15 @@ glamor_setup_program_render(CARD8 op,
return NULL;
if (glamor_is_component_alpha(mask)) {
/* This only works for PictOpOver */
if (op != PictOpOver)
return NULL;
alpha = glamor_program_alpha_ca_first;
if (glamor_priv->has_dual_blend) {
alpha = glamor_program_alpha_dual_blend;
} else {
/* This only works for PictOpOver */
if (op != PictOpOver)
return NULL;
alpha = glamor_program_alpha_ca_first;
}
} else
alpha = glamor_program_alpha_normal;
......
......@@ -43,6 +43,7 @@ typedef enum {
glamor_program_alpha_normal,
glamor_program_alpha_ca_first,
glamor_program_alpha_ca_second,
glamor_program_alpha_dual_blend,
glamor_program_alpha_count
} glamor_program_alpha;
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment