Re: [Mesa-dev] [PATCH 05/29] mesa: Consider internal base format in _mesa_format_convert
On Thu, 2014-11-20 at 08:42 +0100, Iago Toral wrote: On Wed, 2014-11-19 at 11:43 -0800, Jason Ekstrand wrote: 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? I thought about that too but when I looked at the original code it seemed that it only cared for the base format in these two scenarios, so I thought that maybe the conversions cases that could be affected are all handled in those two paths. I'll check again though, just in case I missed something. I don't know how I came to that conclusion but it seems wrong after looking at the original code in texstore.c, which considers the base internal format in the integer, float and ubyte paths too, so we should do the same in _mesa_format_convert. I'll fix that. Iago On Tue, Nov 18, 2014 at 1:23 AM, Iago Toral Quiroga ito...@igalia.com wrote: Add a dst_internal_format parameter to _mesa_format_convert, that represents the base internal format for texture/pixel uploads, so we can do the right thing when the driver has selected a different internal format for the target dst format. --- src/mesa/main/format_utils.c | 65 +++- src/mesa/main/format_utils.h | 2 +- 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/src/mesa/main/format_utils.c b/src/mesa/main/format_utils.c index fc59e86..5964689 100644 --- a/src/mesa/main/format_utils.c +++ b/src/mesa/main/format_utils.c @@ -303,7 +303,7 @@ _mesa_compute_component_mapping(GLenum inFormat, GLenum outFormat, GLubyte *map) void _mesa_format_convert(void *void_dst, uint32_t dst_format, size_t dst_stride, void *void_src, uint32_t src_format, size_t src_stride, - size_t width, size_t height) + size_t width, size_t height, GLenum dst_internal_format) { uint8_t *dst = (uint8_t *)void_dst; uint8_t *src = (uint8_t *)void_src; @@ -422,6 +422,36 @@ _mesa_format_convert(void *void_dst, uint32_t dst_format, size_t dst_stride, if (src_array_format.as_uint dst_array_format.as_uint) { assert(src_array_format.normalized == dst_array_format.normalized); + /* If the base format of our dst is not the same as the provided base + * format it means that we are converting to a different format + * than the one originally requested by the client. This can happen when + * the internal base format requested is not supported by the driver. + * In this case we need to consider the requested internal base format to + * compute the correct swizzle operation from src to dst. We will do this + * by computing the swizzle transform src-rgba-base-rgba-dst instead + * of src-rgba-dst. + */ + mesa_format dst_mesa_format; + if (dst_format MESA_ARRAY_FORMAT_BIT) + dst_mesa_format = _mesa_format_from_array_format(dst_format); + else + dst_mesa_format = dst_format; Let's put an extra line here so it doesn't get confused with the below if statement + if (dst_internal_format != _mesa_get_format_base_format(dst_mesa_format)) { + /* Compute src2rgba as src-rgba-base-rgba */ + uint8_t rgba2base[4], base2rgba[4], swizzle[4]; + _mesa_compute_component_mapping(GL_RGBA, dst_internal_format, rgba2base); + _mesa_compute_component_mapping(dst_internal_format, GL_RGBA, base2rgba); + + for (i = 0; i 4; i++) { +if (base2rgba[i] MESA_FORMAT_SWIZZLE_W) + swizzle[i] = base2rgba[i]; +else + swizzle[i] = src2rgba[rgba2base[base2rgba[i]]]; 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. Actually, the problem is worse, because the mapping written by _mesa_compute_component_mapping is a 6-component mapping and we are passing a 4-component array. I'll fix this. + } + memcpy(src2rgba, swizzle, sizeof(src2rgba)); + } + + /* Compute src2dst from src2rgba */ for (i = 0; i 4; i++) {
Re: [Mesa-dev] [PATCH 05/29] mesa: Consider internal base format in _mesa_format_convert
On Wed, Nov 19, 2014 at 11:42 PM, Iago Toral ito...@igalia.com wrote: On Wed, 2014-11-19 at 11:43 -0800, Jason Ekstrand wrote: 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? I thought about that too but when I looked at the original code it seemed that it only cared for the base format in these two scenarios, so I thought that maybe the conversions cases that could be affected are all handled in those two paths. I'll check again though, just in case I missed something. On Tue, Nov 18, 2014 at 1:23 AM, Iago Toral Quiroga ito...@igalia.com wrote: Add a dst_internal_format parameter to _mesa_format_convert, that represents the base internal format for texture/pixel uploads, so we can do the right thing when the driver has selected a different internal format for the target dst format. --- src/mesa/main/format_utils.c | 65 +++- src/mesa/main/format_utils.h | 2 +- 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/src/mesa/main/format_utils.c b/src/mesa/main/format_utils.c index fc59e86..5964689 100644 --- a/src/mesa/main/format_utils.c +++ b/src/mesa/main/format_utils.c @@ -303,7 +303,7 @@ _mesa_compute_component_mapping(GLenum inFormat, GLenum outFormat, GLubyte *map) void _mesa_format_convert(void *void_dst, uint32_t dst_format, size_t dst_stride, void *void_src, uint32_t src_format, size_t src_stride, - size_t width, size_t height) + size_t width, size_t height, GLenum dst_internal_format) { uint8_t *dst = (uint8_t *)void_dst; uint8_t *src = (uint8_t *)void_src; @@ -422,6 +422,36 @@ _mesa_format_convert(void *void_dst, uint32_t dst_format, size_t dst_stride, if (src_array_format.as_uint dst_array_format.as_uint) { assert(src_array_format.normalized == dst_array_format.normalized); + /* If the base format of our dst is not the same as the provided base + * format it means that we are converting to a different format + * than the one originally requested by the client. This can happen when + * the internal base format requested is not supported by the driver. + * In this case we need to consider the requested internal base format to + * compute the correct swizzle operation from src to dst. We will do this + * by computing the swizzle transform src-rgba-base-rgba-dst instead + * of src-rgba-dst. + */ + mesa_format dst_mesa_format; + if (dst_format MESA_ARRAY_FORMAT_BIT) + dst_mesa_format = _mesa_format_from_array_format(dst_format); + else + dst_mesa_format = dst_format; Let's put an extra line here so it doesn't get confused with the below if statement + if (dst_internal_format != _mesa_get_format_base_format(dst_mesa_format)) { + /* Compute src2rgba as src-rgba-base-rgba */ + uint8_t rgba2base[4], base2rgba[4], swizzle[4]; + _mesa_compute_component_mapping(GL_RGBA, dst_internal_format, rgba2base); + _mesa_compute_component_mapping(dst_internal_format, GL_RGBA, base2rgba); + + for (i = 0; i 4; i++) { +if (base2rgba[i] MESA_FORMAT_SWIZZLE_W) + swizzle[i] = base2rgba[i]; +else + swizzle[i] = src2rgba[rgba2base[base2rgba[i]]]; 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. Actually, the problem is worse, because the mapping written by _mesa_compute_component_mapping is a 6-component mapping and we are passing a 4-component array. I'll fix this. 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. + } + memcpy(src2rgba, swizzle, sizeof(src2rgba)); + } + + /* Compute src2dst from
Re: [Mesa-dev] [PATCH 05/29] mesa: Consider internal base format in _mesa_format_convert
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? On Tue, Nov 18, 2014 at 1:23 AM, Iago Toral Quiroga ito...@igalia.com wrote: Add a dst_internal_format parameter to _mesa_format_convert, that represents the base internal format for texture/pixel uploads, so we can do the right thing when the driver has selected a different internal format for the target dst format. --- src/mesa/main/format_utils.c | 65 +++- src/mesa/main/format_utils.h | 2 +- 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/src/mesa/main/format_utils.c b/src/mesa/main/format_utils.c index fc59e86..5964689 100644 --- a/src/mesa/main/format_utils.c +++ b/src/mesa/main/format_utils.c @@ -303,7 +303,7 @@ _mesa_compute_component_mapping(GLenum inFormat, GLenum outFormat, GLubyte *map) void _mesa_format_convert(void *void_dst, uint32_t dst_format, size_t dst_stride, void *void_src, uint32_t src_format, size_t src_stride, - size_t width, size_t height) + size_t width, size_t height, GLenum dst_internal_format) { uint8_t *dst = (uint8_t *)void_dst; uint8_t *src = (uint8_t *)void_src; @@ -422,6 +422,36 @@ _mesa_format_convert(void *void_dst, uint32_t dst_format, size_t dst_stride, if (src_array_format.as_uint dst_array_format.as_uint) { assert(src_array_format.normalized == dst_array_format.normalized); + /* If the base format of our dst is not the same as the provided base + * format it means that we are converting to a different format + * than the one originally requested by the client. This can happen when + * the internal base format requested is not supported by the driver. + * In this case we need to consider the requested internal base format to + * compute the correct swizzle operation from src to dst. We will do this + * by computing the swizzle transform src-rgba-base-rgba-dst instead + * of src-rgba-dst. + */ + mesa_format dst_mesa_format; + if (dst_format MESA_ARRAY_FORMAT_BIT) + dst_mesa_format = _mesa_format_from_array_format(dst_format); + else + dst_mesa_format = dst_format; Let's put an extra line here so it doesn't get confused with the below if statement + if (dst_internal_format != _mesa_get_format_base_format(dst_mesa_format)) { + /* Compute src2rgba as src-rgba-base-rgba */ + uint8_t rgba2base[4], base2rgba[4], swizzle[4]; + _mesa_compute_component_mapping(GL_RGBA, dst_internal_format, rgba2base); + _mesa_compute_component_mapping(dst_internal_format, GL_RGBA, base2rgba); + + for (i = 0; i 4; i++) { +if (base2rgba[i] MESA_FORMAT_SWIZZLE_W) + swizzle[i] = base2rgba[i]; +else + swizzle[i] = src2rgba[rgba2base[base2rgba[i]]]; 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. + } + memcpy(src2rgba, swizzle, sizeof(src2rgba)); + } + + /* Compute src2dst from src2rgba */ for (i = 0; i 4; i++) { if (rgba2dst[i] MESA_FORMAT_SWIZZLE_W) { src2dst[i] = rgba2dst[i]; @@ -539,9 +569,42 @@ _mesa_format_convert(void *void_dst, uint32_t dst_format, size_t dst_stride, src += src_stride; } } else { + /* For some conversions, doing src-rgba-dst is not enough and we + * need to consider the base internal format. In these cases a + * swizzle operation is required to match the semantics of the base + * internal format requested: src-rgba-swizzle-rgba-dst. + * + * We can detect these cases by checking if the swizzle transform + * for base-rgba-base is 0123. If it is not, then we need + * to do the swizzle operation (need_convert = true). + */ + GLubyte rgba2base[4], base2rgba[4], map[4]; + bool need_convert = false; + mesa_format dst_mesa_format; + if (dst_format MESA_ARRAY_FORMAT_BIT) +dst_mesa_format = _mesa_format_from_array_format(dst_format); + else +dst_mesa_format = dst_format; Blank line again + if (dst_internal_format != + _mesa_get_format_base_format(dst_mesa_format)) { +_mesa_compute_component_mapping(GL_RGBA, dst_internal_format, +base2rgba); +_mesa_compute_component_mapping(dst_internal_format, GL_RGBA, +rgba2base); +for (i = 0; i 4; ++i) { + map[i] = base2rgba[rgba2base[i]]; + if (map[i] != i) +
Re: [Mesa-dev] [PATCH 05/29] mesa: Consider internal base format in _mesa_format_convert
On Wed, 2014-11-19 at 11:43 -0800, Jason Ekstrand wrote: 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? I thought about that too but when I looked at the original code it seemed that it only cared for the base format in these two scenarios, so I thought that maybe the conversions cases that could be affected are all handled in those two paths. I'll check again though, just in case I missed something. On Tue, Nov 18, 2014 at 1:23 AM, Iago Toral Quiroga ito...@igalia.com wrote: Add a dst_internal_format parameter to _mesa_format_convert, that represents the base internal format for texture/pixel uploads, so we can do the right thing when the driver has selected a different internal format for the target dst format. --- src/mesa/main/format_utils.c | 65 +++- src/mesa/main/format_utils.h | 2 +- 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/src/mesa/main/format_utils.c b/src/mesa/main/format_utils.c index fc59e86..5964689 100644 --- a/src/mesa/main/format_utils.c +++ b/src/mesa/main/format_utils.c @@ -303,7 +303,7 @@ _mesa_compute_component_mapping(GLenum inFormat, GLenum outFormat, GLubyte *map) void _mesa_format_convert(void *void_dst, uint32_t dst_format, size_t dst_stride, void *void_src, uint32_t src_format, size_t src_stride, - size_t width, size_t height) + size_t width, size_t height, GLenum dst_internal_format) { uint8_t *dst = (uint8_t *)void_dst; uint8_t *src = (uint8_t *)void_src; @@ -422,6 +422,36 @@ _mesa_format_convert(void *void_dst, uint32_t dst_format, size_t dst_stride, if (src_array_format.as_uint dst_array_format.as_uint) { assert(src_array_format.normalized == dst_array_format.normalized); + /* If the base format of our dst is not the same as the provided base + * format it means that we are converting to a different format + * than the one originally requested by the client. This can happen when + * the internal base format requested is not supported by the driver. + * In this case we need to consider the requested internal base format to + * compute the correct swizzle operation from src to dst. We will do this + * by computing the swizzle transform src-rgba-base-rgba-dst instead + * of src-rgba-dst. + */ + mesa_format dst_mesa_format; + if (dst_format MESA_ARRAY_FORMAT_BIT) + dst_mesa_format = _mesa_format_from_array_format(dst_format); + else + dst_mesa_format = dst_format; Let's put an extra line here so it doesn't get confused with the below if statement + if (dst_internal_format != _mesa_get_format_base_format(dst_mesa_format)) { + /* Compute src2rgba as src-rgba-base-rgba */ + uint8_t rgba2base[4], base2rgba[4], swizzle[4]; + _mesa_compute_component_mapping(GL_RGBA, dst_internal_format, rgba2base); + _mesa_compute_component_mapping(dst_internal_format, GL_RGBA, base2rgba); + + for (i = 0; i 4; i++) { +if (base2rgba[i] MESA_FORMAT_SWIZZLE_W) + swizzle[i] = base2rgba[i]; +else + swizzle[i] = src2rgba[rgba2base[base2rgba[i]]]; 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. Actually, the problem is worse, because the mapping written by _mesa_compute_component_mapping is a 6-component mapping and we are passing a 4-component array. I'll fix this. + } + memcpy(src2rgba, swizzle, sizeof(src2rgba)); + } + + /* Compute src2dst from src2rgba */ for (i = 0; i 4; i++) { if (rgba2dst[i] MESA_FORMAT_SWIZZLE_W) { src2dst[i] = rgba2dst[i]; @@ -539,9 +569,42 @@ _mesa_format_convert(void *void_dst, uint32_t dst_format, size_t dst_stride, src += src_stride; } } else { + /* For some conversions, doing src-rgba-dst is not enough and we + * need to
[Mesa-dev] [PATCH 05/29] mesa: Consider internal base format in _mesa_format_convert
Add a dst_internal_format parameter to _mesa_format_convert, that represents the base internal format for texture/pixel uploads, so we can do the right thing when the driver has selected a different internal format for the target dst format. --- src/mesa/main/format_utils.c | 65 +++- src/mesa/main/format_utils.h | 2 +- 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/src/mesa/main/format_utils.c b/src/mesa/main/format_utils.c index fc59e86..5964689 100644 --- a/src/mesa/main/format_utils.c +++ b/src/mesa/main/format_utils.c @@ -303,7 +303,7 @@ _mesa_compute_component_mapping(GLenum inFormat, GLenum outFormat, GLubyte *map) void _mesa_format_convert(void *void_dst, uint32_t dst_format, size_t dst_stride, void *void_src, uint32_t src_format, size_t src_stride, - size_t width, size_t height) + size_t width, size_t height, GLenum dst_internal_format) { uint8_t *dst = (uint8_t *)void_dst; uint8_t *src = (uint8_t *)void_src; @@ -422,6 +422,36 @@ _mesa_format_convert(void *void_dst, uint32_t dst_format, size_t dst_stride, if (src_array_format.as_uint dst_array_format.as_uint) { assert(src_array_format.normalized == dst_array_format.normalized); + /* If the base format of our dst is not the same as the provided base + * format it means that we are converting to a different format + * than the one originally requested by the client. This can happen when + * the internal base format requested is not supported by the driver. + * In this case we need to consider the requested internal base format to + * compute the correct swizzle operation from src to dst. We will do this + * by computing the swizzle transform src-rgba-base-rgba-dst instead + * of src-rgba-dst. + */ + mesa_format dst_mesa_format; + if (dst_format MESA_ARRAY_FORMAT_BIT) + dst_mesa_format = _mesa_format_from_array_format(dst_format); + else + dst_mesa_format = dst_format; + if (dst_internal_format != _mesa_get_format_base_format(dst_mesa_format)) { + /* Compute src2rgba as src-rgba-base-rgba */ + uint8_t rgba2base[4], base2rgba[4], swizzle[4]; + _mesa_compute_component_mapping(GL_RGBA, dst_internal_format, rgba2base); + _mesa_compute_component_mapping(dst_internal_format, GL_RGBA, base2rgba); + + for (i = 0; i 4; i++) { +if (base2rgba[i] MESA_FORMAT_SWIZZLE_W) + swizzle[i] = base2rgba[i]; +else + swizzle[i] = src2rgba[rgba2base[base2rgba[i]]]; + } + memcpy(src2rgba, swizzle, sizeof(src2rgba)); + } + + /* Compute src2dst from src2rgba */ for (i = 0; i 4; i++) { if (rgba2dst[i] MESA_FORMAT_SWIZZLE_W) { src2dst[i] = rgba2dst[i]; @@ -539,9 +569,42 @@ _mesa_format_convert(void *void_dst, uint32_t dst_format, size_t dst_stride, src += src_stride; } } else { + /* For some conversions, doing src-rgba-dst is not enough and we + * need to consider the base internal format. In these cases a + * swizzle operation is required to match the semantics of the base + * internal format requested: src-rgba-swizzle-rgba-dst. + * + * We can detect these cases by checking if the swizzle transform + * for base-rgba-base is 0123. If it is not, then we need + * to do the swizzle operation (need_convert = true). + */ + GLubyte rgba2base[4], base2rgba[4], map[4]; + bool need_convert = false; + mesa_format dst_mesa_format; + if (dst_format MESA_ARRAY_FORMAT_BIT) +dst_mesa_format = _mesa_format_from_array_format(dst_format); + else +dst_mesa_format = dst_format; + if (dst_internal_format != + _mesa_get_format_base_format(dst_mesa_format)) { +_mesa_compute_component_mapping(GL_RGBA, dst_internal_format, +base2rgba); +_mesa_compute_component_mapping(dst_internal_format, GL_RGBA, +rgba2base); +for (i = 0; i 4; ++i) { + map[i] = base2rgba[rgba2base[i]]; + if (map[i] != i) + need_convert = true; +} + } + for (row = 0; row height; ++row) { _mesa_unpack_rgba_row(src_format, width, src, tmp_float + row * width); +if (need_convert) + _mesa_swizzle_and_convert(tmp_float + row * width, GL_FLOAT, 4, + tmp_float + row * width, GL_FLOAT, 4, + map, false, width); src += src_stride; } } diff --git a/src/mesa/main/format_utils.h