<p dir="ltr"><br>
On Oct 10, 2015 12:09 PM, "Matt Turner" <<a href="mailto:mattst88@gmail.com">mattst88@gmail.com</a>> wrote:<br>
><br>
> On Sat, Oct 10, 2015 at 11:47 AM, Rob Clark <<a href="mailto:robdclark@gmail.com">robdclark@gmail.com</a>> wrote:<br>
> > From: Rob Clark <<a href="mailto:robclark@freedesktop.org">robclark@freedesktop.org</a>><br>
> ><br>
> > Needed in NIR too, so move out of mesa/main/imports.c<br>
> ><br>
> > Signed-off-by: Rob Clark <<a href="mailto:robclark@freedesktop.org">robclark@freedesktop.org</a>><br>
> > ---<br>
> > src/glsl/Makefile.am | 1 +<br>
> > src/mesa/main/imports.c | 148 --------------------------------------<br>
> > src/mesa/main/imports.h | 38 ++++++++--<br>
> > src/util/Makefile.sources | 2 +<br>
> > src/util/convert.c | 179 ++++++++++++++++++++++++++++++++++++++++++++++<br>
> > src/util/convert.h | 43 +++++++++++<br>
> > 6 files changed, 259 insertions(+), 152 deletions(-)<br>
> > create mode 100644 src/util/convert.c<br>
> > create mode 100644 src/util/convert.h<br>
> ><br>
> > diff --git a/src/glsl/Makefile.am b/src/glsl/Makefile.am<br>
> > index 3265391..347919b 100644<br>
> > --- a/src/glsl/Makefile.am<br>
> > +++ b/src/glsl/Makefile.am<br>
> > @@ -160,6 +160,7 @@ glsl_compiler_SOURCES = \<br>
> > glsl_compiler_LDADD = \<br>
> > <a href="http://libglsl.la">libglsl.la</a> \<br>
> > $(top_builddir)/src/<a href="http://libglsl_util.la">libglsl_util.la</a> \<br>
> > + $(top_builddir)/src/util/<a href="http://libmesautil.la">libmesautil.la</a> \<br>
> > $(PTHREAD_LIBS)<br>
> ><br>
> > glsl_test_SOURCES = \<br>
> > diff --git a/src/mesa/main/imports.c b/src/mesa/main/imports.c<br>
> > index 350e675..230ebbc 100644<br>
> > --- a/src/mesa/main/imports.c<br>
> > +++ b/src/mesa/main/imports.c<br>
> > @@ -307,154 +307,6 @@ _mesa_bitcount_64(uint64_t n)<br>
> > }<br>
> > #endif<br>
> ><br>
> > -<br>
> > -/**<br>
> > - * Convert a 4-byte float to a 2-byte half float.<br>
> > - *<br>
> > - * Not all float32 values can be represented exactly as a float16 value. We<br>
> > - * round such intermediate float32 values to the nearest float16. When the<br>
> > - * float32 lies exactly between to float16 values, we round to the one with<br>
> > - * an even mantissa.<br>
> > - *<br>
> > - * This rounding behavior has several benefits:<br>
> > - * - It has no sign bias.<br>
> > - *<br>
> > - * - It reproduces the behavior of real hardware: opcode F32TO16 in Intel's<br>
> > - * GPU ISA.<br>
> > - *<br>
> > - * - By reproducing the behavior of the GPU (at least on Intel hardware),<br>
> > - * compile-time evaluation of constant packHalf2x16 GLSL expressions will<br>
> > - * result in the same value as if the expression were executed on the GPU.<br>
> > - */<br>
> > -GLhalfARB<br>
> > -_mesa_float_to_half(float val)<br>
> > -{<br>
> > - const fi_type fi = {val};<br>
> > - const int flt_m = fi.i & 0x7fffff;<br>
> > - const int flt_e = (fi.i >> 23) & 0xff;<br>
> > - const int flt_s = (fi.i >> 31) & 0x1;<br>
> > - int s, e, m = 0;<br>
> > - GLhalfARB result;<br>
> > -<br>
> > - /* sign bit */<br>
> > - s = flt_s;<br>
> > -<br>
> > - /* handle special cases */<br>
> > - if ((flt_e == 0) && (flt_m == 0)) {<br>
> > - /* zero */<br>
> > - /* m = 0; - already set */<br>
> > - e = 0;<br>
> > - }<br>
> > - else if ((flt_e == 0) && (flt_m != 0)) {<br>
> > - /* denorm -- denorm float maps to 0 half */<br>
> > - /* m = 0; - already set */<br>
> > - e = 0;<br>
> > - }<br>
> > - else if ((flt_e == 0xff) && (flt_m == 0)) {<br>
> > - /* infinity */<br>
> > - /* m = 0; - already set */<br>
> > - e = 31;<br>
> > - }<br>
> > - else if ((flt_e == 0xff) && (flt_m != 0)) {<br>
> > - /* NaN */<br>
> > - m = 1;<br>
> > - e = 31;<br>
> > - }<br>
> > - else {<br>
> > - /* regular number */<br>
> > - const int new_exp = flt_e - 127;<br>
> > - if (new_exp < -14) {<br>
> > - /* The float32 lies in the range (0.0, min_normal16) and is rounded<br>
> > - * to a nearby float16 value. The result will be either zero, subnormal,<br>
> > - * or normal.<br>
> > - */<br>
> > - e = 0;<br>
> > - m = _mesa_lroundevenf((1 << 24) * fabsf(fi.f));<br>
> > - }<br>
> > - else if (new_exp > 15) {<br>
> > - /* map this value to infinity */<br>
> > - /* m = 0; - already set */<br>
> > - e = 31;<br>
> > - }<br>
> > - else {<br>
> > - /* The float32 lies in the range<br>
> > - * [min_normal16, max_normal16 + max_step16)<br>
> > - * and is rounded to a nearby float16 value. The result will be<br>
> > - * either normal or infinite.<br>
> > - */<br>
> > - e = new_exp + 15;<br>
> > - m = _mesa_lroundevenf(flt_m / (float) (1 << 13));<br>
> > - }<br>
> > - }<br>
> > -<br>
> > - assert(0 <= m && m <= 1024);<br>
> > - if (m == 1024) {<br>
> > - /* The float32 was rounded upwards into the range of the next exponent,<br>
> > - * so bump the exponent. This correctly handles the case where f32<br>
> > - * should be rounded up to float16 infinity.<br>
> > - */<br>
> > - ++e;<br>
> > - m = 0;<br>
> > - }<br>
> > -<br>
> > - result = (s << 15) | (e << 10) | m;<br>
> > - return result;<br>
> > -}<br>
> > -<br>
> > -<br>
> > -/**<br>
> > - * Convert a 2-byte half float to a 4-byte float.<br>
> > - * Based on code from:<br>
> > - * <a href="http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/008786.html">http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/008786.html</a><br>
> > - */<br>
> > -float<br>
> > -_mesa_half_to_float(GLhalfARB val)<br>
> > -{<br>
> > - /* XXX could also use a 64K-entry lookup table */<br>
> > - const int m = val & 0x3ff;<br>
> > - const int e = (val >> 10) & 0x1f;<br>
> > - const int s = (val >> 15) & 0x1;<br>
> > - int flt_m, flt_e, flt_s;<br>
> > - fi_type fi;<br>
> > - float result;<br>
> > -<br>
> > - /* sign bit */<br>
> > - flt_s = s;<br>
> > -<br>
> > - /* handle special cases */<br>
> > - if ((e == 0) && (m == 0)) {<br>
> > - /* zero */<br>
> > - flt_m = 0;<br>
> > - flt_e = 0;<br>
> > - }<br>
> > - else if ((e == 0) && (m != 0)) {<br>
> > - /* denorm -- denorm half will fit in non-denorm single */<br>
> > - const float half_denorm = 1.0f / 16384.0f; /* 2^-14 */<br>
> > - float mantissa = ((float) (m)) / 1024.0f;<br>
> > - float sign = s ? -1.0f : 1.0f;<br>
> > - return sign * mantissa * half_denorm;<br>
> > - }<br>
> > - else if ((e == 31) && (m == 0)) {<br>
> > - /* infinity */<br>
> > - flt_e = 0xff;<br>
> > - flt_m = 0;<br>
> > - }<br>
> > - else if ((e == 31) && (m != 0)) {<br>
> > - /* NaN */<br>
> > - flt_e = 0xff;<br>
> > - flt_m = 1;<br>
> > - }<br>
> > - else {<br>
> > - /* regular */<br>
> > - flt_e = e + 112;<br>
> > - flt_m = m << 13;<br>
> > - }<br>
> > -<br>
> > - fi.i = (flt_s << 31) | (flt_e << 23) | flt_m;<br>
> > - result = fi.f;<br>
> > - return result;<br>
> > -}<br>
> > -<br>
> > /*@}*/<br>
> ><br>
> ><br>
> > diff --git a/src/mesa/main/imports.h b/src/mesa/main/imports.h<br>
> > index 9024758..3a09304 100644<br>
> > --- a/src/mesa/main/imports.h<br>
> > +++ b/src/mesa/main/imports.h<br>
> > @@ -42,6 +42,7 @@<br>
> > #include "compiler.h"<br>
> > #include "glheader.h"<br>
> > #include "errors.h"<br>
> > +#include "util/convert.h"<br>
> ><br>
> > #ifdef __cplusplus<br>
> > extern "C" {<br>
> > @@ -396,12 +397,41 @@ _mesa_flsll(uint64_t n)<br>
> > #endif<br>
> > }<br>
> ><br>
> > +/**<br>
> > + * Convert a 4-byte float to a 2-byte half float.<br>
> > + *<br>
> > + * Not all float32 values can be represented exactly as a float16 value. We<br>
> > + * round such intermediate float32 values to the nearest float16. When the<br>
> > + * float32 lies exactly between to float16 values, we round to the one with<br>
> > + * an even mantissa.<br>
> > + *<br>
> > + * This rounding behavior has several benefits:<br>
> > + * - It has no sign bias.<br>
> > + *<br>
> > + * - It reproduces the behavior of real hardware: opcode F32TO16 in Intel's<br>
> > + * GPU ISA.<br>
> > + *<br>
> > + * - By reproducing the behavior of the GPU (at least on Intel hardware),<br>
> > + * compile-time evaluation of constant packHalf2x16 GLSL expressions will<br>
> > + * result in the same value as if the expression were executed on the GPU.<br>
> > + */<br>
> > +static inline GLhalfARB<br>
> > +_mesa_float_to_half(float val)<br>
> > +{<br>
> > + return float_to_half(val);<br>
> > +}<br>
> ><br>
> > -extern GLhalfARB<br>
> > -_mesa_float_to_half(float f);<br>
> ><br>
> > -extern float<br>
> > -_mesa_half_to_float(GLhalfARB h);<br>
> > +/**<br>
> > + * Convert a 2-byte half float to a 4-byte float.<br>
> > + * Based on code from:<br>
> > + * <a href="http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/008786.html">http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/008786.html</a><br>
> > + */<br>
> > +static inline float<br>
> > +_mesa_half_to_float(GLhalfARB val)<br>
> > +{<br>
> > + return half_to_float(val);<br>
> > +}</p>
<p dir="ltr">This is kind of ugly. How hard would it really be to just replace the uses with the new name? I don't think its used *that* often.</p>
<p dir="ltr">> > static inline bool<br>
> > _mesa_half_is_negative(GLhalfARB h)<br>
> > diff --git a/src/util/Makefile.sources b/src/util/Makefile.sources<br>
> > index e45431d..71b2a25 100644<br>
> > --- a/src/util/Makefile.sources<br>
> > +++ b/src/util/Makefile.sources<br>
> > @@ -1,5 +1,7 @@<br>
> > MESA_UTIL_FILES := \<br>
> > bitset.h \<br>
> > + convert.c \<br>
> > + convert.h \<br>
> > debug.c \<br>
> > debug.h \<br>
> > format_srgb.h \<br>
> > diff --git a/src/util/convert.c b/src/util/convert.c<br>
> > new file mode 100644<br>
> > index 0000000..e86e322<br>
> > --- /dev/null<br>
> > +++ b/src/util/convert.c<br>
><br>
> half-float.c seems like a better name.</p>
<p dir="ltr">Agreed.</p>
<p dir="ltr">> > @@ -0,0 +1,179 @@<br>
> > +/*<br>
> > + * Copyright © 2015 Red Hat<br>
><br>
> What the?<br>
><br>
> No. This code was written by Brian (commit 7eb3e9b) and Chad (commit<br>
> 529b6d1). Its copyright belongs to VMware and Intel (and probably<br>
> "gking" from [1])<br>
><br>
> [1] <a href="https://web.archive.org/web/20030303115125/http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/008786.html">https://web.archive.org/web/20030303115125/http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/008786.html</a><br>
><br>
> > + *<br>
> > + * Permission is hereby granted, free of charge, to any person obtaining a<br>
> > + * copy of this software and associated documentation files (the "Software"),<br>
> > + * to deal in the Software without restriction, including without limitation<br>
> > + * the rights to use, copy, modify, merge, publish, distribute, sublicense,<br>
> > + * and/or sell copies of the Software, and to permit persons to whom the<br>
> > + * Software is furnished to do so, subject to the following conditions:<br>
> > + *<br>
> > + * The above copyright notice and this permission notice (including the next<br>
> > + * paragraph) shall be included in all copies or substantial portions of the<br>
> > + * Software.<br>
> > + *<br>
> > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR<br>
> > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,<br>
> > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL<br>
> > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER<br>
> > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING<br>
> > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS<br>
> > + * IN THE SOFTWARE.<br>
> > + *<br>
> > + * Authors:<br>
> > + * Rob Clark <<a href="mailto:robclark@freedesktop.org">robclark@freedesktop.org</a>><br>
><br>
> We're trying to stop with author lists generally, but listing yourself<br>
> as an author on some code you copied from somewhere else is not okay.<br>
><br>
> > + */<br>
> > +<br>
> > +#include <math.h><br>
> > +#include <assert.h><br>
> > +#include "convert.h"<br>
> > +#include "rounding.h"<br>
> > +<br>
> > +typedef union { float f; int32_t i; uint32_t u; } fi_type;<br>
> > +<br>
> > +/**<br>
> > + * Convert a 4-byte float to a 2-byte half float.<br>
> > + *<br>
> > + * Not all float32 values can be represented exactly as a float16 value. We<br>
> > + * round such intermediate float32 values to the nearest float16. When the<br>
> > + * float32 lies exactly between to float16 values, we round to the one with<br>
> > + * an even mantissa.<br>
> > + *<br>
> > + * This rounding behavior has several benefits:<br>
> > + * - It has no sign bias.<br>
> > + *<br>
> > + * - It reproduces the behavior of real hardware: opcode F32TO16 in Intel's<br>
> > + * GPU ISA.<br>
> > + *<br>
> > + * - By reproducing the behavior of the GPU (at least on Intel hardware),<br>
> > + * compile-time evaluation of constant packHalf2x16 GLSL expressions will<br>
> > + * result in the same value as if the expression were executed on the GPU.<br>
> > + */<br>
> > +uint16_t<br>
> > +float_to_half(float val)<br>
> > +{<br>
> > + const fi_type fi = {val};<br>
> > + const int flt_m = fi.i & 0x7fffff;<br>
> > + const int flt_e = (fi.i >> 23) & 0xff;<br>
> > + const int flt_s = (fi.i >> 31) & 0x1;<br>
> > + int s, e, m = 0;<br>
> > + uint16_t result;<br>
> > +<br>
> > + /* sign bit */<br>
> > + s = flt_s;<br>
> > +<br>
> > + /* handle special cases */<br>
> > + if ((flt_e == 0) && (flt_m == 0)) {<br>
> > + /* zero */<br>
> > + /* m = 0; - already set */<br>
> > + e = 0;<br>
> > + }<br>
> > + else if ((flt_e == 0) && (flt_m != 0)) {<br>
> > + /* denorm -- denorm float maps to 0 half */<br>
> > + /* m = 0; - already set */<br>
> > + e = 0;<br>
> > + }<br>
> > + else if ((flt_e == 0xff) && (flt_m == 0)) {<br>
> > + /* infinity */<br>
> > + /* m = 0; - already set */<br>
> > + e = 31;<br>
> > + }<br>
> > + else if ((flt_e == 0xff) && (flt_m != 0)) {<br>
> > + /* NaN */<br>
> > + m = 1;<br>
> > + e = 31;<br>
> > + }<br>
> > + else {<br>
> > + /* regular number */<br>
> > + const int new_exp = flt_e - 127;<br>
> > + if (new_exp < -14) {<br>
> > + /* The float32 lies in the range (0.0, min_normal16) and is rounded<br>
> > + * to a nearby float16 value. The result will be either zero, subnormal,<br>
> > + * or normal.<br>
> > + */<br>
> > + e = 0;<br>
> > + m = _mesa_lroundevenf((1 << 24) * fabsf(fi.f));<br>
> > + }<br>
> > + else if (new_exp > 15) {<br>
> > + /* map this value to infinity */<br>
> > + /* m = 0; - already set */<br>
> > + e = 31;<br>
> > + }<br>
> > + else {<br>
> > + /* The float32 lies in the range<br>
> > + * [min_normal16, max_normal16 + max_step16)<br>
> > + * and is rounded to a nearby float16 value. The result will be<br>
> > + * either normal or infinite.<br>
> > + */<br>
> > + e = new_exp + 15;<br>
> > + m = _mesa_lroundevenf(flt_m / (float) (1 << 13));<br>
> > + }<br>
> > + }<br>
> > +<br>
> > + assert(0 <= m && m <= 1024);<br>
> > + if (m == 1024) {<br>
> > + /* The float32 was rounded upwards into the range of the next exponent,<br>
> > + * so bump the exponent. This correctly handles the case where f32<br>
> > + * should be rounded up to float16 infinity.<br>
> > + */<br>
> > + ++e;<br>
> > + m = 0;<br>
> > + }<br>
> > +<br>
> > + result = (s << 15) | (e << 10) | m;<br>
> > + return result;<br>
> > +}<br>
> > +<br>
> > +<br>
> > +/**<br>
> > + * Convert a 2-byte half float to a 4-byte float.<br>
> > + * Based on code from:<br>
> > + * <a href="http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/008786.html">http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/008786.html</a><br>
> > + */<br>
> > +float<br>
> > +half_to_float(uint16_t val)<br>
> > +{<br>
> > + /* XXX could also use a 64K-entry lookup table */<br>
> > + const int m = val & 0x3ff;<br>
> > + const int e = (val >> 10) & 0x1f;<br>
> > + const int s = (val >> 15) & 0x1;<br>
> > + int flt_m, flt_e, flt_s;<br>
> > + fi_type fi;<br>
> > + float result;<br>
> > +<br>
> > + /* sign bit */<br>
> > + flt_s = s;<br>
> > +<br>
> > + /* handle special cases */<br>
> > + if ((e == 0) && (m == 0)) {<br>
> > + /* zero */<br>
> > + flt_m = 0;<br>
> > + flt_e = 0;<br>
> > + }<br>
> > + else if ((e == 0) && (m != 0)) {<br>
> > + /* denorm -- denorm half will fit in non-denorm single */<br>
> > + const float half_denorm = 1.0f / 16384.0f; /* 2^-14 */<br>
> > + float mantissa = ((float) (m)) / 1024.0f;<br>
> > + float sign = s ? -1.0f : 1.0f;<br>
> > + return sign * mantissa * half_denorm;<br>
> > + }<br>
> > + else if ((e == 31) && (m == 0)) {<br>
> > + /* infinity */<br>
> > + flt_e = 0xff;<br>
> > + flt_m = 0;<br>
> > + }<br>
> > + else if ((e == 31) && (m != 0)) {<br>
> > + /* NaN */<br>
> > + flt_e = 0xff;<br>
> > + flt_m = 1;<br>
> > + }<br>
> > + else {<br>
> > + /* regular */<br>
> > + flt_e = e + 112;<br>
> > + flt_m = m << 13;<br>
> > + }<br>
> > +<br>
> > + fi.i = (flt_s << 31) | (flt_e << 23) | flt_m;<br>
> > + result = fi.f;<br>
> > + return result;<br>
> > +}<br>
> > diff --git a/src/util/convert.h b/src/util/convert.h<br>
> > new file mode 100644<br>
> > index 0000000..30d36a1<br>
> > --- /dev/null<br>
> > +++ b/src/util/convert.h<br>
> > @@ -0,0 +1,43 @@<br>
> > +/*<br>
> > + * Copyright © 2015 Red Hat<br>
><br>
> Seems fishy.<br>
><br>
> > + *<br>
> > + * Permission is hereby granted, free of charge, to any person obtaining a<br>
> > + * copy of this software and associated documentation files (the "Software"),<br>
> > + * to deal in the Software without restriction, including without limitation<br>
> > + * the rights to use, copy, modify, merge, publish, distribute, sublicense,<br>
> > + * and/or sell copies of the Software, and to permit persons to whom the<br>
> > + * Software is furnished to do so, subject to the following conditions:<br>
> > + *<br>
> > + * The above copyright notice and this permission notice (including the next<br>
> > + * paragraph) shall be included in all copies or substantial portions of the<br>
> > + * Software.<br>
> > + *<br>
> > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR<br>
> > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,<br>
> > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL<br>
> > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER<br>
> > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING<br>
> > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS<br>
> > + * IN THE SOFTWARE.<br>
> > + *<br>
> > + * Authors:<br>
> > + * Rob Clark <<a href="mailto:robclark@freedesktop.org">robclark@freedesktop.org</a>><br>
><br>
> Again, no author list.<br>
><br>
> > + */<br>
> > +<br>
> > +#ifndef _MATH_H_<br>
> > +#define _MATH_H_<br>
><br>
> Wrong name.<br>
><br>
> > +<br>
> > +#include <stdint.h><br>
> > +<br>
> > +#ifdef __cplusplus<br>
> > +extern "C" {<br>
> > +#endif<br>
> > +<br>
> > +uint16_t float_to_half(float val);<br>
> > +float half_to_float(uint16_t val);<br>
><br>
> I think these functions need to be prefixed with something -- util_*<br>
> or something or just leave them as _mesa_*.</p>
<p dir="ltr">Unfortunately, until is kind of a grab-bag right now. Some stuff has a util_ prefix, some has kept its _mesa_ or u_ prefix depending on whether it was copied from Mesa or gallium, and some (hash_table for example) isn't prefixed at all. Personally, I'd go with either util_ (it is a utility library) or just keep _mesa_ (this is still the mesa project after all). I'm not going to be too insistent though</p>
<p dir="ltr">> > +<br>
> > +#ifdef __cplusplus<br>
> > +} /* extern C */<br>
> > +#endif<br>
> > +<br>
> > +#endif /* _MATH_H_ */<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">http://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br>
</p>