[Mesa-dev] [PATCH 1/2] _mesa_meta_GenerateMipmap: Support all texture targets by generating shaders at runtime
Brian Paul
brianp at vmware.com
Wed Sep 12 06:25:39 PDT 2012
On 09/11/2012 07:27 PM, Anuj Phogat wrote:
> glsl path of _mesa_meta_GenerateMipmap() function would require different fragment
> shaders depending on the texture target. This patch adds the code to generate
> appropriate fragment shader programs at run time.
> Fixes https://bugs.freedesktop.org/show_bug.cgi?id=54296
>
> V2: Removed the code for integer textures as ARB is planning to
> disallow automatic mipmap generation for integer textures.
> Now using ralloc_asprintf in setup_glsl_generate_mipmap().
>
> NOTE: This is a candidate for stable branches.
>
> Signed-off-by: Anuj Phogat<anuj.phogat at gmail.com>
> ---
> src/mesa/drivers/common/meta.c | 75 ++++++++++++++++++++++++++++++++++++---
> src/mesa/drivers/common/meta.h | 2 +
> 2 files changed, 71 insertions(+), 6 deletions(-)
>
> diff --git a/src/mesa/drivers/common/meta.c b/src/mesa/drivers/common/meta.c
> index 7e81e5e..16110c5 100644
> --- a/src/mesa/drivers/common/meta.c
> +++ b/src/mesa/drivers/common/meta.c
> @@ -76,6 +76,7 @@
> #include "drivers/common/meta.h"
> #include "main/enums.h"
> #include "main/glformats.h"
> +#include "../glsl/ralloc.h"
>
>
> /** Return offset in bytes of the field within a vertex struct */
> @@ -286,6 +287,15 @@ struct gen_mipmap_state
> GLuint IntegerShaderProg;
> };
>
> +/**
> + * State for GLSL texture sampler which is used to generate fragment
> + * shader in _mesa_meta_generate_mipmap().
> + */
> +struct glsl_sampler {
> + const char *type;
> + const char *func;
> + const char *texcoords;
> +};
>
> /**
> * State for texture decompression
> @@ -2974,7 +2984,7 @@ setup_texture_coords(GLenum faceTarget,
>
> static void
> setup_ff_generate_mipmap(struct gl_context *ctx,
> - struct gen_mipmap_state *mipmap)
> + struct gen_mipmap_state *mipmap)
> {
> struct vertex {
> GLfloat x, y, tex[3];
> @@ -3004,12 +3014,55 @@ setup_ff_generate_mipmap(struct gl_context *ctx,
>
>
> static void
> +setup_texture_sampler(GLenum target, struct glsl_sampler *sampler)
> +{
> + switch(target) {
> + case GL_TEXTURE_1D:
> + sampler->type = "sampler1D";
> + sampler->func = "texture1D";
> + sampler->texcoords = "texCoords.x";
> + break;
> + case GL_TEXTURE_2D:
> + sampler->type = "sampler2D";
> + sampler->func = "texture2D";
> + sampler->texcoords = "texCoords.xy";
> + break;
> + case GL_TEXTURE_3D:
> + sampler->type = "sampler3D";
> + sampler->func = "texture3D";
> + sampler->texcoords = "texCoords";
> + break;
> + case GL_TEXTURE_CUBE_MAP:
> + sampler->type = "samplerCube";
> + sampler->func = "textureCube";
> + sampler->texcoords = "texCoords";
> + break;
> + case GL_TEXTURE_1D_ARRAY:
> + sampler->type = "sampler1DArray";
> + sampler->func = "texture1DArray";
> + sampler->texcoords = "texCoords.xy";
> + break;
> + case GL_TEXTURE_2D_ARRAY:
> + sampler->type = "sampler2DArray";
> + sampler->func = "texture2DArray";
> + sampler->texcoords = "texCoords";
> + break;
> + default:
> + /* unexpected texture target */
There should probably be an assertion or _mesa_problem() call here.
> + return;
> + }
> +}
> +
> +
> +static void
> setup_glsl_generate_mipmap(struct gl_context *ctx,
> - struct gen_mipmap_state *mipmap)
> + struct gen_mipmap_state *mipmap,
> + GLenum target)
> {
> struct vertex {
> GLfloat x, y, tex[3];
> };
> + struct glsl_sampler sampler;
>
> static const char *vs_source =
> "attribute vec2 position;\n"
> @@ -3020,12 +3073,12 @@ setup_glsl_generate_mipmap(struct gl_context *ctx,
> " texCoords = textureCoords;\n"
> " gl_Position = vec4(position, 0.0, 1.0);\n"
> "}\n";
> - static const char *fs_source =
> - "uniform sampler2D tex2d;\n"
> + static const char *fs_template =
> + "uniform %s texSampler;\n"
> "varying vec3 texCoords;\n"
> "void main()\n"
> "{\n"
> - " gl_FragColor = texture2D(tex2d, texCoords.xy);\n"
> + " gl_FragColor = %s(texSampler, %s);\n"
> "}\n";
>
> static const char *vs_int_source =
> @@ -3048,6 +3101,7 @@ setup_glsl_generate_mipmap(struct gl_context *ctx,
> "{\n"
> " out_color = texture(tex2d, texCoords.xy);\n"
> "}\n";
> + char *fs_source;
> GLuint vs, fs;
>
> /* Check if already initialized */
> @@ -3067,6 +3121,14 @@ setup_glsl_generate_mipmap(struct gl_context *ctx,
> _mesa_VertexAttribPointerARB(1, 3, GL_FLOAT, GL_FALSE,
> sizeof(struct vertex), OFFSET(tex));
>
> + /* Generate a fragment shader program appropriate for the texture target */
> + setup_texture_sampler(target,&sampler);
> + mem_ctx = ralloc_context(NULL);
> +
> + fs_source = ralloc_asprintf(mem_ctx, fs_template,
> + sampler.type, sampler.func,
> + sampler.texcoords);
> +
> vs = compile_shader_with_debug(ctx, GL_VERTEX_SHADER, vs_source);
> fs = compile_shader_with_debug(ctx, GL_FRAGMENT_SHADER, fs_source);
>
> @@ -3080,6 +3142,7 @@ setup_glsl_generate_mipmap(struct gl_context *ctx,
> _mesa_EnableVertexAttribArrayARB(0);
> _mesa_EnableVertexAttribArrayARB(1);
> link_program_with_debug(ctx, mipmap->ShaderProg);
> + ralloc_free(mem_ctx);
>
> if ((_mesa_is_desktop_gl(ctx)&& ctx->Const.GLSLVersion>= 130) ||
> _mesa_is_gles3(ctx)){
> @@ -3172,7 +3235,7 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
> * GenerateMipmap function.
> */
> if (use_glsl_version) {
> - setup_glsl_generate_mipmap(ctx, mipmap);
> + setup_glsl_generate_mipmap(ctx, mipmap, target);
>
> if (texObj->_IsIntegerFormat)
> _mesa_UseProgramObjectARB(mipmap->IntegerShaderProg);
> diff --git a/src/mesa/drivers/common/meta.h b/src/mesa/drivers/common/meta.h
> index d8dfb56..8a6b33b 100644
> --- a/src/mesa/drivers/common/meta.h
> +++ b/src/mesa/drivers/common/meta.h
> @@ -58,6 +58,8 @@
> #define MESA_META_MULTISAMPLE 0x100000
> /**\}*/
>
> +void *mem_ctx;
> +
> extern void
> _mesa_meta_init(struct gl_context *ctx);
>
I'm not too familiar with the ralloc stuff so you might want to get
Ian to double-check that. Otherwise, looks OK to me.
Reviewed-by: Brian Paul <brianp at vmware.com>
More information about the mesa-dev
mailing list