Am 11.06.2015 um 17:33 schrieb Rob Clark: > On Thu, Jun 11, 2015 at 10:53 AM, Roland Scheidegger <srol...@vmware.com> > wrote: >> For 1-4/7, 6/7: >> Reviewed-by: Roland Scheidegger <srol...@vmware.com> >> >> I think though using two exclusive booleans is really ugly. Probably >> should just use a tgsi_return_type enum instead indeed, and treat the >> unorm/snorm cases as float. I'm not entirely sure what the unorm/snorm >> types are for neither, this is a d3d10-ism but I'm not sure it serves >> much purpose (since, of course, for the purposes of the shader, the >> results indeed are floats). At least for now llvmpipe actually doesn't >> use that information (as we recompile the shader anyway if the texture >> "type" changes in the actually bound sampler views we get all the >> information from there). >> >> >> (FWIW I believe there's a slight catch with the >> util_format_is_pure_uint/sint functions - because right now in gallium >> it is sort of ok to sample from things like D24S8 textures, which means >> the depth component is sampled (so same as D24X8, opposed to X24S8), and >> depending if the D or S channel is first the answer may not quite be >> right...) > > fwiw, the u_blitter (or rather u_simple_shader) is actually creating > separate samplers for depth+stencil. So I don't *think* we use > _is_pure_uint/sint() on zs formats.. Yeah that's ok then. IIRC mesa state tracker still uses zs formats for sampling - this comes from a time where sampling stencil wasn't even possible. There's some special casing in llvmpipe/gallivm just for that. I guess it would be cleaner if we'd just forbid this (the state tracker could use something like util_format_depth_only() similar to util_format_stencil_only()), rather than have to assume you want to sample the depth component if it's a ds format. But anyway that's not really related here.
> > Currently I'm always treating stencil SVIEW as uint and depth SVIEW as > float (since at least from u_format.csv this seemed to be the case..) Yes, that makes sense. Roland > > BR, > -R > >> Roland >> >> Am 11.06.2015 um 02:14 schrieb Rob Clark: >>> From: Rob Clark <robcl...@freedesktop.org> >>> >>> Some hardware needs to know the sampler type. Update the blit related >>> shaders to include SVIEW decl. >>> >>> Signed-off-by: Rob Clark <robcl...@freedesktop.org> >>> --- >>> Possibly I should have refactored the existing code to pass around a >>> return_type rather than doing the is_uint/is_sint thing everywhere. >>> And this does kind of ignore UNORM/SNORM.. although I'm not really >>> sure that we need shader variants for UNORM/SNORM (we don't have this >>> information in GLSL IR or NIR IR, and I don't know any hw that doesn't >>> just treat those as FLOAT in the shader compiler). Anyways, sending >>> it out as-is for comments. >>> >>> src/gallium/auxiliary/util/u_blit.c | 32 +++++++++---- >>> src/gallium/auxiliary/util/u_blitter.c | 42 ++++++++++++---- >>> src/gallium/auxiliary/util/u_simple_shaders.c | 69 >>> +++++++++++++++++++++++---- >>> src/gallium/auxiliary/util/u_simple_shaders.h | 15 ++++-- >>> src/gallium/auxiliary/util/u_tests.c | 3 +- >>> src/gallium/tests/trivial/quad-tex.c | 2 +- >>> 6 files changed, 132 insertions(+), 31 deletions(-) >>> >>> diff --git a/src/gallium/auxiliary/util/u_blit.c >>> b/src/gallium/auxiliary/util/u_blit.c >>> index 3f3b5fe..0062d96 100644 >>> --- a/src/gallium/auxiliary/util/u_blit.c >>> +++ b/src/gallium/auxiliary/util/u_blit.c >>> @@ -65,7 +65,7 @@ struct blit_state >>> struct pipe_vertex_element velem[2]; >>> >>> void *vs; >>> - void *fs[PIPE_MAX_TEXTURE_TYPES][TGSI_WRITEMASK_XYZW + 1]; >>> + void *fs[PIPE_MAX_TEXTURE_TYPES][TGSI_WRITEMASK_XYZW + 1][3]; >>> >>> struct pipe_resource *vbuf; /**< quad vertices */ >>> unsigned vbuf_slot; >>> @@ -135,15 +135,17 @@ void >>> util_destroy_blit(struct blit_state *ctx) >>> { >>> struct pipe_context *pipe = ctx->pipe; >>> - unsigned i, j; >>> + unsigned i, j, k; >>> >>> if (ctx->vs) >>> pipe->delete_vs_state(pipe, ctx->vs); >>> >>> for (i = 0; i < Elements(ctx->fs); i++) { >>> for (j = 0; j < Elements(ctx->fs[i]); j++) { >>> - if (ctx->fs[i][j]) >>> - pipe->delete_fs_state(pipe, ctx->fs[i][j]); >>> + for (k = 0; k < Elements(ctx->fs[i][j]); k++) { >>> + if (ctx->fs[i][j][k]) >>> + pipe->delete_fs_state(pipe, ctx->fs[i][j][k]); >>> + } >>> } >>> } >>> >>> @@ -158,18 +160,31 @@ util_destroy_blit(struct blit_state *ctx) >>> */ >>> static INLINE void >>> set_fragment_shader(struct blit_state *ctx, uint writemask, >>> + enum pipe_format format, >>> enum pipe_texture_target pipe_tex) >>> { >>> - if (!ctx->fs[pipe_tex][writemask]) { >>> + boolean is_uint = util_format_is_pure_uint(format); >>> + boolean is_sint = util_format_is_pure_sint(format); >>> + unsigned type; >>> + >>> + if (is_uint) >>> + type = 0; >>> + else if (is_sint) >>> + type = 1; >>> + else >>> + type = 2; >>> + >>> + if (!ctx->fs[pipe_tex][writemask][type]) { >>> unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex, 0); >>> >>> - ctx->fs[pipe_tex][writemask] = >>> + ctx->fs[pipe_tex][writemask][type] = >>> util_make_fragment_tex_shader_writemask(ctx->pipe, tgsi_tex, >>> TGSI_INTERPOLATE_LINEAR, >>> - writemask); >>> + writemask, >>> + is_uint, is_sint); >>> } >>> >>> - cso_set_fragment_shader_handle(ctx->cso, ctx->fs[pipe_tex][writemask]); >>> + cso_set_fragment_shader_handle(ctx->cso, >>> ctx->fs[pipe_tex][writemask][type]); >>> } >>> >>> >>> @@ -571,6 +586,7 @@ util_blit_pixels_tex(struct blit_state *ctx, >>> >>> /* shaders */ >>> set_fragment_shader(ctx, TGSI_WRITEMASK_XYZW, >>> + src_sampler_view->format, >>> src_sampler_view->texture->target); >>> set_vertex_shader(ctx); >>> cso_set_tessctrl_shader_handle(ctx->cso, NULL); >>> diff --git a/src/gallium/auxiliary/util/u_blitter.c >>> b/src/gallium/auxiliary/util/u_blitter.c >>> index 16bf90f..27e0d10 100644 >>> --- a/src/gallium/auxiliary/util/u_blitter.c >>> +++ b/src/gallium/auxiliary/util/u_blitter.c >>> @@ -81,6 +81,8 @@ struct blitter_context_priv >>> /* FS which outputs a color from a texture, >>> where the index is PIPE_TEXTURE_* to be sampled. */ >>> void *fs_texfetch_col[PIPE_MAX_TEXTURE_TYPES]; >>> + void *fs_texfetch_col_uint[PIPE_MAX_TEXTURE_TYPES]; >>> + void *fs_texfetch_col_sint[PIPE_MAX_TEXTURE_TYPES]; >>> >>> /* FS which outputs a depth from a texture, >>> where the index is PIPE_TEXTURE_* to be sampled. */ >>> @@ -90,6 +92,8 @@ struct blitter_context_priv >>> >>> /* FS which outputs one sample from a multisample texture. */ >>> void *fs_texfetch_col_msaa[PIPE_MAX_TEXTURE_TYPES]; >>> + void *fs_texfetch_col_msaa_uint[PIPE_MAX_TEXTURE_TYPES]; >>> + void *fs_texfetch_col_msaa_sint[PIPE_MAX_TEXTURE_TYPES]; >>> void *fs_texfetch_depth_msaa[PIPE_MAX_TEXTURE_TYPES]; >>> void *fs_texfetch_depthstencil_msaa[PIPE_MAX_TEXTURE_TYPES]; >>> void *fs_texfetch_stencil_msaa[PIPE_MAX_TEXTURE_TYPES]; >>> @@ -438,6 +442,10 @@ void util_blitter_destroy(struct blitter_context >>> *blitter) >>> for (i = 0; i < PIPE_MAX_TEXTURE_TYPES; i++) { >>> if (ctx->fs_texfetch_col[i]) >>> ctx->delete_fs_state(pipe, ctx->fs_texfetch_col[i]); >>> + if (ctx->fs_texfetch_col_sint[i]) >>> + ctx->delete_fs_state(pipe, ctx->fs_texfetch_col_sint[i]); >>> + if (ctx->fs_texfetch_col_uint[i]) >>> + ctx->delete_fs_state(pipe, ctx->fs_texfetch_col_uint[i]); >>> if (ctx->fs_texfetch_depth[i]) >>> ctx->delete_fs_state(pipe, ctx->fs_texfetch_depth[i]); >>> if (ctx->fs_texfetch_depthstencil[i]) >>> @@ -447,6 +455,10 @@ void util_blitter_destroy(struct blitter_context >>> *blitter) >>> >>> if (ctx->fs_texfetch_col_msaa[i]) >>> ctx->delete_fs_state(pipe, ctx->fs_texfetch_col_msaa[i]); >>> + if (ctx->fs_texfetch_col_msaa_sint[i]) >>> + ctx->delete_fs_state(pipe, ctx->fs_texfetch_col_msaa_sint[i]); >>> + if (ctx->fs_texfetch_col_msaa_uint[i]) >>> + ctx->delete_fs_state(pipe, ctx->fs_texfetch_col_msaa_uint[i]); >>> if (ctx->fs_texfetch_depth_msaa[i]) >>> ctx->delete_fs_state(pipe, ctx->fs_texfetch_depth_msaa[i]); >>> if (ctx->fs_texfetch_depthstencil_msaa[i]) >>> @@ -844,20 +856,20 @@ static void *blitter_get_fs_texfetch_col(struct >>> blitter_context_priv *ctx, >>> { >>> struct pipe_context *pipe = ctx->base.pipe; >>> unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, src_nr_samples); >>> + boolean is_uint, is_sint; >>> >>> assert(target < PIPE_MAX_TEXTURE_TYPES); >>> >>> + is_uint = util_format_is_pure_uint(format); >>> + is_sint = util_format_is_pure_sint(format); >>> + >>> if (src_nr_samples > 1) { >>> void **shader; >>> >>> if (dst_nr_samples <= 1) { >>> /* The destination has one sample, so we'll do color resolve. */ >>> - boolean is_uint, is_sint; >>> unsigned index = GET_MSAA_RESOLVE_FS_IDX(src_nr_samples); >>> >>> - is_uint = util_format_is_pure_uint(format); >>> - is_sint = util_format_is_pure_sint(format); >>> - >>> assert(filter < 2); >>> >>> if (is_uint) >>> @@ -885,24 +897,38 @@ static void *blitter_get_fs_texfetch_col(struct >>> blitter_context_priv *ctx, >>> /* The destination has multiple samples, we'll do >>> * an MSAA->MSAA copy. >>> */ >>> - shader = &ctx->fs_texfetch_col_msaa[target]; >>> + if (is_uint) >>> + shader = &ctx->fs_texfetch_col_msaa_uint[target]; >>> + else if (is_sint) >>> + shader = &ctx->fs_texfetch_col_msaa_sint[target]; >>> + else >>> + shader = &ctx->fs_texfetch_col_msaa[target]; >>> >>> /* Create the fragment shader on-demand. */ >>> if (!*shader) { >>> assert(!ctx->cached_all_shaders); >>> - *shader = util_make_fs_blit_msaa_color(pipe, tgsi_tex); >>> + *shader = util_make_fs_blit_msaa_color(pipe, tgsi_tex, >>> + is_uint, is_sint); >>> } >>> } >>> >>> return *shader; >>> } else { >>> - void **shader = &ctx->fs_texfetch_col[target]; >>> + void **shader; >>> + >>> + if (is_uint) >>> + shader = &ctx->fs_texfetch_col_uint[target]; >>> + else if (is_sint) >>> + shader = &ctx->fs_texfetch_col_sint[target]; >>> + else >>> + shader = &ctx->fs_texfetch_col[target]; >>> >>> /* Create the fragment shader on-demand. */ >>> if (!*shader) { >>> assert(!ctx->cached_all_shaders); >>> *shader = util_make_fragment_tex_shader(pipe, tgsi_tex, >>> - TGSI_INTERPOLATE_LINEAR); >>> + TGSI_INTERPOLATE_LINEAR, >>> + is_uint, is_sint); >>> } >>> >>> return *shader; >>> diff --git a/src/gallium/auxiliary/util/u_simple_shaders.c >>> b/src/gallium/auxiliary/util/u_simple_shaders.c >>> index c612b67..8b6b8a6 100644 >>> --- a/src/gallium/auxiliary/util/u_simple_shaders.c >>> +++ b/src/gallium/auxiliary/util/u_simple_shaders.c >>> @@ -201,6 +201,27 @@ void *util_make_layered_clear_geometry_shader(struct >>> pipe_context *pipe) >>> return pipe->create_gs_state(pipe, &state); >>> } >>> >>> +static struct ureg_src >>> +decl_sampler_view(struct ureg_program *ureg, >>> + unsigned nr, >>> + unsigned target, >>> + boolean is_uint, >>> + boolean is_sint) >>> +{ >>> + unsigned type; >>> + >>> + assert(!(is_uint && is_sint)); >>> + >>> + if (is_uint) >>> + type = TGSI_RETURN_TYPE_UINT; >>> + else if (is_sint) >>> + type = TGSI_RETURN_TYPE_SINT; >>> + else >>> + type = TGSI_RETURN_TYPE_FLOAT; >>> + >>> + return ureg_DECL_sampler_view(ureg, nr, target, type, type, type, type); >>> +} >>> + >>> /** >>> * Make simple fragment texture shader: >>> * IMM {0,0,0,1} // (if writemask != 0xf) >>> @@ -216,7 +237,9 @@ void * >>> util_make_fragment_tex_shader_writemask(struct pipe_context *pipe, >>> unsigned tex_target, >>> unsigned interp_mode, >>> - unsigned writemask ) >>> + unsigned writemask, >>> + boolean is_uint, >>> + boolean is_sint) >>> { >>> struct ureg_program *ureg; >>> struct ureg_src sampler; >>> @@ -232,6 +255,8 @@ util_make_fragment_tex_shader_writemask(struct >>> pipe_context *pipe, >>> >>> sampler = ureg_DECL_sampler( ureg, 0 ); >>> >>> + decl_sampler_view(ureg, 0, tex_target, is_uint, is_sint); >>> + >>> tex = ureg_DECL_fs_input( ureg, >>> TGSI_SEMANTIC_GENERIC, 0, >>> interp_mode ); >>> @@ -268,12 +293,16 @@ util_make_fragment_tex_shader_writemask(struct >>> pipe_context *pipe, >>> */ >>> void * >>> util_make_fragment_tex_shader(struct pipe_context *pipe, unsigned >>> tex_target, >>> - unsigned interp_mode) >>> + unsigned interp_mode, >>> + boolean is_uint, >>> + boolean is_sint) >>> { >>> return util_make_fragment_tex_shader_writemask( pipe, >>> tex_target, >>> interp_mode, >>> - TGSI_WRITEMASK_XYZW ); >>> + TGSI_WRITEMASK_XYZW, >>> + is_uint, >>> + is_sint ); >>> } >>> >>> >>> @@ -298,6 +327,8 @@ util_make_fragment_tex_shader_writedepth(struct >>> pipe_context *pipe, >>> >>> sampler = ureg_DECL_sampler( ureg, 0 ); >>> >>> + decl_sampler_view(ureg, 0, tex_target, FALSE, FALSE); >>> + >>> tex = ureg_DECL_fs_input( ureg, >>> TGSI_SEMANTIC_GENERIC, 0, >>> interp_mode ); >>> @@ -343,7 +374,9 @@ util_make_fragment_tex_shader_writedepthstencil(struct >>> pipe_context *pipe, >>> return NULL; >>> >>> depth_sampler = ureg_DECL_sampler( ureg, 0 ); >>> + decl_sampler_view(ureg, 0, tex_target, FALSE, FALSE); >>> stencil_sampler = ureg_DECL_sampler( ureg, 1 ); >>> + decl_sampler_view(ureg, 1, tex_target, TRUE, FALSE); >>> >>> tex = ureg_DECL_fs_input( ureg, >>> TGSI_SEMANTIC_GENERIC, 0, >>> @@ -398,6 +431,8 @@ util_make_fragment_tex_shader_writestencil(struct >>> pipe_context *pipe, >>> >>> stencil_sampler = ureg_DECL_sampler( ureg, 0 ); >>> >>> + decl_sampler_view(ureg, 0, tex_target, TRUE, FALSE); >>> + >>> tex = ureg_DECL_fs_input( ureg, >>> TGSI_SEMANTIC_GENERIC, 0, >>> interp_mode ); >>> @@ -512,6 +547,7 @@ util_make_fragment_cloneinput_shader(struct >>> pipe_context *pipe, int num_cbufs, >>> static void * >>> util_make_fs_blit_msaa_gen(struct pipe_context *pipe, >>> unsigned tgsi_tex, >>> + const char *samp_type, >>> const char *output_semantic, >>> const char *output_mask) >>> { >>> @@ -519,6 +555,7 @@ util_make_fs_blit_msaa_gen(struct pipe_context *pipe, >>> "FRAG\n" >>> "DCL IN[0], GENERIC[0], LINEAR\n" >>> "DCL SAMP[0]\n" >>> + "DCL SVIEW[0], %s, %s\n" >>> "DCL OUT[0], %s\n" >>> "DCL TEMP[0]\n" >>> >>> @@ -534,7 +571,8 @@ util_make_fs_blit_msaa_gen(struct pipe_context *pipe, >>> assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA || >>> tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA); >>> >>> - sprintf(text, shader_templ, output_semantic, output_mask, type); >>> + sprintf(text, shader_templ, type, samp_type, >>> + output_semantic, output_mask, type); >>> >>> if (!tgsi_text_translate(text, tokens, Elements(tokens))) { >>> puts(text); >>> @@ -556,9 +594,22 @@ util_make_fs_blit_msaa_gen(struct pipe_context *pipe, >>> */ >>> void * >>> util_make_fs_blit_msaa_color(struct pipe_context *pipe, >>> - unsigned tgsi_tex) >>> + unsigned tgsi_tex, >>> + boolean is_uint, >>> + boolean is_sint) >>> { >>> - return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, >>> + const char *samp_type; >>> + >>> + assert(!(is_uint && is_sint)); >>> + >>> + if (is_uint) >>> + samp_type = "UINT"; >>> + else if (is_sint) >>> + samp_type = "SINT"; >>> + else >>> + samp_type = "FLOAT"; >>> + >>> + return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, samp_type, >>> "COLOR[0]", ""); >>> } >>> >>> @@ -572,7 +623,7 @@ void * >>> util_make_fs_blit_msaa_depth(struct pipe_context *pipe, >>> unsigned tgsi_tex) >>> { >>> - return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, >>> + return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, "FLOAT", >>> "POSITION", ".z"); >>> } >>> >>> @@ -586,7 +637,7 @@ void * >>> util_make_fs_blit_msaa_stencil(struct pipe_context *pipe, >>> unsigned tgsi_tex) >>> { >>> - return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, >>> + return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, "UINT", >>> "STENCIL", ".y"); >>> } >>> >>> @@ -653,6 +704,7 @@ util_make_fs_msaa_resolve(struct pipe_context *pipe, >>> >>> /* Declarations. */ >>> sampler = ureg_DECL_sampler(ureg, 0); >>> + decl_sampler_view(ureg, 0, tgsi_tex, is_uint, is_sint); >>> coord = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, 0, >>> TGSI_INTERPOLATE_LINEAR); >>> out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); >>> @@ -713,6 +765,7 @@ util_make_fs_msaa_resolve_bilinear(struct pipe_context >>> *pipe, >>> >>> /* Declarations. */ >>> sampler = ureg_DECL_sampler(ureg, 0); >>> + decl_sampler_view(ureg, 0, tgsi_tex, is_uint, is_sint); >>> coord = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, 0, >>> TGSI_INTERPOLATE_LINEAR); >>> out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); >>> diff --git a/src/gallium/auxiliary/util/u_simple_shaders.h >>> b/src/gallium/auxiliary/util/u_simple_shaders.h >>> index dd282e0..89cb3570 100644 >>> --- a/src/gallium/auxiliary/util/u_simple_shaders.h >>> +++ b/src/gallium/auxiliary/util/u_simple_shaders.h >>> @@ -68,15 +68,18 @@ extern void * >>> util_make_layered_clear_geometry_shader(struct pipe_context *pipe); >>> >>> extern void * >>> -util_make_fragment_tex_shader_writemask(struct pipe_context *pipe, >>> +util_make_fragment_tex_shader_writemask(struct pipe_context *pipe, >>> unsigned tex_target, >>> unsigned interp_mode, >>> - unsigned writemask); >>> + unsigned writemask, >>> + boolean is_uint, >>> + boolean is_sint); >>> >>> extern void * >>> util_make_fragment_tex_shader(struct pipe_context *pipe, unsigned >>> tex_target, >>> - unsigned interp_mode); >>> - >>> + unsigned interp_mode, >>> + boolean is_uint, >>> + boolean is_sint); >>> >>> extern void * >>> util_make_fragment_tex_shader_writedepth(struct pipe_context *pipe, >>> @@ -115,7 +118,9 @@ util_make_fragment_cloneinput_shader(struct >>> pipe_context *pipe, int num_cbufs, >>> >>> extern void * >>> util_make_fs_blit_msaa_color(struct pipe_context *pipe, >>> - unsigned tgsi_tex); >>> + unsigned tgsi_tex, >>> + boolean is_uint, >>> + boolean is_sint); >>> >>> >>> extern void * >>> diff --git a/src/gallium/auxiliary/util/u_tests.c >>> b/src/gallium/auxiliary/util/u_tests.c >>> index fe54972..e30ae55 100644 >>> --- a/src/gallium/auxiliary/util/u_tests.c >>> +++ b/src/gallium/auxiliary/util/u_tests.c >>> @@ -373,7 +373,8 @@ null_sampler_view(struct pipe_context *ctx, unsigned >>> tgsi_tex_target) >>> >>> /* Fragment shader. */ >>> fs = util_make_fragment_tex_shader(ctx, tgsi_tex_target, >>> - TGSI_INTERPOLATE_LINEAR); >>> + TGSI_INTERPOLATE_LINEAR, >>> + FALSE, FALSE); >>> cso_set_fragment_shader_handle(cso, fs); >>> >>> /* Vertex shader. */ >>> diff --git a/src/gallium/tests/trivial/quad-tex.c >>> b/src/gallium/tests/trivial/quad-tex.c >>> index abecedb..946dbec 100644 >>> --- a/src/gallium/tests/trivial/quad-tex.c >>> +++ b/src/gallium/tests/trivial/quad-tex.c >>> @@ -270,7 +270,7 @@ static void init_prog(struct program *p) >>> } >>> >>> /* fragment shader */ >>> - p->fs = util_make_fragment_tex_shader(p->pipe, TGSI_TEXTURE_2D, >>> TGSI_INTERPOLATE_LINEAR); >>> + p->fs = util_make_fragment_tex_shader(p->pipe, TGSI_TEXTURE_2D, >>> TGSI_INTERPOLATE_LINEAR, FALSE, FALSE); >>> } >>> >>> static void close_prog(struct program *p) >>> >> _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev