<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Sat, Apr 28, 2018 at 4:14 AM, Karol Herbst <span dir="ltr"><<a href="mailto:kherbst@redhat.com" target="_blank">kherbst@redhat.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">OpenCL has explicit casts where one can specify the rounding mode and put a<br>
sat modifier:<br>
<br>
<a href="https://www.khronos.org/registry/OpenCL/sdk/2.1/docs/man/xhtml/convert_T.html" rel="noreferrer" target="_blank">https://www.khronos.org/<wbr>registry/OpenCL/sdk/2.1/docs/<wbr>man/xhtml/convert_T.html</a><br>
<br>
_sat is valid for all conversions to an integer type and rounding modes are<br>
valid for all conversions involving floats.<br>
<br>
Allthough the FPRoundingMode modifier is allowed without any restrictions in<br>
capabilities, it can only be used together with fp16 in GLSL. Additionally it<br>
can be used for conversions to/from floating points in OpenCL.<br>
<br>
The SaturatedConversion modifier, OpSatConvertUToS and OpSatConvertSToU are<br>
only supported for Kernels, so current drivers are safe.<br>
<br>
Signed-off-by: Karol Herbst <<a href="mailto:kherbst@redhat.com">kherbst@redhat.com</a>><br>
---<br>
src/compiler/glsl/glsl_to_nir.<wbr>cpp | 2 +-<br>
src/compiler/nir/nir.h | 2 +-<br>
src/compiler/nir/nir_opcodes.<wbr>py | 28 +++++-----<br>
src/compiler/nir/nir_opcodes_<wbr>c.py | 26 +++++----<br>
src/compiler/spirv/spirv_to_<wbr>nir.c | 4 +-<br>
src/compiler/spirv/vtn_alu.c | 108 ++++++++++++++++++++++++------<wbr>--------<br>
src/compiler/spirv/vtn_<wbr>glsl450.c | 2 +-<br>
src/compiler/spirv/vtn_<wbr>private.h | 2 +-<br>
8 files changed, 107 insertions(+), 67 deletions(-)<br>
<br>
diff --git a/src/compiler/glsl/glsl_to_<wbr>nir.cpp b/src/compiler/glsl/glsl_to_<wbr>nir.cpp<br>
index 8e5e9c34912..fcb6ef27e47 100644<br>
--- a/src/compiler/glsl/glsl_to_<wbr>nir.cpp<br>
+++ b/src/compiler/glsl/glsl_to_<wbr>nir.cpp<br>
@@ -1589,7 +1589,7 @@ nir_visitor::visit(ir_<wbr>expression *ir)<br>
nir_alu_type src_type = nir_get_nir_type_for_glsl_<wbr>base_type(types[0]);<br>
nir_alu_type dst_type = nir_get_nir_type_for_glsl_<wbr>base_type(out_type);<br>
result = nir_build_alu(&b, nir_type_conversion_op(src_<wbr>type, dst_type,<br>
- nir_rounding_mode_undef),<br>
+ nir_rounding_mode_undef, false),<br>
srcs[0], NULL, NULL, NULL);<br>
/* b2i and b2f don't have fixed bit-size versions so the builder will<br>
* just assume 32 and we have to fix it up here.<br>
diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h<br>
index f3326e6df94..f32e5bd8bb2 100644<br>
--- a/src/compiler/nir/nir.h<br>
+++ b/src/compiler/nir/nir.h<br>
@@ -784,7 +784,7 @@ nir_get_nir_type_for_glsl_<wbr>type(const struct glsl_type *type)<br>
}<br>
<br>
nir_op nir_type_conversion_op(nir_<wbr>alu_type src, nir_alu_type dst,<br>
- nir_rounding_mode rnd);<br>
+ nir_rounding_mode rnd, bool saturation);<br>
<br>
typedef enum {<br>
NIR_OP_IS_COMMUTATIVE = (1 << 0),<br>
diff --git a/src/compiler/nir/nir_<wbr>opcodes.py b/src/compiler/nir/nir_<wbr>opcodes.py<br>
index f4cd175bc6a..9c51f77bf1b 100644<br>
--- a/src/compiler/nir/nir_<wbr>opcodes.py<br>
+++ b/src/compiler/nir/nir_<wbr>opcodes.py<br>
@@ -168,26 +168,28 @@ unop("flog2", tfloat, "log2f(src0)")<br>
<br>
# Generate all of the numeric conversion opcodes<br>
for src_t in [tint, tuint, tfloat]:<br>
- if src_t in (tint, tuint):<br>
- dst_types = [tfloat, src_t]<br>
- elif src_t == tfloat:<br>
- dst_types = [tint, tuint, tfloat]<br>
-<br>
- for dst_t in dst_types:<br>
+ for dst_t in [tint, tuint, tfloat]:<br>
if dst_t == tfloat:<br>
bit_sizes = [16, 32, 64]<br>
+ sat_modes = ['']<br>
else:<br>
bit_sizes = [8, 16, 32, 64]<br>
+ if src_t != tfloat and dst_t != src_t:<br>
+ sat_modes = ['_sat']<br>
+ else:<br>
+ sat_modes = ['_sat', '']<br>
for bit_size in bit_sizes:<br>
- if dst_t == tfloat and src_t == tfloat:<br>
- rnd_modes = ['_rtne', '_rtz', '']<br>
- for rnd_mode in rnd_modes:<br>
+ for sat_mode in sat_modes:<br>
+ if src_t == tfloat or dst_t == tfloat:<br>
+ for rnd_mode in ['_rtne', '_rtz', '_ru', '_rd', '']:<br>
+ unop_convert("{0}2{1}{2}{3}{4}<wbr>".format(src_t[0], dst_t[0],<br>
+ bit_size, rnd_mode,<br>
+ sat_mode),<br>
+ dst_t + str(bit_size), src_t, "src0")<br>
+ else:<br>
unop_convert("{0}2{1}{2}{3}".<wbr>format(src_t[0], dst_t[0],<br>
- bit_size, rnd_mode),<br>
+ bit_size, sat_mode),<br>
dst_t + str(bit_size), src_t, "src0")<br>
- else:<br>
- unop_convert("{0}2{1}{2}".<wbr>format(src_t[0], dst_t[0], bit_size),<br>
- dst_t + str(bit_size), src_t, "src0")<br></blockquote><div><br></div><div>As I mentioned on IRC, we need proper constant folding. Getting rounding modes on f32->f16 wrong isn't good and I probably shouldn't have let it through. Let's not make the problem worse. Not correctly handling _sat is especially bad.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
# We'll hand-code the to/from bool conversion opcodes. Because bool doesn't<br>
# have multiple bit-sizes, we can always infer the size from the other type.<br>
diff --git a/src/compiler/nir/nir_<wbr>opcodes_c.py b/src/compiler/nir/nir_<wbr>opcodes_c.py<br>
index 19079f86e7b..9b8642f0cc1 100644<br>
--- a/src/compiler/nir/nir_<wbr>opcodes_c.py<br>
+++ b/src/compiler/nir/nir_<wbr>opcodes_c.py<br>
@@ -30,7 +30,8 @@ template = Template("""<br>
#include "nir.h"<br>
<br>
nir_op<br>
-nir_type_conversion_op(nir_<wbr>alu_type src, nir_alu_type dst, nir_rounding_mode rnd)<br>
+nir_type_conversion_op(nir_<wbr>alu_type src, nir_alu_type dst, nir_rounding_mode rnd,<br>
+ bool saturate)<br>
{<br>
nir_alu_type src_base = (nir_alu_type) nir_alu_type_get_base_type(<wbr>src);<br>
nir_alu_type dst_base = (nir_alu_type) nir_alu_type_get_base_type(<wbr>dst);<br>
@@ -41,7 +42,8 @@ nir_type_conversion_op(nir_<wbr>alu_type src, nir_alu_type dst, nir_rounding_mode rnd<br>
return nir_op_fmov;<br>
} else if ((src_base == nir_type_int || src_base == nir_type_uint) &&<br>
(dst_base == nir_type_int || dst_base == nir_type_uint) &&<br>
- src_bit_size == dst_bit_size) {<br>
+ src_bit_size == dst_bit_size &&<br>
+ (src_base == dst_base || !saturate)) {<br>
/* Integer <-> integer conversions with the same bit-size on both<br>
* ends are just no-op moves.<br>
*/<br>
@@ -54,12 +56,9 @@ nir_type_conversion_op(nir_<wbr>alu_type src, nir_alu_type dst, nir_rounding_mode rnd<br>
switch (dst_base) {<br>
% for dst_t in ['int', 'uint', 'float']:<br>
case nir_type_${dst_t}:<br>
+<% orig_dst_t = dst_t %><br>
% if src_t in ['int', 'uint'] and dst_t in ['int', 'uint']:<br>
-% if dst_t == 'int':<br>
-<% continue %><br>
-% else:<br>
-<% dst_t = src_t %><br>
-% endif<br>
+<% dst_t = src_t %><br>
% endif<br>
switch (dst_bit_size) {<br>
% if dst_t == 'float':<br>
@@ -69,18 +68,25 @@ nir_type_conversion_op(nir_<wbr>alu_type src, nir_alu_type dst, nir_rounding_mode rnd<br>
% endif<br>
% for dst_bits in bit_sizes:<br>
case ${dst_bits}:<br>
-% if src_t == 'float' and dst_t == 'float':<br>
+% if src_t == 'float' or dst_t == 'float':<br>
switch(rnd) {<br>
-% for rnd_t in [('rtne', '_rtne'), ('rtz', '_rtz'), ('undef', '')]:<br>
+% for rnd_t in [('rtne', '_rtne'), ('rtz', '_rtz'), ('ru', '_ru'), ('rd', '_rd'), ('undef', '')]:<br>
case nir_rounding_mode_${rnd_t[0]}:<br>
+% if dst_t != 'float':<br>
+ if (saturate)<br>
+ return ${'nir_op_{0}2{1}{2}{3}_sat'.<wbr>format(src_t[0], dst_t[0],<br>
+ dst_bits, rnd_t[1])};<br>
+% endif<br>
return ${'nir_op_{0}2{1}{2}{3}'.<wbr>format(src_t[0], dst_t[0],<br>
dst_bits, rnd_t[1])};<br>
% endfor<br>
default:<br>
- unreachable("Invalid 16-bit nir rounding mode");<br>
+ unreachable("Invalid float nir rounding mode");<br>
}<br>
% else:<br>
assert(rnd == nir_rounding_mode_undef);<br>
+ if (saturate)<br>
+ return ${'nir_op_{0}2{1}{2}_sat'.<wbr>format(src_t[0], orig_dst_t[0], dst_bits)};<br>
return ${'nir_op_{0}2{1}{2}'.format(<wbr>src_t[0], dst_t[0], dst_bits)};<br>
% endif<br>
% endfor<br>
diff --git a/src/compiler/spirv/spirv_to_<wbr>nir.c b/src/compiler/spirv/spirv_to_<wbr>nir.c<br>
index 2a835f047e4..6f1a1871b38 100644<br>
--- a/src/compiler/spirv/spirv_to_<wbr>nir.c<br>
+++ b/src/compiler/spirv/spirv_to_<wbr>nir.c<br>
@@ -1726,7 +1726,7 @@ vtn_handle_constant(struct vtn_builder *b, SpvOp opcode,<br>
bit_size = glsl_get_bit_size(val->type-><wbr>type);<br>
};<br>
<br>
- nir_op op = vtn_nir_alu_op_for_spirv_<wbr>opcode(b, opcode, &swap,<br>
+ nir_op op = vtn_nir_alu_op_for_spirv_<wbr>opcode(b, val, opcode, &swap,<br>
nir_alu_type_get_type_size(<wbr>src_alu_type),<br>
nir_alu_type_get_type_size(<wbr>dst_alu_type));<br>
nir_const_value src[4];<br>
@@ -3839,6 +3839,8 @@ vtn_handle_body_instruction(<wbr>struct vtn_builder *b, SpvOp opcode,<br>
case SpvOpUConvert:<br>
case SpvOpSConvert:<br>
case SpvOpFConvert:<br>
+ case SpvOpSatConvertUToS:<br>
+ case SpvOpSatConvertSToU:<br>
case SpvOpQuantizeToF16:<br>
case SpvOpConvertPtrToU:<br>
case SpvOpConvertUToPtr:<br>
diff --git a/src/compiler/spirv/vtn_alu.c b/src/compiler/spirv/vtn_alu.c<br>
index 3134849ba90..b96f7d688fb 100644<br>
--- a/src/compiler/spirv/vtn_alu.c<br>
+++ b/src/compiler/spirv/vtn_alu.c<br>
@@ -273,8 +273,46 @@ vtn_handle_bitcast(struct vtn_builder *b, struct vtn_ssa_value *dest,<br>
dest->def = nir_vec(&b->nb, dest_chan, dest_components);<br>
}<br>
<br>
+static void<br>
+handle_rounding_mode(struct vtn_builder *b, struct vtn_value *val, int member,<br>
+ const struct vtn_decoration *dec, void *_out_rounding_mode)<br>
+{<br>
+ nir_rounding_mode *out_rounding_mode = _out_rounding_mode;<br>
+ assert(dec->scope == VTN_DEC_DECORATION);<br>
+ if (dec->decoration != SpvDecorationFPRoundingMode)<br>
+ return;<br>
+ switch (dec->literals[0]) {<br>
+ case SpvFPRoundingModeRTE:<br>
+ *out_rounding_mode = nir_rounding_mode_rtne;<br>
+ break;<br>
+ case SpvFPRoundingModeRTZ:<br>
+ *out_rounding_mode = nir_rounding_mode_rtz;<br>
+ break;<br>
+ case SpvFPRoundingModeRTP:<br>
+ *out_rounding_mode = nir_rounding_mode_ru;<br>
+ break;<br>
+ case SpvFPRoundingModeRTN:<br>
+ *out_rounding_mode = nir_rounding_mode_rd;<br>
+ break;<br>
+ default:<br>
+ unreachable("Not supported rounding mode");<br>
+ break;<br>
+ }<br>
+}<br>
+<br>
+static void<br>
+handle_saturation(struct vtn_builder *b, struct vtn_value *val, int member,<br>
+ const struct vtn_decoration *dec, void *_out_saturation)<br>
+{<br>
+ bool *out_saturation = _out_saturation;<br>
+ assert(dec->scope == VTN_DEC_DECORATION);<br>
+ if (dec->decoration != SpvDecorationSaturatedConversi<wbr>on)<br>
+ return;<br>
+ *out_saturation = true;<br>
+}<br>
+<br>
nir_op<br>
-vtn_nir_alu_op_for_spirv_<wbr>opcode(struct vtn_builder *b,<br>
+vtn_nir_alu_op_for_spirv_<wbr>opcode(struct vtn_builder *b, struct vtn_value *val,<br>
SpvOp opcode, bool *swap,<br>
unsigned src_bit_size, unsigned dst_bit_size)<br>
{<br>
@@ -356,42 +394,67 @@ vtn_nir_alu_op_for_spirv_<wbr>opcode(struct vtn_builder *b,<br>
case SpvOpConvertSToF:<br>
case SpvOpConvertUToF:<br>
case SpvOpSConvert:<br>
- case SpvOpFConvert: {<br>
+ case SpvOpFConvert:<br>
+ case SpvOpSatConvertUToS:<br>
+ case SpvOpSatConvertSToU: {<br>
nir_alu_type src_type;<br>
nir_alu_type dst_type;<br>
<br>
+ nir_rounding_mode rounding_mode = nir_rounding_mode_undef;<br>
+ bool saturation = false;<br>
+<br>
switch (opcode) {<br>
case SpvOpConvertFToS:<br>
src_type = nir_type_float;<br>
dst_type = nir_type_int;<br>
+ vtn_foreach_decoration(b, val, handle_rounding_mode, &rounding_mode);<br>
+ vtn_foreach_decoration(b, val, handle_saturation, &saturation);<br>
break;<br>
case SpvOpConvertFToU:<br>
src_type = nir_type_float;<br>
dst_type = nir_type_uint;<br>
+ vtn_foreach_decoration(b, val, handle_rounding_mode, &rounding_mode);<br>
+ vtn_foreach_decoration(b, val, handle_saturation, &saturation);<br>
break;<br>
case SpvOpFConvert:<br>
src_type = dst_type = nir_type_float;<br>
+ vtn_foreach_decoration(b, val, handle_rounding_mode, &rounding_mode);<br>
break;<br>
case SpvOpConvertSToF:<br>
src_type = nir_type_int;<br>
dst_type = nir_type_float;<br>
+ vtn_foreach_decoration(b, val, handle_rounding_mode, &rounding_mode);<br>
break;<br>
case SpvOpSConvert:<br>
src_type = dst_type = nir_type_int;<br>
+ vtn_foreach_decoration(b, val, handle_saturation, &saturation);<br>
break;<br>
case SpvOpConvertUToF:<br>
src_type = nir_type_uint;<br>
dst_type = nir_type_float;<br>
+ vtn_foreach_decoration(b, val, handle_rounding_mode, &rounding_mode);<br>
break;<br>
case SpvOpUConvert:<br>
src_type = dst_type = nir_type_uint;<br>
+ vtn_foreach_decoration(b, val, handle_saturation, &saturation);<br>
+ break;<br>
+ case SpvOpSatConvertUToS:<br>
+ src_type = nir_type_uint;<br>
+ dst_type = nir_type_int;<br>
+ saturation = true;<br>
+ break;<br>
+ case SpvOpSatConvertSToU:<br>
+ src_type = nir_type_int;<br>
+ dst_type = nir_type_uint;<br>
+ saturation = true;<br>
break;<br>
default:<br>
unreachable("Invalid opcode");<br>
}<br>
src_type |= src_bit_size;<br>
dst_type |= dst_bit_size;<br>
- return nir_type_conversion_op(src_<wbr>type, dst_type, nir_rounding_mode_undef);<br>
+<br>
+ return nir_type_conversion_op(src_<wbr>type, dst_type, rounding_mode, saturation);<br>
}<br>
/* Derivatives: */<br>
case SpvOpDPdx: return nir_op_fddx;<br>
@@ -417,27 +480,6 @@ handle_no_contraction(struct vtn_builder *b, struct vtn_value *val, int member,<br>
b->nb.exact = true;<br>
}<br>
<br>
-static void<br>
-handle_rounding_mode(struct vtn_builder *b, struct vtn_value *val, int member,<br>
- const struct vtn_decoration *dec, void *_out_rounding_mode)<br>
-{<br>
- nir_rounding_mode *out_rounding_mode = _out_rounding_mode;<br>
- assert(dec->scope == VTN_DEC_DECORATION);<br>
- if (dec->decoration != SpvDecorationFPRoundingMode)<br>
- return;<br>
- switch (dec->literals[0]) {<br>
- case SpvFPRoundingModeRTE:<br>
- *out_rounding_mode = nir_rounding_mode_rtne;<br>
- break;<br>
- case SpvFPRoundingModeRTZ:<br>
- *out_rounding_mode = nir_rounding_mode_rtz;<br>
- break;<br>
- default:<br>
- unreachable("Not supported rounding mode");<br>
- break;<br>
- }<br>
-}<br>
-<br>
void<br>
vtn_handle_alu(struct vtn_builder *b, SpvOp opcode,<br>
const uint32_t *w, unsigned count)<br>
@@ -579,7 +621,7 @@ vtn_handle_alu(struct vtn_builder *b, SpvOp opcode,<br>
bool swap;<br>
unsigned src_bit_size = glsl_get_bit_size(vtn_src[0]-><wbr>type);<br>
unsigned dst_bit_size = glsl_get_bit_size(type);<br>
- nir_op op = vtn_nir_alu_op_for_spirv_<wbr>opcode(b, opcode, &swap,<br>
+ nir_op op = vtn_nir_alu_op_for_spirv_<wbr>opcode(b, val, opcode, &swap,<br>
src_bit_size, dst_bit_size);<br>
<br>
if (swap) {<br>
@@ -605,7 +647,7 @@ vtn_handle_alu(struct vtn_builder *b, SpvOp opcode,<br>
bool swap;<br>
unsigned src_bit_size = glsl_get_bit_size(vtn_src[0]-><wbr>type);<br>
unsigned dst_bit_size = glsl_get_bit_size(type);<br>
- nir_op op = vtn_nir_alu_op_for_spirv_<wbr>opcode(b, opcode, &swap,<br>
+ nir_op op = vtn_nir_alu_op_for_spirv_<wbr>opcode(b, val, opcode, &swap,<br>
src_bit_size, dst_bit_size);<br>
<br>
assert(!swap);<br>
@@ -623,23 +665,11 @@ vtn_handle_alu(struct vtn_builder *b, SpvOp opcode,<br>
vtn_handle_bitcast(b, val->ssa, src[0]);<br>
break;<br>
<br>
- case SpvOpFConvert: {<br>
- nir_alu_type src_alu_type = nir_get_nir_type_for_glsl_<wbr>type(vtn_src[0]->type);<br>
- nir_alu_type dst_alu_type = nir_get_nir_type_for_glsl_<wbr>type(type);<br>
- nir_rounding_mode rounding_mode = nir_rounding_mode_undef;<br>
-<br>
- vtn_foreach_decoration(b, val, handle_rounding_mode, &rounding_mode);<br>
- nir_op op = nir_type_conversion_op(src_<wbr>alu_type, dst_alu_type, rounding_mode);<br>
-<br>
- val->ssa->def = nir_build_alu(&b->nb, op, src[0], src[1], NULL, NULL);<br>
- break;<br>
- }<br>
-<br>
default: {<br>
bool swap;<br>
unsigned src_bit_size = glsl_get_bit_size(vtn_src[0]-><wbr>type);<br>
unsigned dst_bit_size = glsl_get_bit_size(type);<br>
- nir_op op = vtn_nir_alu_op_for_spirv_<wbr>opcode(b, opcode, &swap,<br>
+ nir_op op = vtn_nir_alu_op_for_spirv_<wbr>opcode(b, val, opcode, &swap,<br>
src_bit_size, dst_bit_size);<br>
<br>
if (swap) {<br>
diff --git a/src/compiler/spirv/vtn_<wbr>glsl450.c b/src/compiler/spirv/vtn_<wbr>glsl450.c<br>
index 6fa759b1bba..284371446b5 100644<br>
--- a/src/compiler/spirv/vtn_<wbr>glsl450.c<br>
+++ b/src/compiler/spirv/vtn_<wbr>glsl450.c<br>
@@ -659,7 +659,7 @@ handle_glsl450_alu(struct vtn_builder *b, enum GLSLstd450 entrypoint,<br>
nir_op conversion_op =<br>
nir_type_conversion_op(nir_<wbr>type_float | eta->bit_size,<br>
nir_type_float | I->bit_size,<br>
- nir_rounding_mode_undef);<br>
+ nir_rounding_mode_undef, false);<br>
eta = nir_build_alu(nb, conversion_op, eta, NULL, NULL, NULL);<br>
}<br>
/* k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I)) */<br>
diff --git a/src/compiler/spirv/vtn_<wbr>private.h b/src/compiler/spirv/vtn_<wbr>private.h<br>
index b501bbf9b4a..0895c865fbb 100644<br>
--- a/src/compiler/spirv/vtn_<wbr>private.h<br>
+++ b/src/compiler/spirv/vtn_<wbr>private.h<br>
@@ -708,7 +708,7 @@ typedef void (*vtn_execution_mode_foreach_<wbr>cb)(struct vtn_builder *,<br>
void vtn_foreach_execution_mode(<wbr>struct vtn_builder *b, struct vtn_value *value,<br>
vtn_execution_mode_foreach_cb cb, void *data);<br>
<br>
-nir_op vtn_nir_alu_op_for_spirv_<wbr>opcode(struct vtn_builder *b,<br>
+nir_op vtn_nir_alu_op_for_spirv_<wbr>opcode(struct vtn_builder *b, struct vtn_value *val,<br>
SpvOp opcode, bool *swap,<br>
unsigned src_bit_size, unsigned dst_bit_size);<br>
<span class="HOEnZb"><font color="#888888"> <br>
-- <br>
2.14.3<br>
<br>
______________________________<wbr>_________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
<a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev" rel="noreferrer" target="_blank">https://lists.freedesktop.org/<wbr>mailman/listinfo/mesa-dev</a><br>
</font></span></blockquote></div><br></div></div>