<div dir="ltr"><div>Looks good!<br></div>Reviewed-by: Jason Ekstrand <<a href="mailto:jason.ekstrand@intel.com">jason.ekstrand@intel.com</a>><br></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Dec 9, 2014 at 4:07 AM, Iago Toral Quiroga <span dir="ltr"><<a href="mailto:itoral@igalia.com" target="_blank">itoral@igalia.com</a>></span> wrote:<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">The new parameter allows callers to provide a rebase swizzle that<br>
the function needs to use to match the requirements of the base<br>
internal format involved. This is necessary when the source or<br>
destination internal formats (depending on whether we are doing<br>
the conversion for a pixel download or a pixel upload respectively)<br>
do not match the base formats of the source or destination<br>
formats of the conversion. This can happen when the driver does not<br>
support the internal formats and uses a different format to store<br>
pixel data internally.<br>
<br>
For example, a texture upload from RGB to Luminance in a driver<br>
that does not support textures with a Luminance format may decide<br>
to store the Luminance data as RGBA. In this case we want to store<br>
the RGBA values as (R,R,R,1). Following the same example, when we<br>
download from that texture to RGBA we want to read (R,0,0,1). The<br>
rebase_swizzle parameter allows these transforms to happen.<br>
---<br>
 src/mesa/main/format_utils.c | 239 ++++++++++++++++++++++++++++++-------------<br>
 src/mesa/main/format_utils.h |   2 +-<br>
 2 files changed, 171 insertions(+), 70 deletions(-)<br>
<br>
diff --git a/src/mesa/main/format_utils.c b/src/mesa/main/format_utils.c<br>
index ba0be13..040c79a 100644<br>
--- a/src/mesa/main/format_utils.c<br>
+++ b/src/mesa/main/format_utils.c<br>
@@ -279,6 +279,75 @@ gl_type_for_array_format_datatype(enum mesa_array_format_datatype type)<br>
    }<br>
 }<br>
<br>
+/* Takes a src to RGBA swizzle and applies a rebase swizzle to it. This<br>
+ * is used when we need to rebase a format to match a different<br>
+ * base internal format.<br>
+ *<br>
+ * The rebase swizzle can be NULL, which means that no rebase is necessary,<br>
+ * in which case the src to RGBA swizzle is copied to the output without<br>
+ * changes.<br>
+ *<br>
+ * The resulting rebased swizzle and well as the input swizzles are<br>
+ * all 4-element swizzles, but the rebase swizzle can be NULL if no rebase<br>
+ * is necessary.<br>
+ */<br>
+static void<br>
+compute_rebased_rgba_component_mapping(uint8_t *src2rgba,<br>
+                                       uint8_t *rebase_swizzle,<br>
+                                       uint8_t *rebased_src2rgba)<br>
+{<br>
+   int i;<br>
+<br>
+   if (rebase_swizzle) {<br>
+      for (i = 0; i < 4; i++) {<br>
+         if (rebase_swizzle[i] > MESA_FORMAT_SWIZZLE_W)<br>
+            rebased_src2rgba[i] = rebase_swizzle[i];<br>
+         else<br>
+            rebased_src2rgba[i] = src2rgba[rebase_swizzle[i]];<br>
+      }<br>
+   } else {<br>
+      /* No rebase needed, so src2rgba is all that we need */<br>
+      memcpy(rebased_src2rgba, src2rgba, 4 * sizeof(uint8_t));<br>
+   }<br>
+}<br>
+<br>
+/* Computes the final swizzle transform to apply from src to dst in a<br>
+ * conversion that might involve a rebase swizzle.<br>
+ *<br>
+ * This is used to compute the swizzle transform to apply in conversions<br>
+ * between array formats where we have a src2rgba swizzle, a rgba2dst swizzle<br>
+ * and possibly, a rebase swizzle.<br>
+ *<br>
+ * The final swizzle transform to apply (src2dst) when a rebase swizzle is<br>
+ * involved is: src -> rgba -> base -> rgba -> dst<br>
+ */<br>
+static void<br>
+compute_src2dst_component_mapping(uint8_t *src2rgba, uint8_t *rgba2dst,<br>
+                                  uint8_t *rebase_swizzle, uint8_t *src2dst)<br>
+{<br>
+   int i;<br>
+<br>
+   if (!rebase_swizzle) {<br>
+      for (i = 0; i < 4; i++) {<br>
+         if (rgba2dst[i] > MESA_FORMAT_SWIZZLE_W) {<br>
+            src2dst[i] = rgba2dst[i];<br>
+         } else {<br>
+            src2dst[i] = src2rgba[rgba2dst[i]];<br>
+         }<br>
+      }<br>
+   } else {<br>
+      for (i = 0; i < 4; i++) {<br>
+         if (rgba2dst[i] > MESA_FORMAT_SWIZZLE_W) {<br>
+            src2dst[i] = rgba2dst[i];<br>
+         } else if (rebase_swizzle[rgba2dst[i]] > MESA_FORMAT_SWIZZLE_W) {<br>
+            src2dst[i] = rebase_swizzle[rgba2dst[i]];<br>
+         } else {<br>
+            src2dst[i] = src2rgba[rebase_swizzle[rgba2dst[i]]];<br>
+         }<br>
+      }<br>
+   }<br>
+}<br>
+<br>
 /**<br>
  * This can be used to convert between most color formats.<br>
  *<br>
@@ -299,24 +368,31 @@ gl_type_for_array_format_datatype(enum mesa_array_format_datatype type)<br>
  * \param src_stride  The stride of the source format in bytes.<br>
  * \param width  The width, in pixels, of the source image to convert.<br>
  * \param height  The height, in pixels, of the source image to convert.<br>
+ * \param rebase_swizzle  A swizzle transform to apply during the conversion,<br>
+ *                        typically used to match a different internal base<br>
+ *                        format involved. NULL if no rebase transform is needed<br>
+ *                        (i.e. the internal base format and the base format of<br>
+ *                        the dst or the src -depending on whether we are doing<br>
+ *                        an upload or a download respectively- are the same).<br>
  */<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, uint8_t *rebase_swizzle)<br>
 {<br>
    uint8_t *dst = (uint8_t *)void_dst;<br>
    uint8_t *src = (uint8_t *)void_src;<br>
    mesa_array_format src_array_format, dst_array_format;<br>
    bool src_format_is_mesa_array_format, dst_format_is_mesa_array_format;<br>
    uint8_t src2dst[4], src2rgba[4], rgba2dst[4], dst2rgba[4];<br>
+   uint8_t rebased_src2rgba[4];<br>
    GLenum src_gl_type, dst_gl_type, common_gl_type;<br>
    bool normalized, dst_integer, src_integer, is_signed;<br>
    int src_num_channels = 0, dst_num_channels = 0;<br>
    uint8_t (*tmp_ubyte)[4];<br>
    float (*tmp_float)[4];<br>
    uint32_t (*tmp_uint)[4];<br>
-   int i, bits;<br>
+   int bits;<br>
    size_t row;<br>
<br>
    if (_mesa_format_is_mesa_array_format(src_format)) {<br>
@@ -337,67 +413,79 @@ _mesa_format_convert(void *void_dst, uint32_t dst_format, size_t dst_stride,<br>
       dst_array_format = _mesa_format_to_array_format(dst_format);<br>
    }<br>
<br>
-   /* Handle the cases where we can directly unpack */<br>
-   if (!src_format_is_mesa_array_format) {<br>
-      if (dst_array_format == RGBA8888_FLOAT) {<br>
-         for (row = 0; row < height; ++row) {<br>
-            _mesa_unpack_rgba_row(src_format, width,<br>
-                                  src, (float (*)[4])dst);<br>
-            src += src_stride;<br>
-            dst += dst_stride;<br>
-         }<br>
-         return;<br>
-      } else if (dst_array_format == RGBA8888_UBYTE) {<br>
-         assert(!_mesa_is_format_integer_color(src_format));<br>
-         for (row = 0; row < height; ++row) {<br>
-            _mesa_unpack_ubyte_rgba_row(src_format, width,<br>
-                                        src, (uint8_t (*)[4])dst);<br>
-            src += src_stride;<br>
-            dst += dst_stride;<br>
-         }<br>
-         return;<br>
-      } else if (dst_array_format == RGBA8888_UINT &&<br>
-                 _mesa_is_format_unsigned(src_format)) {<br>
-         assert(_mesa_is_format_integer_color(src_format));<br>
-         for (row = 0; row < height; ++row) {<br>
-            _mesa_unpack_uint_rgba_row(src_format, width,<br>
-                                       src, (uint32_t (*)[4])dst);<br>
-            src += src_stride;<br>
-            dst += dst_stride;<br>
+   /* First we see if we can implement the conversion with a direct pack<br>
+    * or unpack.<br>
+    *<br>
+    * In this case we want to be careful when we need to apply a swizzle to<br>
+    * match an internal base format, since in these cases a simple pack/unpack<br>
+    * to the dst format from the src format may not match the requirements<br>
+    * of the internal base format. For now we decide to be safe and<br>
+    * avoid this path in these scenarios but in the future we may want to<br>
+    * enable it for specific combinations that are known to work.<br>
+    */<br>
+   if (!rebase_swizzle) {<br>
+      /* Handle the cases where we can directly unpack */<br>
+      if (!src_format_is_mesa_array_format) {<br>
+         if (dst_array_format == RGBA8888_FLOAT) {<br>
+            for (row = 0; row < height; ++row) {<br>
+               _mesa_unpack_rgba_row(src_format, width,<br>
+                                     src, (float (*)[4])dst);<br>
+               src += src_stride;<br>
+               dst += dst_stride;<br>
+            }<br>
+            return;<br>
+         } else if (dst_array_format == RGBA8888_UBYTE) {<br>
+            assert(!_mesa_is_format_integer_color(src_format));<br>
+            for (row = 0; row < height; ++row) {<br>
+               _mesa_unpack_ubyte_rgba_row(src_format, width,<br>
+                                           src, (uint8_t (*)[4])dst);<br>
+               src += src_stride;<br>
+               dst += dst_stride;<br>
+            }<br>
+            return;<br>
+         } else if (dst_array_format == RGBA8888_UINT &&<br>
+                    _mesa_is_format_unsigned(src_format)) {<br>
+            assert(_mesa_is_format_integer_color(src_format));<br>
+            for (row = 0; row < height; ++row) {<br>
+               _mesa_unpack_uint_rgba_row(src_format, width,<br>
+                                          src, (uint32_t (*)[4])dst);<br>
+               src += src_stride;<br>
+               dst += dst_stride;<br>
+            }<br>
+            return;<br>
          }<br>
-         return;<br>
       }<br>
-   }<br>
<br>
-   /* Handle the cases where we can directly pack */<br>
-   if (!dst_format_is_mesa_array_format) {<br>
-      if (src_array_format == RGBA8888_FLOAT) {<br>
-         for (row = 0; row < height; ++row) {<br>
-            _mesa_pack_float_rgba_row(dst_format, width,<br>
-                                      (const float (*)[4])src, dst);<br>
-            src += src_stride;<br>
-            dst += dst_stride;<br>
-         }<br>
-         return;<br>
-      } else if (src_array_format == RGBA8888_UBYTE) {<br>
-         assert(!_mesa_is_format_integer_color(dst_format));<br>
-         for (row = 0; row < height; ++row) {<br>
-            _mesa_pack_ubyte_rgba_row(dst_format, width,<br>
-                                      (const uint8_t (*)[4])src, dst);<br>
-            src += src_stride;<br>
-            dst += dst_stride;<br>
-         }<br>
-         return;<br>
-      } else if (src_array_format == RGBA8888_UINT &&<br>
-                 _mesa_is_format_unsigned(dst_format)) {<br>
-         assert(_mesa_is_format_integer_color(dst_format));<br>
-         for (row = 0; row < height; ++row) {<br>
-            _mesa_pack_uint_rgba_row(dst_format, width,<br>
-                                     (const uint32_t (*)[4])src, dst);<br>
-            src += src_stride;<br>
-            dst += dst_stride;<br>
+      /* Handle the cases where we can directly pack */<br>
+      if (!dst_format_is_mesa_array_format) {<br>
+         if (src_array_format == RGBA8888_FLOAT) {<br>
+            for (row = 0; row < height; ++row) {<br>
+               _mesa_pack_float_rgba_row(dst_format, width,<br>
+                                         (const float (*)[4])src, dst);<br>
+               src += src_stride;<br>
+               dst += dst_stride;<br>
+            }<br>
+            return;<br>
+         } else if (src_array_format == RGBA8888_UBYTE) {<br>
+            assert(!_mesa_is_format_integer_color(dst_format));<br>
+            for (row = 0; row < height; ++row) {<br>
+               _mesa_pack_ubyte_rgba_row(dst_format, width,<br>
+                                         (const uint8_t (*)[4])src, dst);<br>
+               src += src_stride;<br>
+               dst += dst_stride;<br>
+            }<br>
+            return;<br>
+         } else if (src_array_format == RGBA8888_UINT &&<br>
+                    _mesa_is_format_unsigned(dst_format)) {<br>
+            assert(_mesa_is_format_integer_color(dst_format));<br>
+            for (row = 0; row < height; ++row) {<br>
+               _mesa_pack_uint_rgba_row(dst_format, width,<br>
+                                        (const uint32_t (*)[4])src, dst);<br>
+               src += src_stride;<br>
+               dst += dst_stride;<br>
+            }<br>
+            return;<br>
          }<br>
-         return;<br>
       }<br>
    }<br>
<br>
@@ -432,13 +520,8 @@ _mesa_format_convert(void *void_dst, uint32_t dst_format, size_t dst_stride,<br>
       assert(_mesa_array_format_is_normalized(src_array_format) ==<br>
              _mesa_array_format_is_normalized(dst_array_format));<br>
<br>
-      for (i = 0; i < 4; i++) {<br>
-         if (rgba2dst[i] > MESA_FORMAT_SWIZZLE_W) {<br>
-            src2dst[i] = rgba2dst[i];<br>
-         } else {<br>
-            src2dst[i] = src2rgba[rgba2dst[i]];<br>
-         }<br>
-      }<br>
+      compute_src2dst_component_mapping(src2rgba, rgba2dst, rebase_swizzle,<br>
+                                        src2dst);<br>
<br>
       for (row = 0; row < height; ++row) {<br>
          _mesa_swizzle_and_convert(dst, dst_gl_type, dst_num_channels,<br>
@@ -526,16 +609,22 @@ _mesa_format_convert(void *void_dst, uint32_t dst_format, size_t dst_stride,<br>
        */<br>
       common_gl_type = is_signed ? GL_INT : GL_UNSIGNED_INT;<br>
       if (src_array_format) {<br>
+         compute_rebased_rgba_component_mapping(src2rgba, rebase_swizzle,<br>
+                                                rebased_src2rgba);<br>
          for (row = 0; row < height; ++row) {<br>
             _mesa_swizzle_and_convert(tmp_uint + row * width, common_gl_type, 4,<br>
                                       src, src_gl_type, src_num_channels,<br>
-                                      src2rgba, normalized, width);<br>
+                                      rebased_src2rgba, normalized, width);<br>
             src += src_stride;<br>
          }<br>
       } else {<br>
          for (row = 0; row < height; ++row) {<br>
             _mesa_unpack_uint_rgba_row(src_format, width,<br>
                                        src, tmp_uint + row * width);<br>
+            if (rebase_swizzle)<br>
+               _mesa_swizzle_and_convert(tmp_uint + row * width, common_gl_type, 4,<br>
+                                         tmp_uint + row * width, common_gl_type, 4,<br>
+                                         rebase_swizzle, false, width);<br>
             src += src_stride;<br>
          }<br>
       }<br>
@@ -564,16 +653,22 @@ _mesa_format_convert(void *void_dst, uint32_t dst_format, size_t dst_stride,<br>
       tmp_float = malloc(width * height * sizeof(*tmp_float));<br>
<br>
       if (src_format_is_mesa_array_format) {<br>
+         compute_rebased_rgba_component_mapping(src2rgba, rebase_swizzle,<br>
+                                                rebased_src2rgba);<br>
          for (row = 0; row < height; ++row) {<br>
             _mesa_swizzle_and_convert(tmp_float + row * width, GL_FLOAT, 4,<br>
                                       src, src_gl_type, src_num_channels,<br>
-                                      src2rgba, normalized, width);<br>
+                                      rebased_src2rgba, normalized, width);<br>
             src += src_stride;<br>
          }<br>
       } else {<br>
          for (row = 0; row < height; ++row) {<br>
             _mesa_unpack_rgba_row(src_format, width,<br>
                                   src, tmp_float + row * width);<br>
+            if (rebase_swizzle)<br>
+               _mesa_swizzle_and_convert(tmp_float + row * width, GL_FLOAT, 4,<br>
+                                         tmp_float + row * width, GL_FLOAT, 4,<br>
+                                         rebase_swizzle, false, width);<br>
             src += src_stride;<br>
          }<br>
       }<br>
@@ -598,16 +693,22 @@ _mesa_format_convert(void *void_dst, uint32_t dst_format, size_t dst_stride,<br>
       tmp_ubyte = malloc(width * height * sizeof(*tmp_ubyte));<br>
<br>
       if (src_format_is_mesa_array_format) {<br>
+         compute_rebased_rgba_component_mapping(src2rgba, rebase_swizzle,<br>
+                                                rebased_src2rgba);<br>
          for (row = 0; row < height; ++row) {<br>
             _mesa_swizzle_and_convert(tmp_ubyte + row * width, GL_UNSIGNED_BYTE, 4,<br>
                                       src, src_gl_type, src_num_channels,<br>
-                                      src2rgba, normalized, width);<br>
+                                      rebased_src2rgba, normalized, width);<br>
             src += src_stride;<br>
          }<br>
       } else {<br>
          for (row = 0; row < height; ++row) {<br>
             _mesa_unpack_ubyte_rgba_row(src_format, width,<br>
                                         src, tmp_ubyte + row * width);<br>
+            if (rebase_swizzle)<br>
+               _mesa_swizzle_and_convert(tmp_ubyte + row * width, GL_UNSIGNED_BYTE, 4,<br>
+                                         tmp_ubyte + row * width, GL_UNSIGNED_BYTE, 4,<br>
+                                         rebase_swizzle, 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 28b4715..1633f1e 100644<br>
--- a/src/mesa/main/format_utils.h<br>
+++ b/src/mesa/main/format_utils.h<br>
@@ -184,6 +184,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, uint8_t *rebase_swizzle);<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></div>