[Mesa-dev] [PATCH] st/xa: Use PIPE_FORMAT_R8_UNORM when available

Thomas Hellstrom thellstrom at vmware.com
Thu Sep 17 02:53:20 PDT 2015


On 09/17/2015 11:34 AM, Jose Fonseca wrote:
> On 16/09/15 14:04, Thomas Hellstrom wrote:
>> XA has been using L8_UNORM for a8 and yuv component surfaces.
>> This commit instead makes XA prefer R8_UNORM since it's assumed to
>> have a
>> higher availability.
>>
>> Also neither of these formats are suitable as destination formats using
>> destination alpha blending, so reject those operations.
>>
>> Signed-off-by: Thomas Hellstrom <thellstrom at vmware.com>
>> ---
>>   src/gallium/state_trackers/xa/xa_composite.c | 40
>> ++++++++++------------------
>>   src/gallium/state_trackers/xa/xa_tracker.c   | 28 +++++++++++++------
>>   2 files changed, 34 insertions(+), 34 deletions(-)
>>
>> diff --git a/src/gallium/state_trackers/xa/xa_composite.c
>> b/src/gallium/state_trackers/xa/xa_composite.c
>> index 7cfd1e1..e81eeba 100644
>> --- a/src/gallium/state_trackers/xa/xa_composite.c
>> +++ b/src/gallium/state_trackers/xa/xa_composite.c
>> @@ -78,26 +78,6 @@ static const struct xa_composite_blend xa_blends[]
>> = {
>>         0, 0, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE},
>>   };
>>
>> -
>> -/*
>> - * The alpha value stored in a luminance texture is read by the
>> - * hardware as color.
>> - */
>> -static unsigned
>> -xa_convert_blend_for_luminance(unsigned factor)
>> -{
>> -    switch(factor) {
>> -    case PIPE_BLENDFACTOR_DST_ALPHA:
>> -    return PIPE_BLENDFACTOR_DST_COLOR;
>> -    case PIPE_BLENDFACTOR_INV_DST_ALPHA:
>> -    return PIPE_BLENDFACTOR_INV_DST_COLOR;
>> -    default:
>> -    break;
>> -    }
>> -    return factor;
>> -}
>> -
>> -
>>   static boolean
>>   blend_for_op(struct xa_composite_blend *blend,
>>            enum xa_composite_op op,
>> @@ -131,10 +111,16 @@ blend_for_op(struct xa_composite_blend *blend,
>>       if (!dst_pic->srf)
>>       return supported;
>>
>> -    if (dst_pic->srf->tex->format == PIPE_FORMAT_L8_UNORM) {
>> -    blend->rgb_src = xa_convert_blend_for_luminance(blend->rgb_src);
>> -    blend->rgb_dst = xa_convert_blend_for_luminance(blend->rgb_dst);
>> -    }
>> +    /*
>> +     * None of the hardware formats we might use for dst A8 are
>> +     * suitable for dst_alpha blending, since they present the
>> +     * alpha channel either in all color channels (L8_UNORM) or
>> +     * in the red channel only (R8_UNORM)
>> +     */
>> +    if ((dst_pic->srf->tex->format == PIPE_FORMAT_L8_UNORM ||
>> +         dst_pic->srf->tex->format == PIPE_FORMAT_R8_UNORM) &&
>> +        blend->alpha_dst)
>> +        return FALSE;
>
> I'm not very familiar with this code, but wasn't
> xa_convert_blend_for_luminance compensating for the A8 <-> L8
> mismatch?  It looks like it was doing the right thing.   And
> xa_convert_blend_for_luminance would work both for L8 and R8.

In these operations since the destination format is A8, we're only
interested in the resulting alpha channel. With
PIPE_BLENDFACTOR_DST_ALPHA, we would use the destination alpha channel
for blending, which would pick up 1 for L8 and R8 which is obviously
wrong. Now the removed function instead set PIPE_BLENDFACTOR_DST_COLOR,
which would, if I read the specs correctly blend component-wise and
yield the correct results for the R, G and B channels if L8 is used. and
for the R channel only if R8 is used. But a prerequisite here is that
the destination logical format is A8 and the alpha channel is never
correct AFAICT.

>
>>
>>       /*
>>        * If there's no dst alpha channel, adjust the blend op so that
>> we'll treat
>> @@ -298,7 +284,8 @@ picture_format_fixups(struct xa_picture *src_pic,
>>       ret |= mask ? FS_MASK_SET_ALPHA : FS_SRC_SET_ALPHA;
>>
>>       if (src_hw_format == src_pic_format) {
>> -    if (src->tex->format == PIPE_FORMAT_L8_UNORM)
>> +    if (src->tex->format == PIPE_FORMAT_L8_UNORM ||
>> +            src->tex->format == PIPE_FORMAT_R8_UNORM)
>>           return ((mask) ? FS_MASK_LUMINANCE : FS_SRC_LUMINANCE);
>>
>>       return ret;
>> @@ -372,7 +359,8 @@ bind_shaders(struct xa_context *ctx, const struct
>> xa_composite *comp)
>>       fs_traits |= picture_format_fixups(mask_pic, 1);
>>       }
>>
>> -    if (ctx->srf->format == PIPE_FORMAT_L8_UNORM)
>> +    if (ctx->srf->format == PIPE_FORMAT_L8_UNORM ||
>> +        ctx->srf->format == PIPE_FORMAT_R8_UNORM)
>>       fs_traits |= FS_DST_LUMINANCE;
>
> What exactly is FS_DST_LUMINANCE supposed to do?  From xa_tgsi.c it
> seems to swizzle the alpha channel into the red channel, before
> outputing.  But if we no longer want to emulate A8 with R8/L8 then it
> seems that's no longer necessary.

Yes, it swizzles the alpha channel to all color channels. What we
disable above is only those composite operations that use DEST_ALPHA
blending (which is only a few), together with a R8/L8 destination.
Probably a very odd combination, so there are definitely situations were
we can composite to A8 using other composite operations, and I've
verified that it works.

>
>
> BTW, isn't necessary to update
> src/gallium/state_trackers/xa/xa_renderer.c to apply
> FS_SRC/DST_LUMINANCE traits for R8_UNORM too?

Hmm. Good point. I have missed that. I'll take a look.

Thanks,
Thomas


>
>
>>
>>       shader = xa_shaders_get(ctx->shaders, vs_traits, fs_traits);
>> diff --git a/src/gallium/state_trackers/xa/xa_tracker.c
>> b/src/gallium/state_trackers/xa/xa_tracker.c
>> index 2944b16..cd1394a 100644
>> --- a/src/gallium/state_trackers/xa/xa_tracker.c
>> +++ b/src/gallium/state_trackers/xa/xa_tracker.c
>> @@ -82,7 +82,7 @@ static const unsigned int
>> stype_bind[XA_LAST_SURFACE_TYPE] = { 0,
>>   };
>>
>>   static struct xa_format_descriptor
>> -xa_get_pipe_format(enum xa_formats xa_format)
>> +xa_get_pipe_format(struct xa_tracker *xa, enum xa_formats xa_format)
>>   {
>>       struct xa_format_descriptor fdesc;
>>
>> @@ -102,7 +102,13 @@ xa_get_pipe_format(enum xa_formats xa_format)
>>       fdesc.format = PIPE_FORMAT_B5G5R5A1_UNORM;
>>       break;
>>       case xa_format_a8:
>> -    fdesc.format = PIPE_FORMAT_L8_UNORM;
>> +        if (xa->screen->is_format_supported(xa->screen,
>> PIPE_FORMAT_R8_UNORM,
>> +                                            PIPE_TEXTURE_2D, 0,
>> +                                            stype_bind[xa_type_a] |
>> +                                            PIPE_BIND_RENDER_TARGET))
>> +            fdesc.format = PIPE_FORMAT_R8_UNORM;
>> +        else
>> +            fdesc.format = PIPE_FORMAT_L8_UNORM;
>>       break;
>>       case xa_format_z24:
>>       fdesc.format = PIPE_FORMAT_Z24X8_UNORM;
>> @@ -126,7 +132,12 @@ xa_get_pipe_format(enum xa_formats xa_format)
>>       fdesc.format = PIPE_FORMAT_S8_UINT_Z24_UNORM;
>>       break;
>>       case xa_format_yuv8:
>> -    fdesc.format = PIPE_FORMAT_L8_UNORM;
>> +        if (xa->screen->is_format_supported(xa->screen,
>> PIPE_FORMAT_R8_UNORM,
>> +                                            PIPE_TEXTURE_2D, 0,
>> +                                           
>> stype_bind[xa_type_yuv_component]))
>> +            fdesc.format = PIPE_FORMAT_R8_UNORM;
>> +        else
>> +            fdesc.format = PIPE_FORMAT_L8_UNORM;
>>       break;
>>       default:
>>       fdesc.xa_format = xa_format_unknown;
>> @@ -184,7 +195,8 @@ xa_tracker_create(int drm_fd)
>>       for (i = 0; i < num_preferred[stype]; ++i) {
>>           xa_format = preferred[stype][i];
>>
>> -        struct xa_format_descriptor fdesc =
>> xa_get_pipe_format(xa_format);
>> +        struct xa_format_descriptor fdesc =
>> +                xa_get_pipe_format(xa, xa_format);
>>
>>           if (xa->screen->is_format_supported(xa->screen, fdesc.format,
>>                           PIPE_TEXTURE_2D, 0, bind)) {
>> @@ -259,7 +271,7 @@ xa_get_format_stype_depth(struct xa_tracker *xa,
>>       int found = 0;
>>
>>       for (i = xa->format_map[stype][0]; i <=
>> xa->format_map[stype][1]; ++i) {
>> -    fdesc = xa_get_pipe_format(xa->supported_formats[i]);
>> +    fdesc = xa_get_pipe_format(xa, xa->supported_formats[i]);
>>       if (fdesc.xa_format != xa_format_unknown &&
>>           xa_format_depth(fdesc.xa_format) == depth) {
>>           found = 1;
>> @@ -277,7 +289,7 @@ XA_EXPORT int
>>   xa_format_check_supported(struct xa_tracker *xa,
>>                 enum xa_formats xa_format, unsigned int flags)
>>   {
>> -    struct xa_format_descriptor fdesc = xa_get_pipe_format(xa_format);
>> +    struct xa_format_descriptor fdesc = xa_get_pipe_format(xa,
>> xa_format);
>>       unsigned int bind;
>>
>>       if (fdesc.xa_format == xa_format_unknown)
>> @@ -328,7 +340,7 @@ surface_create(struct xa_tracker *xa,
>>       if (xa_format == xa_format_unknown)
>>       fdesc = xa_get_format_stype_depth(xa, stype, depth);
>>       else
>> -    fdesc = xa_get_pipe_format(xa_format);
>> +    fdesc = xa_get_pipe_format(xa, xa_format);
>>
>>       if (fdesc.xa_format == xa_format_unknown)
>>       return NULL;
>> @@ -440,7 +452,7 @@ xa_surface_redefine(struct xa_surface *srf,
>>       if (xa_format == xa_format_unknown)
>>       fdesc = xa_get_format_stype_depth(xa, stype, depth);
>>       else
>> -    fdesc = xa_get_pipe_format(xa_format);
>> +    fdesc = xa_get_pipe_format(xa, xa_format);
>>
>>       if (width == template->width0 && height == template->height0 &&
>>       template->format == fdesc.format &&
>>
>



More information about the mesa-dev mailing list