<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>