On Tue, Sep 11, 2012 at 12:56 AM, Ian Romanick <i...@freedesktop.org> wrote: > On 09/05/2012 05:42 AM, 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 >> >> NOTE: This is a candidate for stable branches. >> >> Signed-off-by: Anuj Phogat <anuj.pho...@gmail.com> >> --- >> src/mesa/drivers/common/meta.c | 100 >> +++++++++++++++++++++++++++++++++++---- >> 1 files changed, 89 insertions(+), 11 deletions(-) >> >> diff --git a/src/mesa/drivers/common/meta.c >> b/src/mesa/drivers/common/meta.c >> index 36672a7..7d701f4 100644 >> --- a/src/mesa/drivers/common/meta.c >> +++ b/src/mesa/drivers/common/meta.c >> @@ -286,6 +286,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 +2983,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 +3013,53 @@ 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->texcoords = "texCoords.xy"; >> + break; >> + case GL_TEXTURE_2D_ARRAY: >> + sampler->type = "sampler2DARRAY"; >> + sampler->texcoords = "texCoords"; >> + break; >> + default: >> + /* unexpected texture target */ >> + 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,14 +3070,17 @@ 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 = >> + "#define SAMPLER_TYPE %s\n" >> + "#define SAMPLER_FUNCTION %s\n" >> + "#define TEX_COORDS %s\n" > > > Since each of these is only used once, why use the extra #defines? I > believe we can use $ to force the arguments to have the same order. > > > static const char *fs_template = > "uniform %1$s texSampler;\n" > > "varying vec3 texCoords;\n" > "void main()\n" > "{\n" > " gl_FragColor = %2$s(texSampler, %3$s);\n" > "}\n"; > > This works like the {0} formatting in Python. > > Brian, do you know if this is supported on Windows? > Never used this before. Good to know this technique. I used #defines for better readability of shader code. We can anyway pass the arguments in order we need them without the need of $.
>> + "uniform SAMPLER_TYPE texSampler;\n" >> "varying vec3 texCoords;\n" >> "void main()\n" >> "{\n" >> - " gl_FragColor = texture2D(tex2d, texCoords.xy);\n" >> + " gl_FragColor = SAMPLER_FUNCTION(texSampler, TEX_COORDS);\n" >> "}\n"; >> - >> + >> static const char *vs_int_source = >> "#version 130\n" >> "in vec2 position;\n" >> @@ -3036,18 +3089,22 @@ setup_glsl_generate_mipmap(struct gl_context *ctx, >> "void main()\n" >> "{\n" >> " texCoords = textureCoords;\n" >> - " gl_Position = gl_Vertex;\n" >> + " gl_Position = vec4(position, 0.0, 1.0);\n" >> "}\n"; >> - static const char *fs_int_source = >> + static const char *fs_int_template = >> "#version 130\n" >> - "uniform isampler2D tex2d;\n" >> + "#define SAMPLER_TYPE i%s\n" >> + "#define TEX_COORDS %s\n" >> + "uniform SAMPLER_TYPE texSampler;\n" >> "in vec3 texCoords;\n" >> "out ivec4 out_color;\n" >> "\n" >> "void main()\n" >> "{\n" >> - " out_color = texture(tex2d, texCoords.xy);\n" >> + " out_color = texture(texSampler, TEX_COORDS);\n" >> "}\n"; >> + char *fs_source, *fs_int_source; >> + unsigned fs_alloc_len; >> GLuint vs, fs; >> >> /* Check if already initialized */ >> @@ -3067,6 +3124,15 @@ 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); >> + fs_alloc_len = strlen(fs_template) + strlen(sampler.type) + >> + strlen(sampler.func) + strlen(sampler.texcoords) + 1; >> + fs_source = (char *) malloc(fs_alloc_len); >> + >> + sprintf(fs_source, fs_template, >> + sampler.type, sampler.func, sampler.texcoords); >> + > > > If we can use ralloc in this code, ralloc_asprintf would make this a lot > better. > > > /* Generate a fragment shader program appropriate for the > * texture target > */ > setup_texture_sampler(target, &sampler); > fs_source = ralloc_asprintf(mem_ctx, fs_template, > sampler.type, sampler.func, sampler.texcoords); > > Right. This looks better. I'll see if it can be used in meta.c >> vs = compile_shader_with_debug(ctx, GL_VERTEX_SHADER, vs_source); >> fs = compile_shader_with_debug(ctx, GL_FRAGMENT_SHADER, fs_source); >> >> @@ -3080,9 +3146,20 @@ setup_glsl_generate_mipmap(struct gl_context *ctx, >> _mesa_EnableVertexAttribArrayARB(0); >> _mesa_EnableVertexAttribArrayARB(1); >> link_program_with_debug(ctx, mipmap->ShaderProg); >> + free(fs_source); >> >> if ((_mesa_is_desktop_gl(ctx) && ctx->Const.GLSLVersion >= 130) || >> _mesa_is_gles3(ctx)){ >> + /* Generate a fragment shader program appropriate for the texture >> + * target >> + */ >> + fs_alloc_len = strlen(fs_int_template) + strlen(sampler.type) + >> + strlen(sampler.texcoords) + 1; >> + fs_int_source = (char *) malloc(fs_alloc_len); >> + >> + sprintf(fs_int_source, fs_int_template, >> + sampler.type, sampler.texcoords); >> + > > > Same here. > > >> vs = compile_shader_with_debug(ctx, GL_VERTEX_SHADER, >> vs_int_source); >> fs = compile_shader_with_debug(ctx, GL_FRAGMENT_SHADER, >> fs_int_source); >> >> @@ -3099,6 +3176,7 @@ setup_glsl_generate_mipmap(struct gl_context *ctx, >> * BindFragDataLocation to 0. >> */ >> link_program_with_debug(ctx, mipmap->IntegerShaderProg); >> + free(fs_int_source); >> } >> } >> >> @@ -3172,7 +3250,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); >> > _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev