Mesa (9.0): _mesa_meta_GenerateMipmap: Support all texture targets by generating shaders at runtime

Ian Romanick idr at kemper.freedesktop.org
Mon Oct 8 03:41:02 UTC 2012


Module: Mesa
Branch: 9.0
Commit: ad4b3b93ded960c22388c7bc3ba14d32b30b8f1d
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=ad4b3b93ded960c22388c7bc3ba14d32b30b8f1d

Author: Anuj Phogat <anuj.phogat at gmail.com>
Date:   Fri Aug 31 13:51:39 2012 -0700

_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 <anuj.phogat at gmail.com>
    Reviewed-by: Brian Paul <brianp at vmware.com>
    (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 <anuj.phogat at gmail.com>
    Reviewed-by: Brian Paul <brianp at vmware.com>
    (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 <anuj.phogat at gmail.com>
    Reviewed-by: Brian Paul <brianp at vmware.com>
    (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 <mattst88 at gmail.com>
    Signed-off-by: Dave Airlie <airlied at redhat.com>
    (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 <ian.d.romanick at intel.com>
    Reviewed-by: Kenneth Graunke <kenneth at whitecape.org>
    Reviewed-by: Brian Paul <brianp at vmware.com>
    Reviewed-by: Anuj Phogat <anuj.phogat at gmail.com>
    (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 <ian.d.romanick at intel.com>
    Reviewed-by: Kenneth Graunke <kenneth at whitecape.org>
    Reviewed-by: Brian Paul <brianp at vmware.com>
    Reviewed-by: Anuj Phogat <anuj.phogat at gmail.com>
    (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 <ian.d.romanick at intel.com>
    Reviewed-by: Kenneth Graunke <kenneth at whitecape.org>
    Reviewed-by: Brian Paul <brianp at vmware.com>
    Reviewed-by: Anuj Phogat <anuj.phogat at gmail.com>
    (cherry picked from commit 0242381f06edb09dcf0eaacd6d26ccd8584700cc)

---

 src/mesa/drivers/common/meta.c |  206 ++++++++++++++++++++++++++++++++-------
 1 files changed, 169 insertions(+), 37 deletions(-)

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);




More information about the mesa-commit mailing list