<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Nov 19, 2014 at 11:42 PM, Iago Toral <span dir="ltr"><<a href="mailto:itoral@igalia.com" target="_blank">itoral@igalia.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On Wed, 2014-11-19 at 11:43 -0800, Jason Ekstrand wrote:<br>
> A couple of specific comments are below.  More generally, why are you<br>
> only considering the base format on two cases?  Do we never use it for<br>
> anything else?<br>
<br>
</span>I thought about that too but when I looked at the original code it<br>
seemed that it only cared for the base format in these two scenarios, so<br>
I thought that maybe the conversions cases that could be affected are<br>
all handled in those two paths. I'll check again though, just in case I<br>
missed something.<br>
<div><div class="h5"><br>
> On Tue, Nov 18, 2014 at 1:23 AM, Iago Toral Quiroga<br>
> <<a href="mailto:itoral@igalia.com">itoral@igalia.com</a>> wrote:<br>
>         Add a dst_internal_format parameter to _mesa_format_convert,<br>
>         that represents<br>
>         the base internal format for texture/pixel uploads, so we can<br>
>         do the right<br>
>         thing when the driver has selected a different internal format<br>
>         for the target<br>
>         dst format.<br>
>         ---<br>
>          src/mesa/main/format_utils.c | 65<br>
>         +++++++++++++++++++++++++++++++++++++++++++-<br>
>          src/mesa/main/format_utils.h |  2 +-<br>
>          2 files changed, 65 insertions(+), 2 deletions(-)<br>
><br>
>         diff --git a/src/mesa/main/format_utils.c<br>
>         b/src/mesa/main/format_utils.c<br>
>         index fc59e86..5964689 100644<br>
>         --- a/src/mesa/main/format_utils.c<br>
>         +++ b/src/mesa/main/format_utils.c<br>
>         @@ -303,7 +303,7 @@ _mesa_compute_component_mapping(GLenum<br>
>         inFormat, GLenum outFormat, GLubyte *map)<br>
>          void<br>
>          _mesa_format_convert(void *void_dst, uint32_t dst_format,<br>
>         size_t dst_stride,<br>
>                               void *void_src, uint32_t src_format,<br>
>         size_t src_stride,<br>
>         -                     size_t width, size_t height)<br>
>         +                     size_t width, size_t height, GLenum<br>
>         dst_internal_format)<br>
>          {<br>
>             uint8_t *dst = (uint8_t *)void_dst;<br>
>             uint8_t *src = (uint8_t *)void_src;<br>
>         @@ -422,6 +422,36 @@ _mesa_format_convert(void *void_dst,<br>
>         uint32_t dst_format, size_t dst_stride,<br>
>             if (src_array_format.as_uint && dst_array_format.as_uint)<br>
>         {<br>
>                assert(src_array_format.normalized ==<br>
>         dst_array_format.normalized);<br>
><br>
>         +      /* If the base format of our dst is not the same as the<br>
>         provided base<br>
>         +       * format it means that we are converting to a<br>
>         different format<br>
>         +       * than the one originally requested by the client.<br>
>         This can happen when<br>
>         +       * the internal base format requested is not supported<br>
>         by the driver.<br>
>         +       * In this case we need to consider the requested<br>
>         internal base format to<br>
>         +       * compute the correct swizzle operation from src to<br>
>         dst. We will do this<br>
>         +       * by computing the swizzle transform<br>
>         src->rgba->base->rgba->dst instead<br>
>         +       * of src->rgba->dst.<br>
>         +       */<br>
>         +      mesa_format dst_mesa_format;<br>
>         +      if (dst_format & MESA_ARRAY_FORMAT_BIT)<br>
>         +         dst_mesa_format =<br>
>         _mesa_format_from_array_format(dst_format);<br>
>         +      else<br>
>         +         dst_mesa_format = dst_format;<br>
><br>
><br>
> Let's put an extra line here so it doesn't get confused with the below<br>
> if statement<br>
><br>
><br>
>         +      if (dst_internal_format !=<br>
>         _mesa_get_format_base_format(dst_mesa_format)) {<br>
>         +         /* Compute src2rgba as src->rgba->base->rgba */<br>
>         +         uint8_t rgba2base[4], base2rgba[4], swizzle[4];<br>
>         +         _mesa_compute_component_mapping(GL_RGBA,<br>
>         dst_internal_format, rgba2base);<br>
>         +         _mesa_compute_component_mapping(dst_internal_format,<br>
>         GL_RGBA, base2rgba);<br>
>         +<br>
>         +         for (i = 0; i < 4; i++) {<br>
>         +            if (base2rgba[i] > MESA_FORMAT_SWIZZLE_W)<br>
>         +               swizzle[i] = base2rgba[i];<br>
>         +            else<br>
>         +               swizzle[i] =<br>
>         src2rgba[rgba2base[base2rgba[i]]];<br>
><br>
><br>
> This doesn't work for composing three swizzles.  If you get a ZERO or<br>
> ONE in rgba2base, you'll read the wrong memory from src2rgba.<br>
<br>
</div></div>Actually, the problem is worse, because the mapping written by<br>
_mesa_compute_component_mapping is a 6-component mapping and we are<br>
passing a 4-component array. I'll fix this.<br></blockquote><div><br></div><div>Right now we have 2 different swizzle formats floating around.  Some with 6 components and some with 4.  4 works just fine as long as you are careful when you compose swizzles.  With 6 you can avoid the if statements because 4 and 5 simply pass through.  I like 4 better (which is why I did it that way in my stuff) but either works.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="HOEnZb"><div class="h5"><br>
><br>
><br>
>         +         }<br>
>         +         memcpy(src2rgba, swizzle, sizeof(src2rgba));<br>
>         +      }<br>
>         +<br>
>         +      /* Compute src2dst from src2rgba */<br>
>                for (i = 0; i < 4; i++) {<br>
>                   if (rgba2dst[i] > MESA_FORMAT_SWIZZLE_W) {<br>
>                      src2dst[i] = rgba2dst[i];<br>
>         @@ -539,9 +569,42 @@ _mesa_format_convert(void *void_dst,<br>
>         uint32_t dst_format, size_t dst_stride,<br>
>                      src += src_stride;<br>
>                   }<br>
>                } else {<br>
>         +         /* For some conversions, doing src->rgba->dst is not<br>
>         enough and we<br>
>         +          * need to consider the base internal format. In<br>
>         these cases a<br>
>         +          * swizzle operation is required to match the<br>
>         semantics of the base<br>
>         +          * internal format requested:<br>
>         src->rgba->swizzle->rgba->dst.<br>
>         +          *<br>
>         +          * We can detect these cases by checking if the<br>
>         swizzle transform<br>
>         +          * for base->rgba->base is 0123. If it is not, then<br>
>         we need<br>
>         +          * to do the swizzle operation (need_convert =<br>
>         true).<br>
>         +          */<br>
>         +         GLubyte rgba2base[4], base2rgba[4], map[4];<br>
>         +         bool need_convert = false;<br>
>         +         mesa_format dst_mesa_format;<br>
>         +         if (dst_format & MESA_ARRAY_FORMAT_BIT)<br>
>         +            dst_mesa_format =<br>
>         _mesa_format_from_array_format(dst_format);<br>
>         +         else<br>
>         +            dst_mesa_format = dst_format;<br>
><br>
><br>
> Blank line again<br>
><br>
><br>
><br>
>         +         if (dst_internal_format !=<br>
>         +             _mesa_get_format_base_format(dst_mesa_format)) {<br>
>         +            _mesa_compute_component_mapping(GL_RGBA,<br>
>         dst_internal_format,<br>
>         +                                            base2rgba);<br>
>         +<br>
>         _mesa_compute_component_mapping(dst_internal_format, GL_RGBA,<br>
>         +                                            rgba2base);<br>
>         +            for (i = 0; i < 4; ++i) {<br>
>         +               map[i] = base2rgba[rgba2base[i]];<br>
>         +               if (map[i] != i)<br>
>         +                  need_convert = true;<br>
>         +            }<br>
>         +         }<br>
>         +<br>
>                   for (row = 0; row < height; ++row) {<br>
>                      _mesa_unpack_rgba_row(src_format, width,<br>
>                                            src, tmp_float + row *<br>
>         width);<br>
>         +            if (need_convert)<br>
>         +               _mesa_swizzle_and_convert(tmp_float + row *<br>
>         width, GL_FLOAT, 4,<br>
>         +                                         tmp_float + row *<br>
>         width, GL_FLOAT, 4,<br>
>         +                                         map, false, width);<br>
>                      src += src_stride;<br>
>                   }<br>
>                }<br>
>         diff --git a/src/mesa/main/format_utils.h<br>
>         b/src/mesa/main/format_utils.h<br>
>         index 4237ad3..29ab4a0 100644<br>
>         --- a/src/mesa/main/format_utils.h<br>
>         +++ b/src/mesa/main/format_utils.h<br>
>         @@ -158,6 +158,6 @@ _mesa_compute_component_mapping(GLenum<br>
>         inFormat, GLenum outFormat, GLubyte *map)<br>
>          void<br>
>          _mesa_format_convert(void *void_dst, uint32_t dst_format,<br>
>         size_t dst_stride,<br>
>                               void *void_src, uint32_t src_format,<br>
>         size_t src_stride,<br>
>         -                     size_t width, size_t height);<br>
>         +                     size_t width, size_t height, GLenum<br>
>         dst_internal_format);<br>
><br>
>          #endif<br>
>         --<br>
>         1.9.1<br>
><br>
>         _______________________________________________<br>
>         mesa-dev mailing list<br>
>         <a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
>         <a href="http://lists.freedesktop.org/mailman/listinfo/mesa-dev" target="_blank">http://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br>
><br>
><br>
<br>
<br>
</div></div></blockquote></div><br></div></div>