[Mesa-dev] [PATCH 1/2] _mesa_meta_GenerateMipmap: Support all texture targets by generating shaders at runtime
Anuj Phogat
anuj.phogat at gmail.com
Tue Sep 4 19:42:20 PDT 2012
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.phogat at 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"
+ "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);
+
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);
+
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);
--
1.7.7.6
More information about the mesa-dev
mailing list