From: Anuj Phogat Date: Fri, 31 Aug 2012 20:51:39 +0000 (-0700) Subject: _mesa_meta_GenerateMipmap: Support all texture targets by generating shaders at runtime X-Git-Tag: accepted/2.0alpha-wayland/20121114.171706~38 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ad4b3b93ded960c22388c7bc3ba14d32b30b8f1d;p=profile%2Fivi%2Fmesa.git _mesa_meta_GenerateMipmap: Support all texture targets by generating shaders at runtime This is a squash for the following 7 commits. The first introduces the functionality, and the remaining six fix various bugs. Patch 1: _mesa_meta_GenerateMipmap: Support all texture targets by generating shaders at runtime 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 Reviewed-by: Brian Paul (cherry picked from commit 299acac849eb8506de9760c94c6e8e8b1046d909) Patch 2: _mesa_meta_GenerateMipmap: Generate separate shaders for glsl 120 / 130 glsl version of _mesa_meta_GenerateMipmap() would require separate shaders for glsl 120 and 130. V2: Removed the code for integer textures as ARB is planning to disallow automatic mipmap generation for integer textures. NOTE: This is a candidate for stable branches. Signed-off-by: Anuj Phogat Reviewed-by: Brian Paul (cherry picked from commit 15bf3103b48a5928321fe56fbb3ed28a0f314418) Patch 3: meta: Add on demand compilation of per target shader programs A call to glGenerateMipmap() follows the generation of a relevant shader program in setup_glsl_generate_mipmap(). To support all texture targets and to avoid compiling shaders everytime, per target shader programs are compiled on demand and saved for the next call. Fixes float-texture(mipmap.manual): See Comment 6: https://bugs.freedesktop.org/show_bug.cgi?id=54296 NOTE: This is a candidate for stable branches. Signed-off-by: Anuj Phogat Reviewed-by: Brian Paul (cherry picked from commit eb1d87fb945783448cc40ad43c9cd4d98002d424) Patch 4: meta: make mem_ctx non-global. I can't see any external users, and this is a global symbol, Reviewed-by: Matt Turner Signed-off-by: Dave Airlie (cherry picked from commit 36639ec6e9a2758e344235fbdc1450719d8851e3) Patch 5: meta: Remove unsafe global mem_ctx pointer NOTE: This is a candidate for the 9.0 branch. Signed-off-by: Ian Romanick Reviewed-by: Kenneth Graunke Reviewed-by: Brian Paul Reviewed-by: Anuj Phogat (cherry picked from commit ab097dde0c958dd8b1c06a07ef8913512753760c) Patch 6: meta: Rearrange shader creation in setup_glsl_generate_mipmap The diff looks weird, but this moves the code from the first 'if (ctx->Const.GLSLVersion < 130)' block down into the second block. It also moves some variable decalarations closer to their use. NOTE: This is a candidate for the 9.0 branch. Signed-off-by: Ian Romanick Reviewed-by: Kenneth Graunke Reviewed-by: Brian Paul Reviewed-by: Anuj Phogat (cherry picked from commit 3308c079bd00e9b9aa546f5214ce197a904d059b) Patch 7: meta: Don't use GLSL 1.30 shader on OpenGL ES 2 Fixes GLES2 CoverageGL conformance test. NOTE: This is a candidate for the 9.0 branch. Signed-off-by: Ian Romanick Reviewed-by: Kenneth Graunke Reviewed-by: Brian Paul Reviewed-by: Anuj Phogat (cherry picked from commit 0242381f06edb09dcf0eaacd6d26ccd8584700cc) --- diff --git a/src/mesa/drivers/common/meta.c b/src/mesa/drivers/common/meta.c index fe452cf..5f0b478 100644 --- a/src/mesa/drivers/common/meta.c +++ b/src/mesa/drivers/common/meta.c @@ -76,7 +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 */ #define OFFSET(FIELD) ((void *) offsetof(struct vertex, FIELD)) @@ -272,6 +272,16 @@ struct bitmap_state struct temp_texture Tex; /**< separate texture from other meta ops */ }; +/** + * 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; + GLuint shader_prog; +}; /** * State for _mesa_meta_generate_mipmap() @@ -284,9 +294,14 @@ struct gen_mipmap_state GLuint Sampler; GLuint ShaderProg; GLuint IntegerShaderProg; + struct glsl_sampler sampler_1d; + struct glsl_sampler sampler_2d; + struct glsl_sampler sampler_3d; + struct glsl_sampler sampler_cubemap; + struct glsl_sampler sampler_1d_array; + struct glsl_sampler sampler_2d_array; }; - /** * State for texture decompression */ @@ -2979,7 +2994,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]; @@ -3008,31 +3023,62 @@ setup_ff_generate_mipmap(struct gl_context *ctx, } +static struct glsl_sampler * +setup_texture_sampler(GLenum target, struct gen_mipmap_state *mipmap) +{ + switch(target) { + case GL_TEXTURE_1D: + mipmap->sampler_1d.type = "sampler1D"; + mipmap->sampler_1d.func = "texture1D"; + mipmap->sampler_1d.texcoords = "texCoords.x"; + return &mipmap->sampler_1d; + case GL_TEXTURE_2D: + mipmap->sampler_2d.type = "sampler2D"; + mipmap->sampler_2d.func = "texture2D"; + mipmap->sampler_2d.texcoords = "texCoords.xy"; + return &mipmap->sampler_2d; + case GL_TEXTURE_3D: + /* Code for mipmap generation with 3D textures is not used yet. + * It's a sw fallback. + */ + mipmap->sampler_3d.type = "sampler3D"; + mipmap->sampler_3d.func = "texture3D"; + mipmap->sampler_3d.texcoords = "texCoords"; + return &mipmap->sampler_3d; + case GL_TEXTURE_CUBE_MAP: + mipmap->sampler_cubemap.type = "samplerCube"; + mipmap->sampler_cubemap.func = "textureCube"; + mipmap->sampler_cubemap.texcoords = "texCoords"; + return &mipmap->sampler_cubemap; + case GL_TEXTURE_1D_ARRAY: + mipmap->sampler_1d_array.type = "sampler1DArray"; + mipmap->sampler_1d_array.func = "texture1DArray"; + mipmap->sampler_1d_array.texcoords = "texCoords.xy"; + return &mipmap->sampler_1d_array; + case GL_TEXTURE_2D_ARRAY: + mipmap->sampler_2d_array.type = "sampler2DArray"; + mipmap->sampler_2d_array.func = "texture2DArray"; + mipmap->sampler_2d_array.texcoords = "texCoords"; + return &mipmap->sampler_2d_array; + default: + _mesa_problem(NULL, "Unexpected texture target 0x%x in" + " setup_texture_sampler()\n", target); + return NULL; + } +} + + 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; + const char *vs_source; - static const char *vs_source = - "attribute vec2 position;\n" - "attribute vec3 textureCoords;\n" - "varying vec3 texCoords;\n" - "void main()\n" - "{\n" - " texCoords = textureCoords;\n" - " gl_Position = vec4(position, 0.0, 1.0);\n" - "}\n"; - static const char *fs_source = - "uniform sampler2D tex2d;\n" - "varying vec3 texCoords;\n" - "void main()\n" - "{\n" - " gl_FragColor = texture2D(tex2d, texCoords.xy);\n" - "}\n"; - static const char *vs_int_source = "#version 130\n" "in vec2 position;\n" @@ -3053,24 +3099,96 @@ setup_glsl_generate_mipmap(struct gl_context *ctx, "{\n" " out_color = texture(tex2d, texCoords.xy);\n" "}\n"; + char *fs_source; GLuint vs, fs; + void *mem_ctx; /* Check if already initialized */ - if (mipmap->ArrayObj != 0) - return; - /* create vertex array object */ - _mesa_GenVertexArrays(1, &mipmap->ArrayObj); - _mesa_BindVertexArray(mipmap->ArrayObj); + if (mipmap->ArrayObj == 0) { - /* create vertex array buffer */ - _mesa_GenBuffersARB(1, &mipmap->VBO); - _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, mipmap->VBO); + /* create vertex array object */ + _mesa_GenVertexArrays(1, &mipmap->ArrayObj); + _mesa_BindVertexArray(mipmap->ArrayObj); - /* setup vertex arrays */ - _mesa_VertexAttribPointerARB(0, 2, GL_FLOAT, GL_FALSE, - sizeof(struct vertex), OFFSET(x)); - _mesa_VertexAttribPointerARB(1, 3, GL_FLOAT, GL_FALSE, - sizeof(struct vertex), OFFSET(tex)); + /* create vertex array buffer */ + _mesa_GenBuffersARB(1, &mipmap->VBO); + _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, mipmap->VBO); + + /* setup vertex arrays */ + _mesa_VertexAttribPointerARB(0, 2, GL_FLOAT, GL_FALSE, + sizeof(struct vertex), OFFSET(x)); + _mesa_VertexAttribPointerARB(1, 3, GL_FLOAT, GL_FALSE, + sizeof(struct vertex), OFFSET(tex)); + } + + /* Generate a fragment shader program appropriate for the texture target */ + sampler = setup_texture_sampler(target, mipmap); + assert(sampler != NULL); + if (sampler->shader_prog != 0) { + mipmap->ShaderProg = sampler->shader_prog; + return; + } + + mem_ctx = ralloc_context(NULL); + + if (ctx->API == API_OPENGLES2 || ctx->Const.GLSLVersion < 130) { + const char *fs_template; + const char *extension_mode; + + vs_source = + "attribute vec2 position;\n" + "attribute vec3 textureCoords;\n" + "varying vec3 texCoords;\n" + "void main()\n" + "{\n" + " texCoords = textureCoords;\n" + " gl_Position = vec4(position, 0.0, 1.0);\n" + "}\n"; + fs_template = + "#extension GL_EXT_texture_array : %s\n" + "uniform %s texSampler;\n" + "varying vec3 texCoords;\n" + "void main()\n" + "{\n" + " gl_FragColor = %s(texSampler, %s);\n" + "}\n"; + + extension_mode = ((target == GL_TEXTURE_1D_ARRAY) || + (target == GL_TEXTURE_2D_ARRAY)) ? + "require" : "disable"; + + fs_source = ralloc_asprintf(mem_ctx, fs_template, + extension_mode, sampler->type, + sampler->func, sampler->texcoords); + } + else { + const char *fs_template; + + vs_source = + "#version 130\n" + "in vec2 position;\n" + "in vec3 textureCoords;\n" + "out vec3 texCoords;\n" + "void main()\n" + "{\n" + " texCoords = textureCoords;\n" + " gl_Position = vec4(position, 0.0, 1.0);\n" + "}\n"; + fs_template = + "#version 130\n" + "uniform %s texSampler;\n" + "in vec3 texCoords;\n" + "out %s out_color;\n" + "\n" + "void main()\n" + "{\n" + " out_color = texture(texSampler, %s);\n" + "}\n"; + + fs_source = ralloc_asprintf(mem_ctx, fs_template, + sampler->type, "vec4", + sampler->texcoords); + } vs = compile_shader_with_debug(ctx, GL_VERTEX_SHADER, vs_source); fs = compile_shader_with_debug(ctx, GL_FRAGMENT_SHADER, fs_source); @@ -3085,6 +3203,8 @@ setup_glsl_generate_mipmap(struct gl_context *ctx, _mesa_EnableVertexAttribArrayARB(0); _mesa_EnableVertexAttribArrayARB(1); link_program_with_debug(ctx, mipmap->ShaderProg); + sampler->shader_prog = mipmap->ShaderProg; + ralloc_free(mem_ctx); if ((_mesa_is_desktop_gl(ctx) && ctx->Const.GLSLVersion >= 130) || _mesa_is_gles3(ctx)){ @@ -3118,8 +3238,20 @@ meta_glsl_generate_mipmap_cleanup(struct gl_context *ctx, mipmap->ArrayObj = 0; _mesa_DeleteBuffersARB(1, &mipmap->VBO); mipmap->VBO = 0; - _mesa_DeleteObjectARB(mipmap->ShaderProg); - mipmap->ShaderProg = 0; + + _mesa_DeleteObjectARB(mipmap->sampler_1d.shader_prog); + _mesa_DeleteObjectARB(mipmap->sampler_2d.shader_prog); + _mesa_DeleteObjectARB(mipmap->sampler_3d.shader_prog); + _mesa_DeleteObjectARB(mipmap->sampler_cubemap.shader_prog); + _mesa_DeleteObjectARB(mipmap->sampler_1d_array.shader_prog); + _mesa_DeleteObjectARB(mipmap->sampler_2d_array.shader_prog); + + mipmap->sampler_1d.shader_prog = 0; + mipmap->sampler_2d.shader_prog = 0; + mipmap->sampler_3d.shader_prog = 0; + mipmap->sampler_cubemap.shader_prog = 0; + mipmap->sampler_1d_array.shader_prog = 0; + mipmap->sampler_2d_array.shader_prog = 0; if (mipmap->IntegerShaderProg) { _mesa_DeleteObjectARB(mipmap->IntegerShaderProg); @@ -3177,7 +3309,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);