renderer: handle rendering to A8 surfaces.

I'm not sure this is 100% complete, piglit fbo-alpha now passes.

This was a guess as to why gnome-shell was broken, but I don't think
it was the correct one.
macos/master
Dave Airlie 9 years ago
parent ee45480c5d
commit bd64c81fc2
  1. 2
      src/vrend_formats.c
  2. 86
      src/vrend_renderer.c
  3. 16
      src/vrend_shader.c
  4. 1
      src/vrend_shader.h

@ -261,7 +261,7 @@ static void vrend_add_formats(struct vrend_format_table *table, int num_entries)
if (status == GL_INVALID_VALUE) { if (status == GL_INVALID_VALUE) {
struct vrend_format_table *entry = NULL; struct vrend_format_table *entry = NULL;
uint8_t swizzle[4]; uint8_t swizzle[4];
binding = VREND_BIND_SAMPLER | VREND_BIND_NEED_SWIZZLE; binding = VREND_BIND_SAMPLER | VREND_BIND_RENDER | VREND_BIND_NEED_SWIZZLE;
switch (table[i].format) { switch (table[i].format) {
case PIPE_FORMAT_A8_UNORM: case PIPE_FORMAT_A8_UNORM:

@ -412,6 +412,14 @@ bool vrend_is_ds_format(enum virgl_formats format)
return vrend_format_is_ds(format); return vrend_format_is_ds(format);
} }
static inline bool vrend_format_is_emulated_alpha(enum virgl_formats format)
{
if (!vrend_state.use_core_profile)
return false;
return (format == VIRGL_FORMAT_A8_UNORM ||
format == VIRGL_FORMAT_A16_UNORM);
}
static inline const char *pipe_shader_to_prefix(int shader_type) static inline const char *pipe_shader_to_prefix(int shader_type)
{ {
switch (shader_type) { switch (shader_type) {
@ -1508,6 +1516,7 @@ void vrend_set_framebuffer_state(struct vrend_context *ctx,
if (status != GL_FRAMEBUFFER_COMPLETE) if (status != GL_FRAMEBUFFER_COMPLETE)
fprintf(stderr,"failed to complete framebuffer 0x%x %s\n", status, ctx->debug_name); fprintf(stderr,"failed to complete framebuffer 0x%x %s\n", status, ctx->debug_name);
} }
ctx->sub->shader_dirty = true;
} }
/* /*
@ -1921,9 +1930,12 @@ static inline void vrend_fill_shader_key(struct vrend_context *ctx,
if (vrend_state.use_core_profile == true) { if (vrend_state.use_core_profile == true) {
int i; int i;
bool add_alpha_test = true; bool add_alpha_test = true;
key->cbufs_are_a8_bitmask = 0;
for (i = 0; i < ctx->sub->nr_cbufs; i++) { for (i = 0; i < ctx->sub->nr_cbufs; i++) {
if (!ctx->sub->surf[i]) if (!ctx->sub->surf[i])
continue; continue;
if (vrend_format_is_emulated_alpha(ctx->sub->surf[i]->format))
key->cbufs_are_a8_bitmask |= (1 << i);
if (util_format_is_pure_integer(ctx->sub->surf[i]->format)) if (util_format_is_pure_integer(ctx->sub->surf[i]->format))
add_alpha_test = false; add_alpha_test = false;
} }
@ -2216,8 +2228,13 @@ void vrend_clear(struct vrend_context *ctx,
vrend_use_program(ctx, 0); vrend_use_program(ctx, 0);
if (buffers & PIPE_CLEAR_COLOR) if (buffers & PIPE_CLEAR_COLOR) {
glClearColor(color->f[0], color->f[1], color->f[2], color->f[3]); if (ctx->sub->nr_cbufs && ctx->sub->surf[0] && vrend_format_is_emulated_alpha(ctx->sub->surf[0]->format)) {
glClearColor(color->f[3], 0.0, 0.0, 0.0);
} else {
glClearColor(color->f[0], color->f[1], color->f[2], color->f[3]);
}
}
if (buffers & PIPE_CLEAR_DEPTH) { if (buffers & PIPE_CLEAR_DEPTH) {
/* gallium clears don't respect depth mask */ /* gallium clears don't respect depth mask */
@ -2849,6 +2866,15 @@ static inline bool is_dst_blend(int blend_factor)
blend_factor == PIPE_BLENDFACTOR_INV_DST_ALPHA); blend_factor == PIPE_BLENDFACTOR_INV_DST_ALPHA);
} }
static inline int conv_a8_blend(int blend_factor)
{
if (blend_factor == PIPE_BLENDFACTOR_DST_ALPHA)
return PIPE_BLENDFACTOR_DST_COLOR;
if (blend_factor == PIPE_BLENDFACTOR_INV_DST_ALPHA)
return PIPE_BLENDFACTOR_INV_DST_COLOR;
return blend_factor;
}
static inline int conv_dst_blend(int blend_factor) static inline int conv_dst_blend(int blend_factor)
{ {
if (blend_factor == PIPE_BLENDFACTOR_DST_ALPHA) if (blend_factor == PIPE_BLENDFACTOR_DST_ALPHA)
@ -2863,12 +2889,17 @@ static void vrend_patch_blend_func(struct vrend_context *ctx)
struct pipe_blend_state *state = &ctx->sub->blend_state; struct pipe_blend_state *state = &ctx->sub->blend_state;
int i; int i;
int rsf, rdf, asf, adf; int rsf, rdf, asf, adf;
bool a8_conv = false;
if (ctx->sub->nr_cbufs == 0) if (ctx->sub->nr_cbufs == 0)
return; return;
for (i = 0; i < ctx->sub->nr_cbufs; i++) { for (i = 0; i < ctx->sub->nr_cbufs; i++) {
if (!ctx->sub->surf[i]) if (!ctx->sub->surf[i])
continue; continue;
if (vrend_format_is_emulated_alpha(ctx->sub->surf[i]->format)) {
a8_conv = true;
break;
}
if (!util_format_has_alpha(ctx->sub->surf[i]->format)) if (!util_format_has_alpha(ctx->sub->surf[i]->format))
break; break;
} }
@ -2880,32 +2911,47 @@ static void vrend_patch_blend_func(struct vrend_context *ctx)
/* ARB_draw_buffers_blend is required for this */ /* ARB_draw_buffers_blend is required for this */
for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
if (state->rt[i].blend_enable) { if (state->rt[i].blend_enable) {
if (!(is_dst_blend(state->rt[i].rgb_src_factor) ||
is_dst_blend(state->rt[i].rgb_dst_factor) ||
is_dst_blend(state->rt[i].alpha_src_factor) ||
is_dst_blend(state->rt[i].alpha_dst_factor)))
continue;
rsf = translate_blend_factor(conv_dst_blend(state->rt[i].rgb_src_factor)); if (a8_conv) {
rdf = translate_blend_factor(conv_dst_blend(state->rt[i].rgb_dst_factor)); rsf = translate_blend_factor(conv_a8_blend(state->rt[i].alpha_src_factor));
asf = translate_blend_factor(conv_dst_blend(state->rt[i].alpha_src_factor)); rdf = translate_blend_factor(conv_a8_blend(state->rt[i].alpha_dst_factor));
adf = translate_blend_factor(conv_dst_blend(state->rt[i].alpha_dst_factor)); asf = translate_blend_factor(PIPE_BLENDFACTOR_ZERO);
adf = translate_blend_factor(PIPE_BLENDFACTOR_ZERO);
} else {
if (!(is_dst_blend(state->rt[i].rgb_src_factor) ||
is_dst_blend(state->rt[i].rgb_dst_factor) ||
is_dst_blend(state->rt[i].alpha_src_factor) ||
is_dst_blend(state->rt[i].alpha_dst_factor)))
continue;
rsf = translate_blend_factor(conv_dst_blend(state->rt[i].rgb_src_factor));
rdf = translate_blend_factor(conv_dst_blend(state->rt[i].rgb_dst_factor));
asf = translate_blend_factor(conv_dst_blend(state->rt[i].alpha_src_factor));
adf = translate_blend_factor(conv_dst_blend(state->rt[i].alpha_dst_factor));
}
glBlendFuncSeparateiARB(i, rsf, rdf, asf, adf); glBlendFuncSeparateiARB(i, rsf, rdf, asf, adf);
} }
} }
} else { } else {
if (state->rt[0].blend_enable) { if (state->rt[0].blend_enable) {
if (!(is_dst_blend(state->rt[0].rgb_src_factor) || if (a8_conv) {
is_dst_blend(state->rt[0].rgb_dst_factor) || rsf = translate_blend_factor(conv_a8_blend(state->rt[i].alpha_src_factor));
is_dst_blend(state->rt[0].alpha_src_factor) || rdf = translate_blend_factor(conv_a8_blend(state->rt[i].alpha_dst_factor));
is_dst_blend(state->rt[0].alpha_dst_factor))) asf = translate_blend_factor(PIPE_BLENDFACTOR_ZERO);
return; adf = translate_blend_factor(PIPE_BLENDFACTOR_ZERO);
} else {
if (!(is_dst_blend(state->rt[0].rgb_src_factor) ||
is_dst_blend(state->rt[0].rgb_dst_factor) ||
is_dst_blend(state->rt[0].alpha_src_factor) ||
is_dst_blend(state->rt[0].alpha_dst_factor)))
return;
rsf = translate_blend_factor(conv_dst_blend(state->rt[i].rgb_src_factor)); rsf = translate_blend_factor(conv_dst_blend(state->rt[i].rgb_src_factor));
rdf = translate_blend_factor(conv_dst_blend(state->rt[i].rgb_dst_factor)); rdf = translate_blend_factor(conv_dst_blend(state->rt[i].rgb_dst_factor));
asf = translate_blend_factor(conv_dst_blend(state->rt[i].alpha_src_factor)); asf = translate_blend_factor(conv_dst_blend(state->rt[i].alpha_src_factor));
adf = translate_blend_factor(conv_dst_blend(state->rt[i].alpha_dst_factor)); adf = translate_blend_factor(conv_dst_blend(state->rt[i].alpha_dst_factor));
}
glBlendFuncSeparate(rsf, rdf, asf, adf); glBlendFuncSeparate(rsf, rdf, asf, adf);
} }

@ -681,6 +681,17 @@ static const char *atests[PIPE_FUNC_ALWAYS + 1] = {
"true", "true",
}; };
static int emit_a8_swizzle(struct dump_ctx *ctx)
{
char buf[255];
char *sret;
snprintf(buf, 255, "fsout_c0.x = fsout_c0.w;\n");
sret = add_str_to_glsl_main(ctx, buf);
if (!sret)
return ENOMEM;
return 0;
}
static int emit_alpha_test(struct dump_ctx *ctx) static int emit_alpha_test(struct dump_ctx *ctx)
{ {
char buf[255]; char buf[255];
@ -1757,6 +1768,11 @@ iter_instruction(struct tgsi_iterate_context *iter,
if (ret) if (ret)
return FALSE; return FALSE;
} }
if (ctx->key->cbufs_are_a8_bitmask) {
ret = emit_a8_swizzle(ctx);
if (ret)
return FALSE;
}
if (ctx->key->add_alpha_test) { if (ctx->key->add_alpha_test) {
ret = emit_alpha_test(ctx); ret = emit_alpha_test(ctx);
if (ret) if (ret)

@ -63,6 +63,7 @@ struct vrend_shader_key {
bool gs_present; bool gs_present;
bool flatshade; bool flatshade;
float alpha_ref_val; float alpha_ref_val;
uint32_t cbufs_are_a8_bitmask;
}; };
struct vrend_shader_cfg { struct vrend_shader_cfg {

Loading…
Cancel
Save