ilo: derive fb blending caps at bind time

Derive whether a RT supports blending, logicop, and the like when
set_framebuffer_state() is called.  This enables us to simplify
gen6_BLEND_STATE().

Signed-off-by: Chia-I Wu <olvaffe@gmail.com>
This commit is contained in:
Chia-I Wu 2014-11-10 13:44:45 +08:00
parent 55d70e0669
commit d388d8576f
3 changed files with 102 additions and 79 deletions

View file

@ -1224,70 +1224,34 @@ gen6_BLEND_STATE(struct ilo_builder *builder,
ILO_BUILDER_ITEM_BLEND, state_align, state_len, &dw);
for (i = 0; i < num_targets; i++) {
const unsigned idx = (blend->independent_blend_enable) ? i : 0;
const struct ilo_blend_cso *cso = &blend->cso[idx];
const int num_samples = fb->num_samples;
const struct util_format_description *format_desc =
(idx < fb->state.nr_cbufs && fb->state.cbufs[idx]) ?
util_format_description(fb->state.cbufs[idx]->format) : NULL;
bool rt_is_unorm, rt_is_pure_integer, rt_dst_alpha_forced_one;
rt_is_unorm = true;
rt_is_pure_integer = false;
rt_dst_alpha_forced_one = false;
if (format_desc) {
int ch;
switch (format_desc->format) {
case PIPE_FORMAT_B8G8R8X8_UNORM:
/* force alpha to one when the HW format has alpha */
assert(ilo_translate_render_format(builder->dev,
PIPE_FORMAT_B8G8R8X8_UNORM) ==
GEN6_FORMAT_B8G8R8A8_UNORM);
rt_dst_alpha_forced_one = true;
break;
default:
break;
}
for (ch = 0; ch < 4; ch++) {
if (format_desc->channel[ch].type == UTIL_FORMAT_TYPE_VOID)
continue;
if (format_desc->channel[ch].pure_integer) {
rt_is_unorm = false;
rt_is_pure_integer = true;
break;
}
if (!format_desc->channel[ch].normalized ||
format_desc->channel[ch].type != UTIL_FORMAT_TYPE_UNSIGNED)
rt_is_unorm = false;
}
}
const struct ilo_blend_cso *cso =
&blend->cso[(blend->independent_blend_enable) ? i : 0];
dw[0] = cso->payload[0];
dw[1] = cso->payload[1];
if (!rt_is_pure_integer) {
if (rt_dst_alpha_forced_one)
dw[0] |= cso->dw_blend_dst_alpha_forced_one;
else
dw[0] |= cso->dw_blend;
}
if (i < fb->state.nr_cbufs && fb->state.cbufs[i]) {
const struct ilo_fb_blend_caps *caps = &fb->blend_caps[i];
/*
* From the Sandy Bridge PRM, volume 2 part 1, page 365:
*
* "Logic Ops are only supported on *_UNORM surfaces (excluding
* _SRGB variants), otherwise Logic Ops must be DISABLED."
*
* Since logicop is ignored for non-UNORM color buffers, no special care
* is needed.
*/
if (rt_is_unorm)
dw[1] |= cso->dw_logicop;
if (caps->can_blend) {
if (caps->dst_alpha_forced_one)
dw[0] |= cso->dw_blend_dst_alpha_forced_one;
else
dw[0] |= cso->dw_blend;
}
if (caps->can_logicop)
dw[1] |= cso->dw_logicop;
if (caps->can_alpha_test)
dw[1] |= dsa->dw_alpha;
} else {
dw[1] |= GEN6_BLEND_DW1_WRITE_DISABLE_A |
GEN6_BLEND_DW1_WRITE_DISABLE_R |
GEN6_BLEND_DW1_WRITE_DISABLE_G |
GEN6_BLEND_DW1_WRITE_DISABLE_B |
dsa->dw_alpha;
}
/*
* From the Sandy Bridge PRM, volume 2 part 1, page 356:
@ -1298,18 +1262,9 @@ gen6_BLEND_STATE(struct ilo_builder *builder,
* There is no such limitation on GEN7, or for AlphaToOne. But GL
* requires that anyway.
*/
if (num_samples > 1)
if (fb->num_samples > 1)
dw[1] |= cso->dw_alpha_mod;
/*
* From the Sandy Bridge PRM, volume 2 part 1, page 382:
*
* "Alpha Test can only be enabled if Pixel Shader outputs a float
* alpha value."
*/
if (!rt_is_pure_integer)
dw[1] |= dsa->dw_alpha;
dw += 2;
}

View file

@ -347,6 +347,13 @@ struct ilo_fb_state {
struct ilo_view_surface null_rt;
struct ilo_zs_surface null_zs;
struct ilo_fb_blend_caps {
bool can_logicop;
bool can_blend;
bool can_alpha_test;
bool dst_alpha_forced_one;
} blend_caps[PIPE_MAX_COLOR_BUFS];
unsigned num_samples;
};

View file

@ -1540,13 +1540,70 @@ ilo_gpe_set_scissor_null(const struct ilo_dev_info *dev,
}
}
static void
fb_set_blend_caps(const struct ilo_dev_info *dev,
enum pipe_format format,
struct ilo_fb_blend_caps *caps)
{
const struct util_format_description *desc =
util_format_description(format);
const int ch = util_format_get_first_non_void_channel(format);
memset(caps, 0, sizeof(*caps));
if (format == PIPE_FORMAT_NONE || desc->is_mixed)
return;
/*
* From the Sandy Bridge PRM, volume 2 part 1, page 365:
*
* "Logic Ops are only supported on *_UNORM surfaces (excluding _SRGB
* variants), otherwise Logic Ops must be DISABLED."
*/
caps->can_logicop = (ch >= 0 && desc->channel[ch].normalized &&
desc->channel[ch].type == UTIL_FORMAT_TYPE_UNSIGNED &&
desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB);
/* no blending for pure integer formats */
caps->can_blend = !util_format_is_pure_integer(format);
/*
* From the Sandy Bridge PRM, volume 2 part 1, page 382:
*
* "Alpha Test can only be enabled if Pixel Shader outputs a float
* alpha value."
*/
caps->can_alpha_test = !util_format_is_pure_integer(format);
caps->dst_alpha_forced_one =
(ilo_translate_render_format(dev, format) !=
ilo_translate_color_format(dev, format));
/* sanity check */
if (caps->dst_alpha_forced_one) {
enum pipe_format render_format;
switch (format) {
case PIPE_FORMAT_B8G8R8X8_UNORM:
render_format = PIPE_FORMAT_B8G8R8A8_UNORM;
break;
default:
render_format = PIPE_FORMAT_NONE;
break;
}
assert(ilo_translate_render_format(dev, format) ==
ilo_translate_color_format(dev, render_format));
}
}
void
ilo_gpe_set_fb(const struct ilo_dev_info *dev,
const struct pipe_framebuffer_state *state,
struct ilo_fb_state *fb)
{
const struct pipe_surface *first;
unsigned first_idx;
const struct pipe_surface *first_surf = NULL;
int i;
ILO_DEV_ASSERT(dev, 6, 7.5);
@ -1557,17 +1614,21 @@ ilo_gpe_set_fb(const struct ilo_dev_info *dev,
(state->height) ? state->height : 1,
1, 0, &fb->null_rt);
first = NULL;
for (first_idx = 0; first_idx < state->nr_cbufs; first_idx++) {
if (state->cbufs[first_idx]) {
first = state->cbufs[first_idx];
break;
for (i = 0; i < state->nr_cbufs; i++) {
if (state->cbufs[i]) {
fb_set_blend_caps(dev, state->cbufs[i]->format, &fb->blend_caps[i]);
if (!first_surf)
first_surf = state->cbufs[i];
} else {
fb_set_blend_caps(dev, PIPE_FORMAT_NONE, &fb->blend_caps[i]);
}
}
if (!first)
first = state->zsbuf;
fb->num_samples = (first) ? first->texture->nr_samples : 1;
if (!first_surf && state->zsbuf)
first_surf = state->zsbuf;
fb->num_samples = (first_surf) ? first_surf->texture->nr_samples : 1;
if (!fb->num_samples)
fb->num_samples = 1;