<div dir="ltr">A couple of specific comments are below.  More generally, why are you only considering the base format on two cases?  Do we never use it for anything else?<br><div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Nov 18, 2014 at 1:23 AM, Iago Toral Quiroga <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">Add a dst_internal_format parameter to _mesa_format_convert, that represents<br>
the base internal format for texture/pixel uploads, so we can do the right<br>
thing when the driver has selected a different internal format for the target<br>
dst format.<br>
---<br>
 src/mesa/main/format_utils.c | 65 +++++++++++++++++++++++++++++++++++++++++++-<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 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 inFormat, GLenum outFormat, GLubyte *map)<br>
 void<br>
 _mesa_format_convert(void *void_dst, uint32_t dst_format, size_t dst_stride,<br>
                      void *void_src, uint32_t src_format, size_t src_stride,<br>
-                     size_t width, size_t height)<br>
+                     size_t width, size_t height, GLenum 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, uint32_t dst_format, size_t dst_stride,<br>
    if (src_array_format.as_uint && dst_array_format.as_uint) {<br>
       assert(src_array_format.normalized == dst_array_format.normalized);<br>
<br>
+      /* If the base format of our dst is not the same as the provided base<br>
+       * format it means that we are converting to a different format<br>
+       * than the one originally requested by the client. This can happen when<br>
+       * the internal base format requested is not supported by the driver.<br>
+       * In this case we need to consider the requested internal base format to<br>
+       * compute the correct swizzle operation from src to dst. We will do this<br>
+       * by computing the swizzle transform 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 = _mesa_format_from_array_format(dst_format);<br>
+      else<br>
+         dst_mesa_format = dst_format;<br></blockquote><div><br></div><div>Let's put an extra line here so it doesn't get confused with the below if statement<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+      if (dst_internal_format != _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, dst_internal_format, rgba2base);<br>
+         _mesa_compute_component_mapping(dst_internal_format, 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] = src2rgba[rgba2base[base2rgba[i]]];<br></blockquote><div><br></div><div>This doesn't work for composing three swizzles.  If you get a ZERO or ONE in rgba2base, you'll read the wrong memory from src2rgba.<br></div><div> <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+         }<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, 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 enough and we<br>
+          * need to consider the base internal format. In these cases a<br>
+          * swizzle operation is required to match the semantics of the base<br>
+          * internal format requested: src->rgba->swizzle->rgba->dst.<br>
+          *<br>
+          * We can detect these cases by checking if the swizzle transform<br>
+          * for base->rgba->base is 0123. If it is not, then we need<br>
+          * to do the swizzle operation (need_convert = 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 = _mesa_format_from_array_format(dst_format);<br>
+         else<br>
+            dst_mesa_format = dst_format;<br></blockquote><div><br></div><div>Blank line again<br></div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+         if (dst_internal_format !=<br>
+             _mesa_get_format_base_format(dst_mesa_format)) {<br>
+            _mesa_compute_component_mapping(GL_RGBA, dst_internal_format,<br>
+                                            base2rgba);<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 * width);<br>
+            if (need_convert)<br>
+               _mesa_swizzle_and_convert(tmp_float + row * width, GL_FLOAT, 4,<br>
+                                         tmp_float + row * width, GL_FLOAT, 4,<br>
+                                         map, false, width);<br>
             src += src_stride;<br>
          }<br>
       }<br>
diff --git a/src/mesa/main/format_utils.h 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 inFormat, GLenum outFormat, GLubyte *map)<br>
 void<br>
 _mesa_format_convert(void *void_dst, uint32_t dst_format, size_t dst_stride,<br>
                      void *void_src, uint32_t src_format, size_t src_stride,<br>
-                     size_t width, size_t height);<br>
+                     size_t width, size_t height, GLenum dst_internal_format);<br>
<br>
 #endif<br>
<span class="HOEnZb"><font color="#888888">--<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>
</font></span></blockquote></div><br></div></div></div>